rememberstack 0.1.0__py3-none-any.whl
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.
- rememberstack/__init__.py +9 -0
- rememberstack/adapters/__init__.py +42 -0
- rememberstack/adapters/codex_writer.py +221 -0
- rememberstack/adapters/markitdown_converter.py +42 -0
- rememberstack/adapters/openrouter.py +136 -0
- rememberstack/adapters/selfhost/__init__.py +54 -0
- rememberstack/adapters/selfhost/forget.py +66 -0
- rememberstack/adapters/selfhost/git.py +374 -0
- rememberstack/adapters/selfhost/lance.py +328 -0
- rememberstack/adapters/selfhost/minio.py +279 -0
- rememberstack/adapters/selfhost/mounts.py +249 -0
- rememberstack/adapters/selfhost/object_store.py +130 -0
- rememberstack/adapters/selfhost/projection.py +80 -0
- rememberstack/adapters/selfhost/queue.py +137 -0
- rememberstack/adapters/selfhost/telemetry.py +45 -0
- rememberstack/adapters/selfhost/watcher.py +70 -0
- rememberstack/adapters/testing/__init__.py +15 -0
- rememberstack/adapters/testing/cost_meter.py +13 -0
- rememberstack/adapters/testing/model_provider.py +83 -0
- rememberstack/adapters/testing/queue.py +43 -0
- rememberstack/adapters/testing/telemetry.py +22 -0
- rememberstack/client.py +19 -0
- rememberstack/core/__init__.py +127 -0
- rememberstack/core/blockizer.py +189 -0
- rememberstack/core/chunker.py +216 -0
- rememberstack/core/consumption_skill.py +275 -0
- rememberstack/core/conversion.py +76 -0
- rememberstack/core/core_manifest.py +598 -0
- rememberstack/core/extension_packs.py +124 -0
- rememberstack/core/forget.py +17 -0
- rememberstack/core/knowledge_authored.py +276 -0
- rememberstack/core/knowledge_compile.py +215 -0
- rememberstack/core/knowledge_fact_sheet.py +210 -0
- rememberstack/core/knowledge_hashing.py +68 -0
- rememberstack/core/knowledge_planner.py +64 -0
- rememberstack/core/knowledge_writer.py +175 -0
- rememberstack/core/ranking.py +200 -0
- rememberstack/core/recipe_linter.py +149 -0
- rememberstack/core/section_snap.py +209 -0
- rememberstack/core/storage_routing.py +27 -0
- rememberstack/eval/__init__.py +53 -0
- rememberstack/eval/consumption.py +141 -0
- rememberstack/eval/contradiction.py +184 -0
- rememberstack/eval/harness.py +136 -0
- rememberstack/eval/lifecycle.py +400 -0
- rememberstack/eval/operational_scale.py +49 -0
- rememberstack/eval/resolution.py +255 -0
- rememberstack/eval/retrieval_spikes.py +50 -0
- rememberstack/eval/skeleton.py +231 -0
- rememberstack/llm/__init__.py +1 -0
- rememberstack/model/__init__.py +589 -0
- rememberstack/model/adjudication.py +100 -0
- rememberstack/model/auth.py +27 -0
- rememberstack/model/blocks.py +30 -0
- rememberstack/model/chunks.py +190 -0
- rememberstack/model/claims.py +162 -0
- rememberstack/model/client.py +98 -0
- rememberstack/model/clustering.py +54 -0
- rememberstack/model/component_version.py +124 -0
- rememberstack/model/consumption.py +88 -0
- rememberstack/model/conversion.py +31 -0
- rememberstack/model/deployment.py +53 -0
- rememberstack/model/documents.py +168 -0
- rememberstack/model/envelope.py +513 -0
- rememberstack/model/evaluation.py +72 -0
- rememberstack/model/forget.py +143 -0
- rememberstack/model/git.py +13 -0
- rememberstack/model/knowledge.py +840 -0
- rememberstack/model/knowledge_authored.py +325 -0
- rememberstack/model/knowledge_planner.py +431 -0
- rememberstack/model/lifecycle.py +42 -0
- rememberstack/model/model_provider.py +78 -0
- rememberstack/model/mounts.py +24 -0
- rememberstack/model/object_store.py +21 -0
- rememberstack/model/operational_scale.py +59 -0
- rememberstack/model/operations.py +153 -0
- rememberstack/model/processing.py +228 -0
- rememberstack/model/queue.py +73 -0
- rememberstack/model/recipes.py +83 -0
- rememberstack/model/relations.py +79 -0
- rememberstack/model/resolution.py +83 -0
- rememberstack/model/retrieval_spikes.py +62 -0
- rememberstack/model/sections.py +120 -0
- rememberstack/model/telemetry.py +30 -0
- rememberstack/ports/__init__.py +29 -0
- rememberstack/ports/auth.py +16 -0
- rememberstack/ports/connector.py +23 -0
- rememberstack/ports/cost_meter.py +17 -0
- rememberstack/ports/forget.py +20 -0
- rememberstack/ports/git.py +20 -0
- rememberstack/ports/model_provider.py +28 -0
- rememberstack/ports/mounts.py +16 -0
- rememberstack/ports/object_store.py +27 -0
- rememberstack/ports/p1_index.py +92 -0
- rememberstack/ports/purge.py +93 -0
- rememberstack/ports/queue.py +23 -0
- rememberstack/ports/telemetry.py +21 -0
- rememberstack/profiles/__init__.py +22 -0
- rememberstack/profiles/selfhost.py +324 -0
- rememberstack/profiles/selfhost_forget.py +158 -0
- rememberstack/profiles/selfhost_operations.py +95 -0
- rememberstack/py.typed +1 -0
- rememberstack/spine/__init__.py +93 -0
- rememberstack/spine/admission.py +26 -0
- rememberstack/spine/backfill.py +168 -0
- rememberstack/spine/catalog_contract.py +742 -0
- rememberstack/spine/chunk_catalog.py +237 -0
- rememberstack/spine/claim_catalog.py +298 -0
- rememberstack/spine/clustering.py +740 -0
- rememberstack/spine/component_versions.py +208 -0
- rememberstack/spine/consumption.py +81 -0
- rememberstack/spine/deployment_bootstrap.py +445 -0
- rememberstack/spine/document_catalog.py +621 -0
- rememberstack/spine/entity_registry.py +205 -0
- rememberstack/spine/extension_packs.py +220 -0
- rememberstack/spine/fact_catalog.py +571 -0
- rememberstack/spine/forget.py +1753 -0
- rememberstack/spine/knowledge.py +5467 -0
- rememberstack/spine/lifecycle.py +1071 -0
- rememberstack/spine/migrations/__init__.py +1 -0
- rememberstack/spine/migrations/_helpers.py +153 -0
- rememberstack/spine/migrations/env.py +58 -0
- rememberstack/spine/migrations/script.py.mako +27 -0
- rememberstack/spine/migrations/versions/__init__.py +1 -0
- rememberstack/spine/migrations/versions/p0_02_0001_extensions_enums.py +189 -0
- rememberstack/spine/migrations/versions/p0_02_0002_infrastructure_registries.py +321 -0
- rememberstack/spine/migrations/versions/p0_02_0003_entities_evaluation_e0_e1.py +631 -0
- rememberstack/spine/migrations/versions/p0_02_0004_claims_facts_evidence.py +411 -0
- rememberstack/spine/migrations/versions/p0_02_0005_projection_knowledge_retrieval.py +391 -0
- rememberstack/spine/migrations/versions/p0_02_0006_partitions_views.py +158 -0
- rememberstack/spine/migrations/versions/p2_06_0007_invalidated_outcome.py +26 -0
- rememberstack/spine/migrations/versions/p3_01_0008_document_version_target.py +58 -0
- rememberstack/spine/migrations/versions/p3_05_0009_reconcile_stage.py +27 -0
- rememberstack/spine/migrations/versions/p3_07_0010_lifecycle_eval_suite.py +25 -0
- rememberstack/spine/migrations/versions/p4_01_0011_survivor_view_rewrite.py +57 -0
- rememberstack/spine/migrations/versions/p6_02_0012_knowledge_compile_recovery.py +58 -0
- rememberstack/spine/migrations/versions/p6_04_0013_knowledge_writer_ledger.py +46 -0
- rememberstack/spine/migrations/versions/p6_05_0014_knowledge_planner_runtime.py +217 -0
- rememberstack/spine/migrations/versions/p6_06_0015_authored_dispatch_runtime.py +38 -0
- rememberstack/spine/migrations/versions/p7_02_0016_operational_eval_suite.py +19 -0
- rememberstack/spine/migrations/versions/p7_05_0017_hard_forget.py +55 -0
- rememberstack/spine/observation_adjudication.py +778 -0
- rememberstack/spine/operations.py +298 -0
- rememberstack/spine/projection.py +662 -0
- rememberstack/spine/recipes.py +276 -0
- rememberstack/spine/resolver.py +763 -0
- rememberstack/spine/review.py +650 -0
- rememberstack/spine/settings.py +22 -0
- rememberstack/spine/supersession.py +510 -0
- rememberstack/spine/sync.py +128 -0
- rememberstack/spine/work_ledger.py +816 -0
- rememberstack/surfaces/__init__.py +110 -0
- rememberstack/surfaces/cli.py +447 -0
- rememberstack/surfaces/consumption_skill.py +87 -0
- rememberstack/surfaces/graph_queries.py +698 -0
- rememberstack/surfaces/http_api.py +377 -0
- rememberstack/surfaces/mcp.py +67 -0
- rememberstack/surfaces/query_engine.py +1591 -0
- rememberstack/surfaces/recipe_executor.py +185 -0
- rememberstack/surfaces/recipe_surface.py +219 -0
- rememberstack/surfaces/remote_mcp.py +133 -0
- rememberstack/surfaces/sdk.py +324 -0
- rememberstack/workers/__init__.py +155 -0
- rememberstack/workers/base.py +312 -0
- rememberstack/workers/e0.py +577 -0
- rememberstack/workers/e1.py +425 -0
- rememberstack/workers/e2.py +525 -0
- rememberstack/workers/e3.py +434 -0
- rememberstack/workers/forget.py +299 -0
- rememberstack/workers/knowledge_authored.py +146 -0
- rememberstack/workers/knowledge_driver.py +735 -0
- rememberstack/workers/knowledge_fact_sheet.py +123 -0
- rememberstack/workers/knowledge_planner.py +325 -0
- rememberstack/workers/knowledge_writer.py +393 -0
- rememberstack/workers/operations.py +42 -0
- rememberstack/workers/p1.py +234 -0
- rememberstack/workers/p2.py +513 -0
- rememberstack/workers/p2_analytics.py +276 -0
- rememberstack/workers/p3.py +673 -0
- rememberstack/workers/reconcile.py +485 -0
- rememberstack/workers/sync.py +168 -0
- rememberstack-0.1.0.dist-info/METADATA +213 -0
- rememberstack-0.1.0.dist-info/RECORD +186 -0
- rememberstack-0.1.0.dist-info/WHEEL +4 -0
- rememberstack-0.1.0.dist-info/entry_points.txt +2 -0
- rememberstack-0.1.0.dist-info/licenses/LICENSE +201 -0
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
"""Create claim, relation, observation, and evidence structures."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Sequence
|
|
4
|
+
|
|
5
|
+
from rememberstack.spine.migrations._helpers import apply_ddl
|
|
6
|
+
from rememberstack.spine.migrations._helpers import drop_tables
|
|
7
|
+
|
|
8
|
+
revision: str = "p0_02_0004"
|
|
9
|
+
down_revision: str | None = "p0_02_0003"
|
|
10
|
+
branch_labels: str | Sequence[str] | None = None
|
|
11
|
+
depends_on: str | Sequence[str] | None = None
|
|
12
|
+
|
|
13
|
+
_DDL = r"""-- ─────────────────────────────────────────────────────────────────────────
|
|
14
|
+
-- claims — immutable verifiable propositions (D31/D32). THREE immutable time axes (concepts §5, D41):
|
|
15
|
+
-- asserted_at = assertion-EVENT time (when the source spoke, ≈ published_at); claim_valid_from/until
|
|
16
|
+
-- (+ precision/kind) = the world-time interval the SOURCE asserted the proposition held (valid-time
|
|
17
|
+
-- as EVIDENCE, not current belief); ingested_at = when WE extracted it (transaction-time). None ever
|
|
18
|
+
-- change, and claim validity is never superseded (D3) — adjudicated validity lives only on relations.
|
|
19
|
+
-- A row in claims is an ACCEPTED claim: the deterministic grounding gate (anchor + window
|
|
20
|
+
-- membership, D32 layers 1-2) MUST pass, enforced by the CHECK — a claim that fails the gate is
|
|
21
|
+
-- never produced (it becomes a ledger entry or is discarded), so the flags exist for audit and are
|
|
22
|
+
-- always true here. Large (~5×10⁷) ⇒ monthly partition by ingested_at; logical FKs (D23).
|
|
23
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
24
|
+
CREATE TABLE claims (
|
|
25
|
+
claim_id uuid NOT NULL,
|
|
26
|
+
deployment_id uuid NOT NULL, -- LOGICAL FK → deployments
|
|
27
|
+
doc_id uuid NOT NULL, -- LOGICAL FK → documents (provenance always attached — requirements_v3)
|
|
28
|
+
chunk_id uuid NOT NULL, -- LOGICAL FK → chunks (the target chunk of the context bundle)
|
|
29
|
+
section_id uuid, -- LOGICAL FK → document_sections (denormalized role/path; explains a Selection decision)
|
|
30
|
+
claim_text text NOT NULL, -- the STANDALONE assertion — what retrieval/E3/reasoning use (decontextualized, D32)
|
|
31
|
+
source_span text NOT NULL, -- the verbatim slice of the chunk the claim derives from (provenance/audit, D32)
|
|
32
|
+
char_start integer NOT NULL, -- source_span offset into document.md (anchor check: a real in-bounds slice, D32 layer 1)
|
|
33
|
+
char_end integer NOT NULL,
|
|
34
|
+
added_context jsonb NOT NULL DEFAULT '[]', -- [{text, source_kind: header|neighbour|prefix|hint, source_ref}] — each substring decontextualization ADDED (D32 layer 2)
|
|
35
|
+
temporal_class claim_temporal_class, -- static | dynamic | atemporal — the "temporally classified" requirement (see reconciliation note)
|
|
36
|
+
is_attributed boolean NOT NULL DEFAULT false, -- preserves a "X said Y" attribution (entailment rule: entails "X said Y", not "Y" — D32)
|
|
37
|
+
-- grounding verdicts (D32). Deterministic layers 1-2 are an ACCEPTANCE GATE (must be true here);
|
|
38
|
+
-- the LLM layers 3-4 are advisory/sampled and may be false on a kept-but-borderline claim:
|
|
39
|
+
anchor_ok boolean NOT NULL, -- layer 1: source_span is a real in-bounds slice of the chunk (deterministic)
|
|
40
|
+
window_membership_ok boolean NOT NULL, -- layer 2: every added_context substring verbatim-exists in its declared bundle source (deterministic; rejects fabrication)
|
|
41
|
+
entailment_self_verdict boolean, -- layer 3: in-call self-assertion the bundle entails the claim (~free, optimistic)
|
|
42
|
+
audit_status grounding_audit_status NOT NULL DEFAULT 'unaudited', -- layer 4: unaudited | sampled_pass | sampled_fail | escalated (sampled, not per-claim)
|
|
43
|
+
kept_flagged boolean NOT NULL DEFAULT false, -- D35 low-confidence Selection outcome: kept but marked-for-review (mirrors a selection_keep_flagged ledger row — see invariant below)
|
|
44
|
+
is_current_testimony boolean NOT NULL DEFAULT true, -- D54 CACHE of testimony currency (the ledger below is truth): false once a newer extraction generation covers this chunk, or (living mode) the chunk left the current version. Bookkeeping, NEVER validity — no adjudication, claims stay immutable in every D3 sense
|
|
45
|
+
asserted_at timestamptz, -- ASSERTION-EVENT time: when the source asserted this (≈ the version's source_modified_at/published_at, D55) — immutable; NOT the fact's world-time (that is claim_valid_*, D41)
|
|
46
|
+
-- D41 source-asserted world-validity INTERVAL — immutable evidence about WHEN (not current belief).
|
|
47
|
+
-- Overlap of these intervals across sources is EXPECTED (it is evidence), so there is deliberately
|
|
48
|
+
-- NO uniqueness/EXCLUDE, NO invalidated_at, NO status here — the opposite of relations (§9):
|
|
49
|
+
claim_valid_from timestamptz, -- world-time start the SOURCE attributed (NULL = unbounded-before/unknown); immutable
|
|
50
|
+
claim_valid_until timestamptz, -- world-time end (NULL = open-per-source OR unknown; disambiguated by claim_valid_precision)
|
|
51
|
+
claim_valid_precision claim_valid_precision NOT NULL DEFAULT 'unknown', -- unknown|instant|day|month|quarter|year|open — "FY2023" stores a normalized [start,end] without lying about granularity
|
|
52
|
+
claim_valid_kind claim_valid_kind, -- which world-interval this is: proposition_validity|event_time|measurement_period|effective_period (so a measurement period is never conflated with an event date or with asserted_at)
|
|
53
|
+
extractor_version text NOT NULL, -- LOGICAL FK → pipeline_component_versions (extractor); replay-on-rebuild key (D33)
|
|
54
|
+
embedding_ref text, -- opaque Lance key (claims are searchable in P1)
|
|
55
|
+
embedding_version text, -- LOGICAL FK → pipeline_component_versions (embedder)
|
|
56
|
+
ingested_at timestamptz NOT NULL DEFAULT now(), -- transaction-time + partition key; immutable
|
|
57
|
+
PRIMARY KEY (claim_id, ingested_at),
|
|
58
|
+
CHECK (char_end >= char_start),
|
|
59
|
+
CHECK (anchor_ok AND window_membership_ok), -- a claims row is an ACCEPTED claim; the deterministic grounding gate passed (D32)
|
|
60
|
+
-- D41 precision/bounds coherence (claim validity carries no status/invalidated_at — it is immutable):
|
|
61
|
+
CHECK (claim_valid_until IS NULL OR claim_valid_from IS NULL OR claim_valid_until >= claim_valid_from),
|
|
62
|
+
CHECK (claim_valid_precision <> 'unknown' OR (claim_valid_from IS NULL AND claim_valid_until IS NULL)),
|
|
63
|
+
CHECK (claim_valid_precision <> 'open' OR (claim_valid_from IS NOT NULL AND claim_valid_until IS NULL)),
|
|
64
|
+
CHECK (claim_valid_precision <> 'instant' OR (claim_valid_from IS NOT NULL AND claim_valid_until = claim_valid_from)),
|
|
65
|
+
-- a bounded precision must actually carry both bounds (else it silently degrades to unknown/open):
|
|
66
|
+
CHECK (claim_valid_precision NOT IN ('day','month','quarter','year') OR (claim_valid_from IS NOT NULL AND claim_valid_until IS NOT NULL))
|
|
67
|
+
) PARTITION BY RANGE (ingested_at);
|
|
68
|
+
COMMENT ON TABLE claims IS
|
|
69
|
+
'E2 immutable verifiable propositions (D31/D32). Stores standalone claim_text + verbatim source_span + offsets + added_context for provenance-and-entailment grounding. Three immutable time axes (D41): asserted_at (assertion event), claim_valid_from/until (+precision/kind = source-asserted world-interval — evidence, not belief), ingested_at (system); never superseded (supersession is on relations, D3). A row here passed the deterministic grounding gate. Monthly-partitioned, logical FKs.';
|
|
70
|
+
CREATE INDEX ix_claims_doc ON claims (deployment_id, doc_id);
|
|
71
|
+
CREATE INDEX ix_claims_chunk ON claims (chunk_id);
|
|
72
|
+
CREATE INDEX ix_claims_flagged ON claims (deployment_id) WHERE kept_flagged = true; -- review surface (D35)
|
|
73
|
+
CREATE INDEX ix_claims_current ON claims (deployment_id, doc_id) WHERE is_current_testimony; -- the D54 hot filter (counts; default claim search)
|
|
74
|
+
CREATE INDEX ix_claims_audit ON claims (deployment_id) WHERE audit_status = 'sampled_fail'; -- grounding regressions
|
|
75
|
+
-- D41 claim-validity is projected to Lance (P1) as filterable scalar columns (claim_valid_from/until/
|
|
76
|
+
-- precision) beside the claim embedding (same pattern as relation windows, D8); the time-filter path
|
|
77
|
+
-- is Lance, so there is NO new Postgres index by default (preserves D23's btree-light mandate on this
|
|
78
|
+
-- ~5×10⁷ partitioned table). A `claims_as_of(t)` search recipe (D9) answers "what did sources assert
|
|
79
|
+
-- held over T" at the EVIDENCE grain; fact-as-of stays relations-only (D10) and the recipe registry
|
|
80
|
+
-- BARS claims_as_of from answering "currently true". An OPTIONAL partial btree on (deployment_id,
|
|
81
|
+
-- claim_valid_from, claim_valid_until) WHERE claim_valid_precision <> 'unknown' is added only if
|
|
82
|
+
-- PG-side temporal claim filtering is ever load-tested against D23 — a spike (§17), not a default.
|
|
83
|
+
|
|
84
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
85
|
+
-- claim_extraction_decisions — the append-only, version-stamped extraction transcript (D33). It
|
|
86
|
+
-- records every Selection DROP (with reason), every low-confidence KEEP-FLAG, and every
|
|
87
|
+
-- decontextualization EDIT. Plain keeps are NOT recorded (they ARE the claims row) — keeping the
|
|
88
|
+
-- table sized for drops+flags+edits, not every keep. Rebuild reads stored claims + these decisions
|
|
89
|
+
-- and never re-calls the model (D7). Large ⇒ monthly partition by decided_at.
|
|
90
|
+
-- INVARIANT: a kept_flagged claim is the pair (claims row with kept_flagged=true) + (a
|
|
91
|
+
-- selection_keep_flagged decision here); the ledger is the replay source from which
|
|
92
|
+
-- claims.kept_flagged is reconstituted on rebuild.
|
|
93
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
94
|
+
CREATE TABLE claim_extraction_decisions (
|
|
95
|
+
decision_id uuid NOT NULL,
|
|
96
|
+
deployment_id uuid NOT NULL, -- LOGICAL FK → deployments
|
|
97
|
+
doc_id uuid NOT NULL, -- LOGICAL FK → documents
|
|
98
|
+
chunk_id uuid NOT NULL, -- LOGICAL FK → chunks
|
|
99
|
+
claim_id uuid, -- LOGICAL FK → claims; set for decontext edits + selection_keep_flagged; NULL for selection_drop (no claim produced)
|
|
100
|
+
decision_type extraction_decision_type NOT NULL, -- selection_drop | selection_keep_flagged | decontext_edit
|
|
101
|
+
source_span text, -- the proposition/sentence the decision was about
|
|
102
|
+
reason selection_drop_reason, -- for drops: opinion|advice|hypothetical|generic|question|intro|conclusion|no_info|ambiguous|references_boilerplate (D31)
|
|
103
|
+
edit_detail jsonb, -- for decontext edits: what was resolved/added and from which bundle source
|
|
104
|
+
protected_class text, -- never-drop class checked/applied (quantity|date|named_entity_predicate|change_of_state) — D35
|
|
105
|
+
extractor_version text NOT NULL, -- LOGICAL FK → pipeline_component_versions; the version that made this decision
|
|
106
|
+
decided_at timestamptz NOT NULL DEFAULT now(), -- partition key
|
|
107
|
+
PRIMARY KEY (decision_id, decided_at)
|
|
108
|
+
) PARTITION BY RANGE (decided_at);
|
|
109
|
+
COMMENT ON TABLE claim_extraction_decisions IS
|
|
110
|
+
'Append-only Selection-drop + keep-flag + decontextualization-edit ledger (D33); plain keeps are not recorded. Makes aggressive Selection auditable and recoverable: a better prompt re-examines only the drops; rebuild replays from here without re-calling the model (D7). Monthly-partitioned.';
|
|
111
|
+
CREATE INDEX ix_cxd_chunk ON claim_extraction_decisions (chunk_id);
|
|
112
|
+
CREATE INDEX ix_cxd_drops ON claim_extraction_decisions (deployment_id, reason) WHERE decision_type = 'selection_drop';
|
|
113
|
+
|
|
114
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
115
|
+
-- grounding_audits — the sampled independent entailment audit (D32 layer 4). Not per-claim
|
|
116
|
+
-- (self-grading is optimistic; a separate judge re-checks a sample; only a borderline band
|
|
117
|
+
-- escalates). claims.audit_status caches the latest result.
|
|
118
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
119
|
+
CREATE TABLE grounding_audits (
|
|
120
|
+
audit_id uuid PRIMARY KEY,
|
|
121
|
+
deployment_id uuid NOT NULL REFERENCES deployments,
|
|
122
|
+
claim_id uuid NOT NULL, -- LOGICAL FK → claims (partitioned)
|
|
123
|
+
verdict grounding_audit_status NOT NULL, -- sampled_pass | sampled_fail | escalated
|
|
124
|
+
judge_version text NOT NULL, -- LOGICAL FK → pipeline_component_versions (independent judge)
|
|
125
|
+
rationale text,
|
|
126
|
+
sampled_at timestamptz NOT NULL DEFAULT now()
|
|
127
|
+
);
|
|
128
|
+
COMMENT ON TABLE grounding_audits IS
|
|
129
|
+
'Sampled independent entailment audits of claims (D32 layer 4). Offline, not per-claim; feeds claims.audit_status and the grounding eval suite.';
|
|
130
|
+
CREATE INDEX ix_grounding_claim ON grounding_audits (claim_id);
|
|
131
|
+
|
|
132
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
133
|
+
-- testimony_currency_events — the D54 currency ledger (append-only; the D33 pattern: this is
|
|
134
|
+
-- truth, claims.is_current_testimony is cache). A transition is BOOKKEEPING, never validity:
|
|
135
|
+
-- no adjudication, no invalidated_at, nothing about the claim changes. Timestamped events keep
|
|
136
|
+
-- transaction-time reconstructions exact (fact-as-of-T still sees old generations).
|
|
137
|
+
-- Written by the reconciliation step of the lifecycle flow (evidence_lifecycle_design §5),
|
|
138
|
+
-- which runs only on COMPLETED basis changes and then recounts affected facts.
|
|
139
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
140
|
+
CREATE TABLE testimony_currency_events (
|
|
141
|
+
event_id uuid NOT NULL,
|
|
142
|
+
deployment_id uuid NOT NULL, -- LOGICAL FK → deployments
|
|
143
|
+
claim_id uuid NOT NULL, -- LOGICAL FK → claims (partitioned)
|
|
144
|
+
doc_id uuid NOT NULL, -- LOGICAL FK → documents (the lineage; the recount scope)
|
|
145
|
+
reconciliation_id uuid NOT NULL, -- identifies ONE reconciliation run = one completed basis change per lineage (a new version's extraction completing, or a version-bump re-extraction completing). Minted when the run starts and stored in processing_state, so a RETRIED run reuses it — its re-emitted events hit the UNIQUE below as no-ops
|
|
146
|
+
became_current boolean NOT NULL, -- false = lost currency; true = regained (un-delete, mode change)
|
|
147
|
+
reason currency_reason NOT NULL, -- reextracted | version_superseded | version_deleted
|
|
148
|
+
from_extractor_version text, -- the superseded generation (reason=reextracted)
|
|
149
|
+
from_version_id uuid, -- the superseded/deleted document version (reason=version_*)
|
|
150
|
+
occurred_at timestamptz NOT NULL DEFAULT now(), -- partition key
|
|
151
|
+
PRIMARY KEY (event_id, occurred_at),
|
|
152
|
+
UNIQUE (claim_id, reconciliation_id, reason, became_current, occurred_at) -- a retried reconciliation re-emits as a no-op, never a duplicate (F11)
|
|
153
|
+
) PARTITION BY RANGE (occurred_at);
|
|
154
|
+
COMMENT ON TABLE testimony_currency_events IS
|
|
155
|
+
'Append-only D54 testimony-currency transitions. Truth for claims.is_current_testimony (cache); replayable (D7). Reasons: reextracted (a newer extraction generation covers the chunk), version_superseded (living-mode lineage moved past the claim''s version), version_deleted. Never validity, never supersession — D3 untouched.';
|
|
156
|
+
CREATE INDEX ix_currency_claim ON testimony_currency_events (claim_id);
|
|
157
|
+
CREATE INDEX ix_currency_doc ON testimony_currency_events (deployment_id, doc_id, occurred_at);
|
|
158
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
159
|
+
-- relations — distinct bi-temporal facts (D2/D3). The (entity_id,predicate) blocking key for
|
|
160
|
+
-- supersession is the composite index below; it is small (distinct facts, not assertions) —
|
|
161
|
+
-- what makes supersession affordable at scale (concepts §6). The canonical fact LABEL + its
|
|
162
|
+
-- embedding live in Lance (D8); PG keeps the label text + version + a Lance ref. Not partitioned.
|
|
163
|
+
--
|
|
164
|
+
-- "Live belief" = invalidated_at IS NULL (transaction-time), regardless of valid_until: a
|
|
165
|
+
-- believed-historical fact ("Alice worked at Acme 2020-2022", valid_until set, invalidated_at NULL)
|
|
166
|
+
-- is still currently believed. status is a GENERATED mirror of invalidated_at so validity has
|
|
167
|
+
-- exactly one authoritative home (D6) and cannot drift.
|
|
168
|
+
--
|
|
169
|
+
-- Uniqueness: a GiST EXCLUSION constraint forbids two BELIEVED, non-contradictory relations with
|
|
170
|
+
-- the same (s,p,o) AND OVERLAPPING valid-time windows. This is more correct than a partial unique
|
|
171
|
+
-- index: it permits re-occurring facts with non-overlapping windows (Alice worked at Acme twice)
|
|
172
|
+
-- and permits contradictions (carved out via contradiction_group), while forbidding duplicate
|
|
173
|
+
-- overlapping beliefs. Evidence-collapse (D2) finds the believed relation whose window covers the
|
|
174
|
+
-- new claim's time.
|
|
175
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
176
|
+
CREATE TABLE relations (
|
|
177
|
+
relation_id uuid PRIMARY KEY, -- the fact's identity; provenance handle in the graph/Lance projections
|
|
178
|
+
deployment_id uuid NOT NULL REFERENCES deployments,
|
|
179
|
+
subject_entity_id uuid NOT NULL, -- canonical subject (composite FK below; only canonical entities enter relations/graph — p2 §2)
|
|
180
|
+
predicate text NOT NULL, -- governed predicate; composite FK below
|
|
181
|
+
object_entity_id uuid NOT NULL, -- canonical object (entity→entity only; literals stay in claims — D2)
|
|
182
|
+
-- bi-temporality (concepts §5): two clocks, different questions.
|
|
183
|
+
valid_from timestamptz, -- VALID-time start: when the fact began holding in the world (NULL = unknown/always)
|
|
184
|
+
valid_until timestamptz, -- VALID-time end: closed by supersession when the fact stops holding ("Alice left Acme")
|
|
185
|
+
ingested_at timestamptz NOT NULL DEFAULT now(), -- TRANSACTION-time: when the system first believed this fact
|
|
186
|
+
invalidated_at timestamptz, -- TRANSACTION-time: when the system learned it was superseded (NULL = still believed)
|
|
187
|
+
evidence_count integer NOT NULL DEFAULT 0, -- cached count of DISTINCT DOCUMENT LINEAGES with current-testimony supporting claims (D54 — invariant under re-extraction/version churn/intra-doc repetition); confidence/salience signal (D2 refined); K3 candidate filter
|
|
188
|
+
contradict_count integer NOT NULL DEFAULT 0, -- cached count of distinct current-testimony lineages contradicting (same D54 rule, stance=contradicts)
|
|
189
|
+
confidence real, -- aggregate confidence over evidence (not an extraction-time guess — concepts §3)
|
|
190
|
+
contradiction_group uuid, -- shared id when two live relations contradict and can't be adjudicated — retrieval shows both sides (concepts §4)
|
|
191
|
+
status relation_status GENERATED ALWAYS AS -- DERIVED mirror of invalidated_at (single validity home, D6): active iff invalidated_at IS NULL, else invalidated
|
|
192
|
+
(CASE WHEN invalidated_at IS NOT NULL THEN 'invalidated'::relation_status ELSE 'active'::relation_status END) STORED,
|
|
193
|
+
-- fact label (D8): the human-readable sentence embedded in Lance; regenerated only on material adjudication change.
|
|
194
|
+
fact_label text, -- "Alice Novak works at Acme as VP of Engineering"
|
|
195
|
+
fact_label_version text, -- LOGICAL FK → pipeline_component_versions (fact_labeler)
|
|
196
|
+
fact_label_embedding_ref text, -- opaque Lance key for the fact-label vector (P1; no vectors in PG/graph — D8)
|
|
197
|
+
normalizer_version text NOT NULL, -- LOGICAL FK → pipeline_component_versions (normalizer); replay-on-rebuild
|
|
198
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
199
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
200
|
+
UNIQUE (deployment_id, relation_id), -- composite-FK target (tenancy isolation, §0)
|
|
201
|
+
FOREIGN KEY (deployment_id, predicate) REFERENCES predicates (deployment_id, predicate) ON UPDATE CASCADE,
|
|
202
|
+
FOREIGN KEY (deployment_id, subject_entity_id) REFERENCES entities (deployment_id, entity_id),
|
|
203
|
+
FOREIGN KEY (deployment_id, object_entity_id) REFERENCES entities (deployment_id, entity_id),
|
|
204
|
+
CHECK (valid_until IS NULL OR valid_from IS NULL OR valid_until >= valid_from),
|
|
205
|
+
CHECK (invalidated_at IS NULL OR invalidated_at >= ingested_at), -- can't un-learn before learning
|
|
206
|
+
-- At most one BELIEVED, non-contradictory relation per (s,p,o) with overlapping world-time:
|
|
207
|
+
EXCLUDE USING gist (
|
|
208
|
+
deployment_id WITH =, subject_entity_id WITH =, predicate WITH =, object_entity_id WITH =,
|
|
209
|
+
tstzrange(valid_from, valid_until) WITH &&
|
|
210
|
+
) WHERE (invalidated_at IS NULL AND contradiction_group IS NULL)
|
|
211
|
+
);
|
|
212
|
+
COMMENT ON TABLE relations IS
|
|
213
|
+
'E3 distinct bi-temporal facts (D2/D3). Identity = (subject,predicate,object) + validity interval; the unit of supersession/contradiction. evidence_count caches corpus redundancy as a confidence signal (D2). status is a generated mirror of invalidated_at (validity has one home, D6). The GiST EXCLUDE forbids overlapping duplicate beliefs while allowing re-occurring facts and carved-out contradictions. fact_label+embedding live in Lance (D8).';
|
|
214
|
+
-- The supersession blocking key (D4) — small, distinct facts; THE index that makes supersession
|
|
215
|
+
-- detection affordable (concepts §6):
|
|
216
|
+
CREATE INDEX ix_relations_block_subj ON relations (deployment_id, subject_entity_id, predicate, object_entity_id);
|
|
217
|
+
CREATE INDEX ix_relations_block_obj ON relations (deployment_id, object_entity_id, predicate); -- reverse blocking ("who works_at acme?")
|
|
218
|
+
CREATE INDEX ix_relations_predicate ON relations (deployment_id, predicate);
|
|
219
|
+
CREATE INDEX ix_relations_contradiction ON relations (contradiction_group) WHERE contradiction_group IS NOT NULL;
|
|
220
|
+
CREATE INDEX ix_relations_live ON relations (deployment_id, subject_entity_id) WHERE invalidated_at IS NULL;
|
|
221
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
222
|
+
-- relation_evidence — the many-to-many join claims ⇄ relations (D2). "Where corpus redundancy goes
|
|
223
|
+
-- to die": 200 documents asserting the same fact = one relation + 200 rows here. ~10⁸ rows.
|
|
224
|
+
--
|
|
225
|
+
-- Partitioned by HASH(relation_id), NOT by ingest month — because every hot access is by
|
|
226
|
+
-- relation_id (hydration) and the evidence-once invariant is on (relation_id, claim_id). With the
|
|
227
|
+
-- partition key = relation_id: relation hydration prunes to ONE partition, AND a real
|
|
228
|
+
-- PRIMARY KEY (relation_id, claim_id) enforces "a claim evidences a relation at most once" in-DB
|
|
229
|
+
-- (so relations.evidence_count cannot be inflated by a retry — a re-link is an ON CONFLICT no-op).
|
|
230
|
+
-- This is D23's evidence-join policy. Hash partitions are STATIC (64 migration-created children;
|
|
231
|
+
-- a measured starting point), so no pg_partman rolling-window is needed. The claim_id reverse lookup
|
|
232
|
+
-- ("which relations does this claim evidence")
|
|
233
|
+
-- scans all partitions but is the cold path. FKs remain logical (D23 btree-only/write-amplification).
|
|
234
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
235
|
+
CREATE TABLE relation_evidence (
|
|
236
|
+
deployment_id uuid NOT NULL, -- LOGICAL FK → deployments
|
|
237
|
+
relation_id uuid NOT NULL, -- LOGICAL FK → relations; HASH partition key
|
|
238
|
+
claim_id uuid NOT NULL, -- LOGICAL FK → claims; the asserting claim (immutable evidence). One claim may evidence MANY relations.
|
|
239
|
+
doc_id uuid NOT NULL, -- LOGICAL FK → documents (the claim's LINEAGE, denormalized write-once) — makes the D54 recount a single-table scan per fact (F7)
|
|
240
|
+
stance evidence_stance NOT NULL, -- supports | contradicts (concepts §3/§4)
|
|
241
|
+
normalizer_version text NOT NULL, -- LOGICAL FK → pipeline_component_versions; which normalizer linked them
|
|
242
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
243
|
+
PRIMARY KEY (relation_id, claim_id) -- evidence-once, DB-enforced (partition key relation_id is included); re-link via ON CONFLICT DO NOTHING is a no-op
|
|
244
|
+
) PARTITION BY HASH (relation_id);
|
|
245
|
+
COMMENT ON TABLE relation_evidence IS
|
|
246
|
+
'Many-to-many evidence links (D2). Corpus redundancy collapses here into relations.evidence_count. Partitioned by HASH(relation_id) so relation hydration prunes to one partition and PRIMARY KEY (relation_id, claim_id) enforces evidence-once in-DB (D23; §17 item 1 resolved). claim_id reverse lookup scans all partitions (cold path). Logical FKs (D23).';
|
|
247
|
+
-- 64 static hash children created by the migration — required, or inserts fail (F5); mirrors observation_evidence:
|
|
248
|
+
DO $$ BEGIN
|
|
249
|
+
FOR i IN 0..63 LOOP
|
|
250
|
+
EXECUTE format('CREATE TABLE relation_evidence_p%s PARTITION OF relation_evidence '
|
|
251
|
+
'FOR VALUES WITH (MODULUS 64, REMAINDER %s);', i, i);
|
|
252
|
+
END LOOP;
|
|
253
|
+
END $$;
|
|
254
|
+
CREATE INDEX ix_relevidence_claim ON relation_evidence (claim_id); -- reverse lookup: relations a claim evidences (all-partition scan)
|
|
255
|
+
|
|
256
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
257
|
+
-- relation_adjudications — append-only supersession/contradiction transcript (D3/D4). Records WHY a
|
|
258
|
+
-- relation's window closed, a contradiction was flagged, or a merge proposed — by which cascade
|
|
259
|
+
-- rung, with what confidence/evidence. Makes the non-deterministic adjudication replayable on
|
|
260
|
+
-- rebuild (D7) and answers "why did valid_until close on 2026-01-15?". Real composite FK; the
|
|
261
|
+
-- deletion GC retires (not deletes) relations referenced here so the audit trail survives (§13).
|
|
262
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
263
|
+
CREATE TABLE relation_adjudications (
|
|
264
|
+
adjudication_id uuid PRIMARY KEY,
|
|
265
|
+
deployment_id uuid NOT NULL REFERENCES deployments,
|
|
266
|
+
relation_id uuid NOT NULL, -- the relation acted upon (composite FK below)
|
|
267
|
+
related_relation_id uuid, -- the other relation in a supersede/contradict pair, if any (composite FK below)
|
|
268
|
+
outcome adjudication_outcome NOT NULL, -- add | noop | supersede | contradict | same_as_merge_proposal (D4 write-time outcomes)
|
|
269
|
+
method adjudication_method NOT NULL, -- novelty_gate | exact | fuzzy | embedding | small_model | frontier_llm (cheap-first cascade, D4)
|
|
270
|
+
confidence real,
|
|
271
|
+
triggering_claim_id uuid, -- LOGICAL FK → claims; the new claim that triggered adjudication
|
|
272
|
+
features jsonb, -- scores/rationale the decision used (audit); scrubbed on hard-forget (§13)
|
|
273
|
+
adjudicator_version text NOT NULL, -- LOGICAL FK → pipeline_component_versions
|
|
274
|
+
decided_by decision_actor NOT NULL DEFAULT 'auto',
|
|
275
|
+
decided_at timestamptz NOT NULL DEFAULT now(),
|
|
276
|
+
superseded_by uuid REFERENCES relation_adjudications, -- a later adjudication that overrode this one
|
|
277
|
+
FOREIGN KEY (deployment_id, relation_id) REFERENCES relations (deployment_id, relation_id),
|
|
278
|
+
FOREIGN KEY (deployment_id, related_relation_id) REFERENCES relations (deployment_id, relation_id)
|
|
279
|
+
);
|
|
280
|
+
COMMENT ON TABLE relation_adjudications IS
|
|
281
|
+
'Append-only supersession/contradiction decision log (D3/D4). Explains every window closure / contradiction flag / merge proposal, by cascade rung + evidence; replayed on P2 rebuild and used for "what did we believe at T / why" audits.';
|
|
282
|
+
CREATE INDEX ix_adjud_relation ON relation_adjudications (relation_id);
|
|
283
|
+
CREATE INDEX ix_adjud_live ON relation_adjudications (relation_id) WHERE superseded_by IS NULL;
|
|
284
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
285
|
+
-- observations — non-graph facts about ONE entity (D43): entity-anchored, bi-temporal, UNTYPED. The
|
|
286
|
+
-- supersession blocking key is subject_entity_id alone (exact, exhaustive per entity); the same-slot /
|
|
287
|
+
-- supersede-vs-coexist judgment is the adjudicator's (D4 cascade), fail-safe to coexist. No governed
|
|
288
|
+
-- attribute vocabulary, no value_domain/cardinality, NO structured value/period columns, no typed
|
|
289
|
+
-- EXCLUDE — the value AND any reporting period live in `statement` and are matched SEMANTICALLY, exactly
|
|
290
|
+
-- like the property (consistent with the untyped design). status is a GENERATED mirror of invalidated_at
|
|
291
|
+
-- (one validity home, D6). The observation LABEL + its embedding live in Lance (D8).
|
|
292
|
+
-- THE NO-CAP RULE (D43): only a CHANGING EFFECTIVE STATE (headcount/balance/status) is capped on
|
|
293
|
+
-- valid-time when superseded; a MEASUREMENT / FIXED-PERIOD figure ("FY2023 revenue") is NEVER capped —
|
|
294
|
+
-- it doesn't stop being true at period-end, stays open, and conflicting same-period figures coexist.
|
|
295
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
296
|
+
CREATE TABLE observations (
|
|
297
|
+
observation_id uuid PRIMARY KEY, -- the observation's identity; provenance handle in Lance
|
|
298
|
+
deployment_id uuid NOT NULL REFERENCES deployments,
|
|
299
|
+
subject_entity_id uuid NOT NULL, -- the ANCHOR + supersession blocking key (a resolved canonical entity); composite FK below
|
|
300
|
+
statement text NOT NULL, -- canonical NL form of the observed fact ("Acme's headcount is 600", "Acme's FY2023 revenue was $5M"); embedded in Lance (D8). The VALUE and any reporting period live HERE — there is no structured value/period column (D43 lean); the adjudicator reads them semantically, like the property.
|
|
301
|
+
-- bi-temporality (concepts §5): two clocks, WORLD-VALIDITY OF THE BELIEF.
|
|
302
|
+
valid_from timestamptz, -- VALID-time start: when the belief began holding in the world (NULL = unknown/always); seeded from the claim's asserted validity (D41)
|
|
303
|
+
valid_until timestamptz, -- VALID-time end. NO-CAP RULE (D43): capped ONLY when a CHANGING EFFECTIVE STATE (headcount/balance/status) is superseded by a later value. A MEASUREMENT / FIXED-PERIOD figure ("FY2023 revenue") is NEVER capped here — it doesn't stop being true at period-end; it stays open and conflicting same-period figures coexist. The adjudicator decides state-vs-measurement from `statement` (semantic), not a typed column. (observations_design.md §3)
|
|
304
|
+
ingested_at timestamptz NOT NULL DEFAULT now(), -- TRANSACTION-time: when the system first believed it
|
|
305
|
+
invalidated_at timestamptz, -- TRANSACTION-time: when learned wrong (NULL = still believed). NOT used to "end" a fact — that's valid_until.
|
|
306
|
+
evidence_count integer NOT NULL DEFAULT 0, -- cached count of DISTINCT current-testimony LINEAGES supporting (D54 — mirrors relations)
|
|
307
|
+
contradict_count integer NOT NULL DEFAULT 0, -- cached count of distinct current-testimony lineages contradicting (D54). NB: conflicting OBSERVATIONS are tracked via contradiction_group, a different concept.
|
|
308
|
+
confidence real, -- aggregate confidence over evidence
|
|
309
|
+
contradiction_group uuid, -- shared id when two live observations conflict and both must stand (concepts §4)
|
|
310
|
+
status relation_status GENERATED ALWAYS AS -- DERIVED mirror of invalidated_at (single validity home, D6)
|
|
311
|
+
(CASE WHEN invalidated_at IS NOT NULL THEN 'invalidated'::relation_status ELSE 'active'::relation_status END) STORED,
|
|
312
|
+
obs_label text, -- the human-readable sentence embedded in Lance (often = statement); semantic blocking + retrieval
|
|
313
|
+
obs_label_version text, -- LOGICAL FK → pipeline_component_versions (labeler)
|
|
314
|
+
obs_label_embedding_ref text, -- opaque Lance key for the label vector (P1; no vectors in PG — D8)
|
|
315
|
+
normalizer_version text NOT NULL, -- LOGICAL FK → pipeline_component_versions; replay-on-rebuild
|
|
316
|
+
adjudicator_version text, -- LOGICAL FK → pipeline_component_versions (supersession/contradiction adjudicator, D4)
|
|
317
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
318
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
319
|
+
UNIQUE (deployment_id, observation_id), -- composite-FK target (tenancy isolation, §0)
|
|
320
|
+
FOREIGN KEY (deployment_id, subject_entity_id) REFERENCES entities (deployment_id, entity_id),
|
|
321
|
+
CHECK (valid_until IS NULL OR valid_from IS NULL OR valid_until >= valid_from),
|
|
322
|
+
CHECK (invalidated_at IS NULL OR invalidated_at >= ingested_at) -- can't un-learn before learning
|
|
323
|
+
-- NOTE: intentionally NO EXCLUDE / uniqueness constraint — there is no typed slot to key one on;
|
|
324
|
+
-- supersession + evidence-collapse are adjudicated (entity-block + semantic + cascade), and
|
|
325
|
+
-- "both-stand" is the safe default.
|
|
326
|
+
);
|
|
327
|
+
COMMENT ON TABLE observations IS
|
|
328
|
+
'D43 non-graph fact layer: a believed value/statement about ONE entity (entity-anchored, bi-temporal, UNTYPED). Sibling of relations; never projects to the graph (D18). The value AND any reporting period live in `statement` (no structured value/period columns); the adjudicator matches same-entity + same-property + same-period + value-compatibility SEMANTICALLY. Supersession is adjudicated by entity-blocking + the D4 cascade (no typed slot, no EXCLUDE); "never silently resolve" is a binding adjudicator contract (supersede only on a positively-matched prior above margin, with a persisted reason; else coexist) + an eval gate, NOT a schema invariant. NO-CAP RULE: only a changing effective state is capped on valid-time; a measurement/fixed-period figure is never capped and conflicting same-period figures coexist. status is a generated mirror of invalidated_at (one validity home, D6); label+embedding live in Lance (D8).';
|
|
329
|
+
-- The supersession blocking key (D4): all live observations for an entity (exact + exhaustive per entity):
|
|
330
|
+
CREATE INDEX ix_observations_block ON observations (deployment_id, subject_entity_id) WHERE invalidated_at IS NULL;
|
|
331
|
+
CREATE INDEX ix_observations_entity ON observations (deployment_id, subject_entity_id); -- full history incl. capped/invalidated
|
|
332
|
+
CREATE INDEX ix_observations_contradiction ON observations (contradiction_group) WHERE contradiction_group IS NOT NULL;
|
|
333
|
+
|
|
334
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
335
|
+
-- observation_evidence — many-to-many join claims ⇄ observations (D2), mirroring relation_evidence.
|
|
336
|
+
-- Corpus redundancy collapses here into observations.evidence_count. HASH(observation_id). Like
|
|
337
|
+
-- relation_evidence (§9), FKs are LOGICAL (D23 — btree-only at 10^8 scale); the integrity guarantee
|
|
338
|
+
-- here is the PRIMARY KEY (evidence-once), NOT referential FKs. (Evidence-collapse of the same value
|
|
339
|
+
-- into ONE observation is adjudicated upstream — best-effort — not enforced by this table, which only
|
|
340
|
+
-- dedups a given (observation, claim) pair.)
|
|
341
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
342
|
+
CREATE TABLE observation_evidence (
|
|
343
|
+
deployment_id uuid NOT NULL, -- LOGICAL FK → deployments
|
|
344
|
+
observation_id uuid NOT NULL, -- LOGICAL FK → observations; HASH partition key
|
|
345
|
+
claim_id uuid NOT NULL, -- LOGICAL FK → claims; the asserting claim (immutable evidence). One claim may evidence many observations.
|
|
346
|
+
stance evidence_stance NOT NULL, -- supports | contradicts (concepts §3/§4)
|
|
347
|
+
normalizer_version text NOT NULL, -- LOGICAL FK → pipeline_component_versions
|
|
348
|
+
doc_id uuid NOT NULL, -- LOGICAL FK → documents (the claim's lineage, write-once) — D54 recount without cross-partition claim joins (F7)
|
|
349
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
350
|
+
PRIMARY KEY (observation_id, claim_id) -- evidence-once, DB-enforced; re-link via ON CONFLICT DO NOTHING is a no-op
|
|
351
|
+
) PARTITION BY HASH (observation_id);
|
|
352
|
+
-- 64 static hash children created by the migration, same as relation_evidence (§9):
|
|
353
|
+
DO $$ BEGIN
|
|
354
|
+
FOR i IN 0..63 LOOP
|
|
355
|
+
EXECUTE format('CREATE TABLE observation_evidence_p%s PARTITION OF observation_evidence '
|
|
356
|
+
'FOR VALUES WITH (MODULUS 64, REMAINDER %s);', i, i);
|
|
357
|
+
END LOOP;
|
|
358
|
+
END $$;
|
|
359
|
+
COMMENT ON TABLE observation_evidence IS
|
|
360
|
+
'Many-to-many evidence links claims ⇄ observations (D2/D43), mirroring relation_evidence. Corpus redundancy collapses into observations.evidence_count. HASH(observation_id), 64 static partitions; PRIMARY KEY (observation_id, claim_id) enforces evidence-once. Logical FKs (D23).';
|
|
361
|
+
CREATE INDEX ix_obsevidence_claim ON observation_evidence (claim_id); -- reverse lookup (all-partition scan, cold path)
|
|
362
|
+
|
|
363
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
364
|
+
-- observation_adjudications — append-only supersession/contradiction transcript (D3/D4), mirroring
|
|
365
|
+
-- relation_adjudications. Records WHY an observation's window closed / a contradiction was flagged, by
|
|
366
|
+
-- cascade rung + confidence; makes the non-deterministic adjudication replayable on rebuild (D7).
|
|
367
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
368
|
+
CREATE TABLE observation_adjudications (
|
|
369
|
+
adjudication_id uuid PRIMARY KEY,
|
|
370
|
+
deployment_id uuid NOT NULL REFERENCES deployments,
|
|
371
|
+
observation_id uuid NOT NULL, -- the observation acted upon (composite FK below)
|
|
372
|
+
related_observation_id uuid, -- the other observation in a supersede/contradict pair, if any (composite FK below)
|
|
373
|
+
outcome adjudication_outcome NOT NULL, -- add | noop | supersede | contradict | same_as_merge_proposal (D4)
|
|
374
|
+
method adjudication_method NOT NULL, -- novelty_gate | exact | fuzzy | embedding | small_model | frontier_llm (cheap-first cascade, D4)
|
|
375
|
+
confidence real,
|
|
376
|
+
triggering_claim_id uuid, -- LOGICAL FK → claims; the new claim that triggered adjudication
|
|
377
|
+
features jsonb, -- scores/rationale (audit); scrubbed on hard-forget (§13)
|
|
378
|
+
adjudicator_version text NOT NULL, -- LOGICAL FK → pipeline_component_versions
|
|
379
|
+
decided_by decision_actor NOT NULL DEFAULT 'auto',
|
|
380
|
+
decided_at timestamptz NOT NULL DEFAULT now(),
|
|
381
|
+
superseded_by uuid REFERENCES observation_adjudications, -- a later adjudication that overrode this one
|
|
382
|
+
FOREIGN KEY (deployment_id, observation_id) REFERENCES observations (deployment_id, observation_id),
|
|
383
|
+
FOREIGN KEY (deployment_id, related_observation_id) REFERENCES observations (deployment_id, observation_id)
|
|
384
|
+
);
|
|
385
|
+
COMMENT ON TABLE observation_adjudications IS
|
|
386
|
+
'Append-only supersession/contradiction decision log for observations (D3/D4/D43), mirroring relation_adjudications. Explains every window closure / contradiction flag by cascade rung + evidence; replayed on rebuild and used for "what did we believe at T / why" audits.';
|
|
387
|
+
CREATE INDEX ix_obsadjud_observation ON observation_adjudications (observation_id);
|
|
388
|
+
CREATE INDEX ix_obsadjud_live ON observation_adjudications (observation_id) WHERE superseded_by IS NULL;
|
|
389
|
+
"""
|
|
390
|
+
_TABLES = (
|
|
391
|
+
"claims",
|
|
392
|
+
"claim_extraction_decisions",
|
|
393
|
+
"grounding_audits",
|
|
394
|
+
"testimony_currency_events",
|
|
395
|
+
"relations",
|
|
396
|
+
"relation_evidence",
|
|
397
|
+
"relation_adjudications",
|
|
398
|
+
"observations",
|
|
399
|
+
"observation_evidence",
|
|
400
|
+
"observation_adjudications",
|
|
401
|
+
)
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
def upgrade() -> None:
|
|
405
|
+
"""Apply create claim, relation, observation, and evidence structures."""
|
|
406
|
+
apply_ddl(sql=_DDL)
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
def downgrade() -> None:
|
|
410
|
+
"""Revert create claim, relation, observation, and evidence structures."""
|
|
411
|
+
drop_tables(table_names=reversed(_TABLES))
|