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,391 @@
|
|
|
1
|
+
"""Create projection, knowledge, and retrieval 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_0005"
|
|
9
|
+
down_revision: str | None = "p0_02_0004"
|
|
10
|
+
branch_labels: str | Sequence[str] | None = None
|
|
11
|
+
depends_on: str | Sequence[str] | None = None
|
|
12
|
+
|
|
13
|
+
_DDL = r"""-- ─────────────────────────────────────────────────────────────────────────
|
|
14
|
+
-- projection_snapshots — registry of P1/P2/P3 rebuilds (D7/D40). Immutable versioned snapshots;
|
|
15
|
+
-- a validation gate must pass before is_latest flips (failure ⇒ previous snapshot keeps serving).
|
|
16
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
17
|
+
CREATE TABLE projection_snapshots (
|
|
18
|
+
snapshot_id uuid PRIMARY KEY,
|
|
19
|
+
deployment_id uuid NOT NULL REFERENCES deployments,
|
|
20
|
+
plane projection_plane NOT NULL, -- P1_search | P2_graph | P3_corpusfs
|
|
21
|
+
version text NOT NULL, -- monotonic/timestamped snapshot version (also the GCS path segment)
|
|
22
|
+
gcs_uri text NOT NULL, -- gs://…/snapshots/<version>/
|
|
23
|
+
status snapshot_status NOT NULL DEFAULT 'building', -- building | validating | published | superseded | failed
|
|
24
|
+
is_latest boolean NOT NULL DEFAULT false, -- the pointer readers follow; exactly one per (deployment,plane)
|
|
25
|
+
row_counts jsonb, -- per-table counts validated against Postgres (D7 validation gate)
|
|
26
|
+
validation jsonb, -- validation report (pass/fail per check)
|
|
27
|
+
built_from_watermark timestamptz, -- max ingested_at included — bounds projection staleness (freshness SLA = cadence, D7)
|
|
28
|
+
built_at timestamptz NOT NULL DEFAULT now(),
|
|
29
|
+
published_at timestamptz,
|
|
30
|
+
UNIQUE (deployment_id, plane, version),
|
|
31
|
+
UNIQUE (deployment_id, snapshot_id) -- composite-FK target (tenancy isolation, §0)
|
|
32
|
+
);
|
|
33
|
+
COMMENT ON TABLE projection_snapshots IS
|
|
34
|
+
'Registry of immutable P1/P2/P3 snapshots (D7/D40). Validation gates is_latest; old snapshots are free point-in-time debugging artifacts. Mirrors the GCS latest pointer for operators/workers.';
|
|
35
|
+
CREATE UNIQUE INDEX ux_snapshot_latest ON projection_snapshots (deployment_id, plane) WHERE is_latest;
|
|
36
|
+
|
|
37
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
38
|
+
-- communities — detected entity communities per P2 snapshot (D11). Recomputed each rebuild.
|
|
39
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
40
|
+
CREATE TABLE communities (
|
|
41
|
+
community_id uuid PRIMARY KEY,
|
|
42
|
+
deployment_id uuid NOT NULL REFERENCES deployments,
|
|
43
|
+
snapshot_id uuid NOT NULL, -- which (P2_graph) rebuild produced this partition (composite FK below)
|
|
44
|
+
label text, -- optional human/LLM topic label (K1 hint)
|
|
45
|
+
size integer NOT NULL, -- member count; an emerging giant community can signal over-merge (health metric, registries §10)
|
|
46
|
+
algorithm community_algorithm NOT NULL,-- leiden | louvain (external pass) — D11
|
|
47
|
+
detected_at timestamptz NOT NULL DEFAULT now(),
|
|
48
|
+
UNIQUE (deployment_id, community_id), -- composite-FK target
|
|
49
|
+
FOREIGN KEY (deployment_id, snapshot_id) REFERENCES projection_snapshots (deployment_id, snapshot_id) ON DELETE CASCADE
|
|
50
|
+
);
|
|
51
|
+
COMMENT ON TABLE communities IS
|
|
52
|
+
'Externally-detected communities per P2 graph snapshot (D11). Feed K1 refresh triggers ("claims in community C changed") and salience; recomputed each rebuild and GC''d with their snapshot (graph stays a projection). FK references must be a plane=P2_graph snapshot (invariant; the writer only inserts P2 snapshots here).';
|
|
53
|
+
CREATE INDEX ix_communities_snapshot ON communities (snapshot_id);
|
|
54
|
+
|
|
55
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
56
|
+
-- entity_graph_metrics — per-entity centrality + community membership per snapshot (D11). PageRank
|
|
57
|
+
-- = salience prior; degree feeds entities.graph_degree (blast-radius) — refreshed ONLY from the
|
|
58
|
+
-- currently-published is_latest P2 snapshot, after the validation gate passes, so the auto-merge
|
|
59
|
+
-- gate is never computed from a stale/unvalidated projection. component_id is a synthetic
|
|
60
|
+
-- per-snapshot WCC grouping label (NOT an FK).
|
|
61
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
62
|
+
CREATE TABLE entity_graph_metrics (
|
|
63
|
+
deployment_id uuid NOT NULL REFERENCES deployments,
|
|
64
|
+
entity_id uuid NOT NULL, -- composite FK below
|
|
65
|
+
snapshot_id uuid NOT NULL, -- composite FK below (a P2_graph snapshot)
|
|
66
|
+
community_id uuid, -- this entity's community in this snapshot (composite FK below)
|
|
67
|
+
pagerank double precision, -- salience prior (retrieval rank + K3 filter)
|
|
68
|
+
degree integer, -- relation degree — copied into entities.graph_degree from the latest published snapshot only
|
|
69
|
+
k_core integer, -- k-core number (hub-ness)
|
|
70
|
+
component_id uuid, -- synthetic per-snapshot weakly-connected-component label (NOT an FK; scoped to snapshot_id)
|
|
71
|
+
computed_at timestamptz NOT NULL DEFAULT now(),
|
|
72
|
+
PRIMARY KEY (deployment_id, entity_id, snapshot_id),
|
|
73
|
+
FOREIGN KEY (deployment_id, entity_id) REFERENCES entities (deployment_id, entity_id) ON DELETE CASCADE,
|
|
74
|
+
FOREIGN KEY (deployment_id, snapshot_id) REFERENCES projection_snapshots (deployment_id, snapshot_id) ON DELETE CASCADE,
|
|
75
|
+
FOREIGN KEY (deployment_id, community_id) REFERENCES communities (deployment_id, community_id) ON DELETE SET NULL (community_id)
|
|
76
|
+
);
|
|
77
|
+
COMMENT ON TABLE entity_graph_metrics IS
|
|
78
|
+
'Per-entity graph analytics written back from each P2 rebuild (D11): PageRank salience, degree (blast-radius), k-core, community, WCC. Read by retrieval ranking, K3 filtering, ER health checks. GC''d when its snapshot is superseded. entities.graph_degree is refreshed only from the published is_latest snapshot.';
|
|
79
|
+
CREATE INDEX ix_egm_entity ON entity_graph_metrics (entity_id);
|
|
80
|
+
CREATE INDEX ix_egm_snapshot ON entity_graph_metrics (snapshot_id);
|
|
81
|
+
|
|
82
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
83
|
+
-- knowledge_artifacts — the PG handle on a K-plane git file (D1, D45–D47). page_kind is the
|
|
84
|
+
-- D46 ownership contract: 'compiled' bodies are machine-owned (regenerated when stale; human
|
|
85
|
+
-- input only via the curation sidecar); 'authored' bodies are human/agent-owned (never
|
|
86
|
+
-- machine-written; evidence changes raise review flags, not recompiles). parent_artifact_id is
|
|
87
|
+
-- the tree the driver compiles in dependency order (children before parents — parents consume
|
|
88
|
+
-- child page_summary values, never re-read child files). inputs_hash is the D45 staleness key.
|
|
89
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
90
|
+
CREATE TABLE knowledge_artifacts (
|
|
91
|
+
artifact_id uuid PRIMARY KEY,
|
|
92
|
+
deployment_id uuid NOT NULL REFERENCES deployments,
|
|
93
|
+
layer knowledge_layer NOT NULL, -- K1 | K2 | K3 — content tier (D47), one mechanism
|
|
94
|
+
page_kind knowledge_page_kind NOT NULL, -- compiled | authored (D46)
|
|
95
|
+
scope_id uuid, -- non-null for K2 scope artifacts (composite FK below)
|
|
96
|
+
parent_artifact_id uuid, -- tree/DAG position (composite FK below)
|
|
97
|
+
git_path text NOT NULL, -- path of the markdown file in the K repo
|
|
98
|
+
curation_path text, -- compiled pages: the human curation sidecar file (D46)
|
|
99
|
+
kind text, -- 'summary' | 'profile' | 'belief' | 'decision_log' | 'model_page' | ...
|
|
100
|
+
page_summary text, -- writer-emitted 2–3 sentence abstract; what PARENT compiles consume
|
|
101
|
+
content_hash text, -- hash of the git file at last compile/sync (drift + quarantine detection, D46)
|
|
102
|
+
inputs_hash text, -- D45 staleness key: hash(candidate evidence IDs + validity fingerprints,
|
|
103
|
+
-- curation sidecar, child summaries, shared model page, writer prompt/model version)
|
|
104
|
+
writer_version text, -- LOGICAL FK → pipeline_component_versions (knowledge_writer); NULL on authored pages
|
|
105
|
+
last_compiled_at timestamptz,
|
|
106
|
+
status knowledge_artifact_status NOT NULL DEFAULT 'active', -- active | stale | quarantined | tombstoned
|
|
107
|
+
UNIQUE (deployment_id, git_path),
|
|
108
|
+
UNIQUE (deployment_id, artifact_id), -- composite-FK target
|
|
109
|
+
FOREIGN KEY (deployment_id, scope_id) REFERENCES scopes (deployment_id, scope_id) ON DELETE SET NULL (scope_id),
|
|
110
|
+
FOREIGN KEY (deployment_id, parent_artifact_id) REFERENCES knowledge_artifacts (deployment_id, artifact_id),
|
|
111
|
+
CHECK (page_kind = 'compiled' OR writer_version IS NULL) -- authored bodies are never machine-written (D46)
|
|
112
|
+
);
|
|
113
|
+
COMMENT ON TABLE knowledge_artifacts IS
|
|
114
|
+
'PG handle + compile state per K-plane git file (D45–D47). page_kind = the D46 ownership contract (compiled: machine-owned, regenerated; authored: human-owned, review-flagged). inputs_hash = the D45 mechanical staleness key (stale iff recomputed hash differs). parent_artifact_id = the compile DAG. Git holds content; PG holds control.';
|
|
115
|
+
CREATE INDEX ix_kartifacts_scope ON knowledge_artifacts (scope_id);
|
|
116
|
+
CREATE INDEX ix_kartifacts_parent ON knowledge_artifacts (parent_artifact_id) WHERE parent_artifact_id IS NOT NULL;
|
|
117
|
+
CREATE INDEX ix_kartifacts_stale ON knowledge_artifacts (deployment_id) WHERE status = 'stale';
|
|
118
|
+
|
|
119
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
120
|
+
-- knowledge_plan_decisions — the planner's append-only STRUCTURE transcript (D45; the D33
|
|
121
|
+
-- ledger discipline applied to structure). Low-blast-radius decisions auto-apply; restructures
|
|
122
|
+
-- above the band queue as 'proposed' for the deployment's accountable reviewer — a human or a
|
|
123
|
+
-- designated reviewer agent (the D24 pattern; k_layers §7). Exception: convert_kind in the
|
|
124
|
+
-- authored→compiled direction NEVER auto-applies (author confirmation).
|
|
125
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
126
|
+
CREATE TABLE knowledge_plan_decisions (
|
|
127
|
+
decision_id uuid PRIMARY KEY,
|
|
128
|
+
deployment_id uuid NOT NULL REFERENCES deployments,
|
|
129
|
+
scope_id uuid, -- composite FK below
|
|
130
|
+
action plan_action NOT NULL, -- create_page | split_page | merge_pages | move_page | retire_page | adjust_rule | convert_kind
|
|
131
|
+
payload jsonb NOT NULL, -- paths, rule diffs, rationale text
|
|
132
|
+
trigger plan_trigger NOT NULL, -- orphan_evidence | size_overflow | community_change | reflection | writer_suggestion | human
|
|
133
|
+
planner_version text NOT NULL, -- LOGICAL FK → pipeline_component_versions (knowledge_planner)
|
|
134
|
+
status plan_decision_status NOT NULL DEFAULT 'proposed', -- proposed | applied | rejected
|
|
135
|
+
decided_at timestamptz NOT NULL DEFAULT now(),
|
|
136
|
+
FOREIGN KEY (deployment_id, scope_id) REFERENCES scopes (deployment_id, scope_id) ON DELETE CASCADE
|
|
137
|
+
);
|
|
138
|
+
COMMENT ON TABLE knowledge_plan_decisions IS
|
|
139
|
+
'Append-only planner transcript (D45): every create/split/merge/move/retire/rule change with trigger + rationale. Reviewable, revertible structure — the opposite of emergent session behavior. Blast-radius-gated auto-apply (D24 pattern).';
|
|
140
|
+
CREATE INDEX ix_kplan_proposed ON knowledge_plan_decisions (deployment_id, decided_at) WHERE status = 'proposed';
|
|
141
|
+
|
|
142
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
143
|
+
-- knowledge_subscriptions — the DISPATCH consumers (the K trigger surface, k_layers §5; the
|
|
144
|
+
-- E→K signal channel D42 deferred, now designed). Binds match criteria — an owned routing rule
|
|
145
|
+
-- (below) and/or page watches — to a workflow endpoint. Dispatch is DEBOUNCED per subscription
|
|
146
|
+
-- and delivered with the D12 worker discipline (Cloud Tasks, retries, DLQ, idempotent
|
|
147
|
+
-- consumers); the payload carries the delta (matched evidence + citation/validity changes),
|
|
148
|
+
-- never a bare ping. The memory system only notifies + serves context — it never runs the
|
|
149
|
+
-- subscriber's logic (subscribers are operating agents outside the system boundary).
|
|
150
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
151
|
+
CREATE TABLE knowledge_subscriptions (
|
|
152
|
+
subscription_id uuid PRIMARY KEY,
|
|
153
|
+
deployment_id uuid NOT NULL REFERENCES deployments,
|
|
154
|
+
scope_id uuid, -- optional owning scope (composite FK below)
|
|
155
|
+
name text NOT NULL, -- e.g. 'planning-module-replan'
|
|
156
|
+
workflow_endpoint text NOT NULL, -- the agentic workflow invoked on dispatch (Cloud Tasks target)
|
|
157
|
+
debounce_seconds integer NOT NULL, -- per-subscription batch window (starting point, measure — k_layers §11 spike 8)
|
|
158
|
+
status subscription_status NOT NULL DEFAULT 'active', -- active | paused | retired
|
|
159
|
+
created_by text, -- registering agent/human
|
|
160
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
161
|
+
UNIQUE (deployment_id, name),
|
|
162
|
+
FOREIGN KEY (deployment_id, scope_id) REFERENCES scopes (deployment_id, scope_id) ON DELETE CASCADE
|
|
163
|
+
);
|
|
164
|
+
COMMENT ON TABLE knowledge_subscriptions IS
|
|
165
|
+
'Dispatch consumers of the K trigger surface (k_layers §5). Match criteria = owned routing rules and/or page watches; consequence = debounced workflow invocation carrying the evidence delta. The E→K signal channel D42 deferred.';
|
|
166
|
+
|
|
167
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
168
|
+
-- knowledge_page_rules — the ROUTING RULES (D45): the recorded answer to "what evidence
|
|
169
|
+
-- belongs to this OWNER". Mechanical: each rule_kind has ONE fixed SQL evaluation
|
|
170
|
+
-- (k_layers_design.md §5); an LLM chooses the rule, SQL evaluates it — no LLM on the routing
|
|
171
|
+
-- path (the D9 rule applied to routing). An owner may hold several rules (union). The owner is
|
|
172
|
+
-- EXACTLY ONE of a page or a subscription, and the rule's CONSEQUENCE derives from it:
|
|
173
|
+
-- compiled page → stale/recompile; authored page → an 'authored_review' flag (a watch rule,
|
|
174
|
+
-- D46); subscription → dispatch (k_layers §5). Page-owned rules require a plan decision;
|
|
175
|
+
-- subscription-owned rules are accounted by the subscription's created_by.
|
|
176
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
177
|
+
CREATE TABLE knowledge_page_rules (
|
|
178
|
+
rule_id uuid PRIMARY KEY,
|
|
179
|
+
deployment_id uuid NOT NULL REFERENCES deployments,
|
|
180
|
+
artifact_id uuid, -- the page this rule feeds (XOR subscription_id; composite FK below)
|
|
181
|
+
subscription_id uuid REFERENCES knowledge_subscriptions (subscription_id) ON DELETE CASCADE,
|
|
182
|
+
rule_kind knowledge_rule_kind NOT NULL,
|
|
183
|
+
params jsonb NOT NULL, -- e.g. {"entity_id": …, "predicates": ["works_for"], "layers": ["relations","observations","claims"]}
|
|
184
|
+
status ontology_status NOT NULL DEFAULT 'active',
|
|
185
|
+
plan_decision_id uuid REFERENCES knowledge_plan_decisions (decision_id), -- who created it and why (page-owned rules)
|
|
186
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
187
|
+
CHECK (num_nonnulls(artifact_id, subscription_id) = 1), -- exactly one owner
|
|
188
|
+
CHECK ((artifact_id IS NOT NULL) = (plan_decision_id IS NOT NULL)), -- plan-decided iff page-owned
|
|
189
|
+
FOREIGN KEY (deployment_id, artifact_id) REFERENCES knowledge_artifacts (deployment_id, artifact_id) ON DELETE CASCADE
|
|
190
|
+
);
|
|
191
|
+
COMMENT ON TABLE knowledge_page_rules IS
|
|
192
|
+
'D45 routing rules, owned by a page XOR a subscription (the trigger surface, k_layers §5). Closed kind set; params per kind; union across an owner''s rules. manual = the editorial escape hatch. Evidence matching NO rule in a scope = orphan → a planner trigger.';
|
|
193
|
+
|
|
194
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
195
|
+
-- knowledge_rule_keys — the routing INVERTED INDEX (D45): rule match keys materialized so that
|
|
196
|
+
-- routing a batch of new evidence is one indexed lookup (the D4 block-first philosophy — exact
|
|
197
|
+
-- keys narrow; nothing expensive runs corpus-wide). Derived-membership rules (entity_subtree
|
|
198
|
+
-- via the part_of closure; community via the D11 writeback) get their keys RE-MATERIALIZED by
|
|
199
|
+
-- the driver when their inputs change — both arrive as ordinary evidence events.
|
|
200
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
201
|
+
CREATE TABLE knowledge_rule_keys (
|
|
202
|
+
deployment_id uuid NOT NULL, -- LOGICAL FK → deployments (tenancy-leading lookup index below)
|
|
203
|
+
rule_id uuid NOT NULL REFERENCES knowledge_page_rules (rule_id) ON DELETE CASCADE,
|
|
204
|
+
key_kind rule_key_kind NOT NULL, -- entity | predicate | community | doc_source
|
|
205
|
+
key_value text NOT NULL, -- uuid-as-text for entity/community; predicate name; doc source
|
|
206
|
+
PRIMARY KEY (rule_id, key_kind, key_value)
|
|
207
|
+
);
|
|
208
|
+
CREATE INDEX ix_krule_keys_lookup ON knowledge_rule_keys (deployment_id, key_kind, key_value);
|
|
209
|
+
COMMENT ON TABLE knowledge_rule_keys IS
|
|
210
|
+
'Inverted index over rule match keys (D45): new evidence → its E-plane labels (entities, predicate, community, doc source) → the rules (page- or subscription-owned) it affects, in one lookup. The key set of a derived-membership rule is re-materialized when its inputs change.';
|
|
211
|
+
|
|
212
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
213
|
+
-- knowledge_page_watches — PAGE-LEVEL watch targets (k_layers §5): subscribe to another page's
|
|
214
|
+
-- recompiles instead of re-declaring its rules (the paired-workbench ergonomics — a gap
|
|
215
|
+
-- analysis watches the compiled to-be page it judges, and stays subscribed as the planner
|
|
216
|
+
-- adjusts that page's rules). Watcher is EXACTLY ONE of an authored page (consequence: an
|
|
217
|
+
-- 'authored_review' flag) or a subscription (consequence: dispatch). Same edge type as the
|
|
218
|
+
-- compile DAG's parent→child dependency, different consequence.
|
|
219
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
220
|
+
CREATE TABLE knowledge_page_watches (
|
|
221
|
+
watch_id uuid PRIMARY KEY,
|
|
222
|
+
deployment_id uuid NOT NULL,
|
|
223
|
+
watcher_artifact_id uuid, -- an authored page … (XOR subscription_id)
|
|
224
|
+
subscription_id uuid REFERENCES knowledge_subscriptions (subscription_id) ON DELETE CASCADE,
|
|
225
|
+
watched_artifact_id uuid NOT NULL, -- the page whose recompiles are watched
|
|
226
|
+
CHECK (num_nonnulls(watcher_artifact_id, subscription_id) = 1),
|
|
227
|
+
FOREIGN KEY (deployment_id, watcher_artifact_id) REFERENCES knowledge_artifacts (deployment_id, artifact_id) ON DELETE CASCADE,
|
|
228
|
+
FOREIGN KEY (deployment_id, watched_artifact_id) REFERENCES knowledge_artifacts (deployment_id, artifact_id) ON DELETE CASCADE
|
|
229
|
+
);
|
|
230
|
+
CREATE UNIQUE INDEX ux_kwatch ON knowledge_page_watches (watcher_artifact_id, subscription_id, watched_artifact_id) NULLS NOT DISTINCT;
|
|
231
|
+
CREATE INDEX ix_kwatch_watched ON knowledge_page_watches (watched_artifact_id);
|
|
232
|
+
COMMENT ON TABLE knowledge_page_watches IS
|
|
233
|
+
'Page-level watches (k_layers §5): a watcher (authored page XOR subscription) subscribes to a watched page''s recompiles. Consequence derives from the watcher: flag or dispatch. Synced from authored frontmatter (watch: page:<path>) or registered with a subscription.';
|
|
234
|
+
|
|
235
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
236
|
+
-- knowledge_dispatches — the append-only DISPATCH transcript (k_layers §5). The driver
|
|
237
|
+
-- coalesces a subscription's matches over its debounce window into ONE row whose payload
|
|
238
|
+
-- carries the delta (matched evidence IDs, citation/validity changes, affected page refs);
|
|
239
|
+
-- delivery is at-least-once (Cloud Tasks, D12 retries/DLQ) — subscriber workflows must be
|
|
240
|
+
-- idempotent per dispatch_id.
|
|
241
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
242
|
+
CREATE TABLE knowledge_dispatches (
|
|
243
|
+
dispatch_id uuid PRIMARY KEY,
|
|
244
|
+
deployment_id uuid NOT NULL REFERENCES deployments,
|
|
245
|
+
subscription_id uuid NOT NULL REFERENCES knowledge_subscriptions (subscription_id) ON DELETE CASCADE,
|
|
246
|
+
payload jsonb NOT NULL, -- {matched_evidence_ids, deltas, page_refs} — the delta, never a bare ping
|
|
247
|
+
status refresh_status NOT NULL DEFAULT 'pending', -- pending | running | done | failed
|
|
248
|
+
enqueued_at timestamptz NOT NULL DEFAULT now(),
|
|
249
|
+
delivered_at timestamptz
|
|
250
|
+
);
|
|
251
|
+
CREATE INDEX ix_kdispatch_pending ON knowledge_dispatches (deployment_id, status) WHERE status = 'pending';
|
|
252
|
+
COMMENT ON TABLE knowledge_dispatches IS
|
|
253
|
+
'Append-only dispatch transcript (k_layers §5): one debounce-coalesced row per subscription window, delta-carrying payload, at-least-once delivery with idempotent consumers (keyed by dispatch_id). Makes the E→K trigger surface auditable like every other non-deterministic boundary (D33 discipline).';
|
|
254
|
+
|
|
255
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
256
|
+
-- knowledge_compilations — the append-only COMPILE transcript (D45; D33 for content).
|
|
257
|
+
-- uncited_count is the K-plane analogue of the Selection-drop ledger: rule-matched evidence the
|
|
258
|
+
-- writer chose not to cite is counted, so "why isn''t fact X on this page?" has an answer.
|
|
259
|
+
-- git_commit is two-phase: the row is written before the push, the sha stamped after; startup
|
|
260
|
+
-- reconciles repo HEAD against the newest committed rows.
|
|
261
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
262
|
+
CREATE TABLE knowledge_compilations (
|
|
263
|
+
compilation_id uuid PRIMARY KEY,
|
|
264
|
+
deployment_id uuid NOT NULL REFERENCES deployments,
|
|
265
|
+
artifact_id uuid NOT NULL, -- composite FK below
|
|
266
|
+
inputs_hash text NOT NULL, -- the candidate snapshot this compile consumed (D45 idempotency)
|
|
267
|
+
candidate_count int NOT NULL, -- rule-matched evidence offered to the writer
|
|
268
|
+
cited_count int NOT NULL, -- evidence the writer used (→ knowledge_artifact_evidence)
|
|
269
|
+
uncited_count int NOT NULL, -- offered but not used (auditable coverage gap)
|
|
270
|
+
evidence_added int NOT NULL DEFAULT 0, -- citation-set delta vs the previous compile
|
|
271
|
+
evidence_removed int NOT NULL DEFAULT 0,
|
|
272
|
+
evidence_invalidated int NOT NULL DEFAULT 0,
|
|
273
|
+
writer_version text NOT NULL, -- LOGICAL FK → pipeline_component_versions (knowledge_writer)
|
|
274
|
+
tokens integer, cost_usd numeric, -- cost metering (requirements: per-layer budgets)
|
|
275
|
+
session_transcript_uri text, -- archived writer-session transcript (GCS) — the residual read-audit log for stock-harness writers (k_layers §7); NULL when a session left no transcript
|
|
276
|
+
git_commit text,
|
|
277
|
+
compiled_at timestamptz NOT NULL DEFAULT now(),
|
|
278
|
+
FOREIGN KEY (deployment_id, artifact_id) REFERENCES knowledge_artifacts (deployment_id, artifact_id) ON DELETE CASCADE
|
|
279
|
+
);
|
|
280
|
+
CREATE INDEX ix_kcompilations_artifact ON knowledge_compilations (artifact_id, compiled_at DESC);
|
|
281
|
+
COMMENT ON TABLE knowledge_compilations IS
|
|
282
|
+
'Append-only compile transcript per page (D45): inputs snapshot, candidate/cited/uncited counts, citation deltas, versions, cost, commit. Makes compiles idempotent (inputs_hash), auditable, and replayable-from-storage like every non-deterministic stage (D7/D33).';
|
|
283
|
+
|
|
284
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
285
|
+
-- knowledge_artifact_evidence — the CITATIONS: page ⇄ evidence links (D45/D46; K3 requirement +
|
|
286
|
+
-- deletion cascade). A BINDING output contract, not self-reported provenance: on a compiled page
|
|
287
|
+
-- the driver REPLACES these rows from the writer's returned citations each compile; on an
|
|
288
|
+
-- authored page they are synced from the page's frontmatter (`cites:`). Evidence-change
|
|
289
|
+
-- staleness, authored review flags, and deletion reach are reverse lookups through this table.
|
|
290
|
+
-- A single link targets EXACTLY ONE of claim/relation/doc (the others NULL) — so a surrogate PK
|
|
291
|
+
-- + a num_nonnulls CHECK + a NULL-tolerant unique index, NOT an all-columns PK (PK columns
|
|
292
|
+
-- cannot be NULL).
|
|
293
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
294
|
+
CREATE TABLE knowledge_artifact_evidence (
|
|
295
|
+
evidence_link_id uuid PRIMARY KEY,
|
|
296
|
+
deployment_id uuid NOT NULL REFERENCES deployments,
|
|
297
|
+
artifact_id uuid NOT NULL, -- composite FK below, ON DELETE CASCADE
|
|
298
|
+
claim_id uuid, -- LOGICAL FK → claims (partitioned)
|
|
299
|
+
relation_id uuid, -- composite FK below, ON DELETE CASCADE (real, relations is not partitioned)
|
|
300
|
+
doc_id uuid, -- LOGICAL FK → documents
|
|
301
|
+
role knowledge_evidence_role NOT NULL, -- supports | contradicts | cites (K3 links supporting AND contradicting evidence)
|
|
302
|
+
CHECK (num_nonnulls(claim_id, relation_id, doc_id) = 1), -- exactly one target per link
|
|
303
|
+
FOREIGN KEY (deployment_id, artifact_id) REFERENCES knowledge_artifacts (deployment_id, artifact_id) ON DELETE CASCADE,
|
|
304
|
+
FOREIGN KEY (deployment_id, relation_id) REFERENCES relations (deployment_id, relation_id) ON DELETE CASCADE
|
|
305
|
+
);
|
|
306
|
+
COMMENT ON TABLE knowledge_artifact_evidence IS
|
|
307
|
+
'Citations (D45/D46): the ONE claim/relation/document each link rests on, role supports|contradicts|cites. Binding writer output on compiled pages (replaced per compile); frontmatter-synced on authored pages. Drives exact incremental refresh (D12), authored review flags (D46), and the deletion cascade. Exactly-one-target enforced by CHECK; surrogate PK because the targets are nullable alternatives.';
|
|
308
|
+
-- NULL-tolerant dedup (one link per (artifact, target, role)); NULLS NOT DISTINCT treats the two
|
|
309
|
+
-- NULL targets as equal so the populated one is the discriminator:
|
|
310
|
+
CREATE UNIQUE INDEX ux_kae_link ON knowledge_artifact_evidence (artifact_id, role, claim_id, relation_id, doc_id) NULLS NOT DISTINCT;
|
|
311
|
+
CREATE INDEX ix_kae_claim ON knowledge_artifact_evidence (claim_id) WHERE claim_id IS NOT NULL;
|
|
312
|
+
CREATE INDEX ix_kae_relation ON knowledge_artifact_evidence (relation_id) WHERE relation_id IS NOT NULL;
|
|
313
|
+
CREATE INDEX ix_kae_doc ON knowledge_artifact_evidence (doc_id) WHERE doc_id IS NOT NULL;
|
|
314
|
+
|
|
315
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
316
|
+
-- knowledge_refresh_queue — the debounced trigger queue (D12) the D45 driver consumes at cycle
|
|
317
|
+
-- start. Evidence-change events carry the changed IDs; the driver ROUTES them to pages via
|
|
318
|
+
-- knowledge_rule_keys + the citation reverse lookup — artifact_id is therefore NULL on evidence
|
|
319
|
+
-- batches (routing is mechanical, no longer "decide which" by an LLM at processing time) and
|
|
320
|
+
-- set only on targeted triggers (authored_review, tombstone, manual). not_before is the plain
|
|
321
|
+
-- debounce delay — the hot-file rationale is gone (D45: the root index is just the last DAG
|
|
322
|
+
-- target, compiled once per cycle). This is domain-trigger aggregation, not D61 task delivery:
|
|
323
|
+
-- once the driver materializes a K job, its unlaned processing_state row and that row's
|
|
324
|
+
-- not_before are authoritative under D67.
|
|
325
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
326
|
+
CREATE TABLE knowledge_refresh_queue (
|
|
327
|
+
refresh_id uuid PRIMARY KEY,
|
|
328
|
+
deployment_id uuid NOT NULL REFERENCES deployments,
|
|
329
|
+
artifact_id uuid, -- composite FK below (nullable); NULL on evidence batches — routing via rule keys (D45)
|
|
330
|
+
scope_id uuid, -- composite FK below
|
|
331
|
+
trigger knowledge_trigger NOT NULL, -- evidence_changed | community_changed | debounce_timer | manual | tombstone | authored_review
|
|
332
|
+
payload jsonb, -- e.g. {changed_relation_ids:[…]} | {changed_claim_ids:[…]} | {community_id:…} | {deleted_doc_id:…}
|
|
333
|
+
not_before timestamptz, -- debounce delay — don't process before this
|
|
334
|
+
status refresh_status NOT NULL DEFAULT 'pending', -- pending | running | done | failed
|
|
335
|
+
enqueued_at timestamptz NOT NULL DEFAULT now(),
|
|
336
|
+
processed_at timestamptz,
|
|
337
|
+
FOREIGN KEY (deployment_id, artifact_id) REFERENCES knowledge_artifacts (deployment_id, artifact_id) ON DELETE CASCADE,
|
|
338
|
+
FOREIGN KEY (deployment_id, scope_id) REFERENCES scopes (deployment_id, scope_id) ON DELETE CASCADE
|
|
339
|
+
);
|
|
340
|
+
COMMENT ON TABLE knowledge_refresh_queue IS
|
|
341
|
+
'Debounced domain-trigger queue for the K compile driver (D12/D45), not D61 delivery state. Evidence batches route mechanically; authored_review surfaces D46 flags; this not_before coalesces triggers, while a materialized K job is delivered only from its unlaned processing_state row (D67).';
|
|
342
|
+
CREATE INDEX ix_krefresh_runnable ON knowledge_refresh_queue (deployment_id, status, not_before) WHERE status = 'pending';
|
|
343
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
344
|
+
-- retrieval_recipes — frozen query plans as registry data (D50). One row per recipe version;
|
|
345
|
+
-- surfaces (API/CLI/MCP) render from status='active' rows. The CHECK is the mechanical half
|
|
346
|
+
-- of the grain linter (D41/D49); the registration linter validates the chain itself.
|
|
347
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
348
|
+
CREATE TABLE retrieval_recipes (
|
|
349
|
+
recipe_id uuid PRIMARY KEY,
|
|
350
|
+
deployment_id uuid NOT NULL REFERENCES deployments,
|
|
351
|
+
name text NOT NULL, -- e.g. 'relation_hybrid_rrf', 'claims_as_of', 'identity_as_of'
|
|
352
|
+
description text NOT NULL, -- rendered into the MCP tool description (D50)
|
|
353
|
+
parameters jsonb NOT NULL, -- typed parameter schema (JSON-Schema form)
|
|
354
|
+
chain jsonb NOT NULL, -- the typed primitive composition: ordered ops + fixed settings (channel sets, RRF constants, rerank weights)
|
|
355
|
+
output_grain recipe_output_grain NOT NULL, -- fact | evidence | compiled | composite (the D49 envelope grain)
|
|
356
|
+
answer_intent recipe_answer_intent NOT NULL, -- current_facts | assertion_history | orientation | audit | change_feed
|
|
357
|
+
version integer NOT NULL DEFAULT 1, -- recall@k measured per (name, version) — regressions attributable (D22)
|
|
358
|
+
status ontology_status NOT NULL DEFAULT 'active',
|
|
359
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
360
|
+
UNIQUE (deployment_id, name, version),
|
|
361
|
+
CHECK (answer_intent <> 'current_facts' OR output_grain = 'fact') -- the D41 bar, mechanical
|
|
362
|
+
);
|
|
363
|
+
COMMENT ON TABLE retrieval_recipes IS
|
|
364
|
+
'D50: recipes as registry rows. MCP tools render from here; the eval harness measures per (name, version); the CHECK enforces the D41 grain bar mechanically (current_facts ⇒ fact grain), with chain-level validation in the registration linter. Adding a query pattern = inserting a row.';
|
|
365
|
+
"""
|
|
366
|
+
_TABLES = (
|
|
367
|
+
"projection_snapshots",
|
|
368
|
+
"communities",
|
|
369
|
+
"entity_graph_metrics",
|
|
370
|
+
"knowledge_artifacts",
|
|
371
|
+
"knowledge_plan_decisions",
|
|
372
|
+
"knowledge_subscriptions",
|
|
373
|
+
"knowledge_page_rules",
|
|
374
|
+
"knowledge_rule_keys",
|
|
375
|
+
"knowledge_page_watches",
|
|
376
|
+
"knowledge_dispatches",
|
|
377
|
+
"knowledge_compilations",
|
|
378
|
+
"knowledge_artifact_evidence",
|
|
379
|
+
"knowledge_refresh_queue",
|
|
380
|
+
"retrieval_recipes",
|
|
381
|
+
)
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
def upgrade() -> None:
|
|
385
|
+
"""Apply create projection, knowledge, and retrieval structures."""
|
|
386
|
+
apply_ddl(sql=_DDL)
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
def downgrade() -> None:
|
|
390
|
+
"""Revert create projection, knowledge, and retrieval structures."""
|
|
391
|
+
drop_tables(table_names=reversed(_TABLES))
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"""Register RANGE families with pg_partman and create projection views."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Sequence
|
|
4
|
+
|
|
5
|
+
from alembic import op
|
|
6
|
+
|
|
7
|
+
from rememberstack.spine.migrations._helpers import apply_ddl
|
|
8
|
+
|
|
9
|
+
revision: str = "p0_02_0006"
|
|
10
|
+
down_revision: str | None = "p0_02_0005"
|
|
11
|
+
branch_labels: str | Sequence[str] | None = None
|
|
12
|
+
depends_on: str | Sequence[str] | None = None
|
|
13
|
+
|
|
14
|
+
_RANGE_PARENTS = (
|
|
15
|
+
("mentions", "created_at"),
|
|
16
|
+
("resolution_decisions", "decided_at"),
|
|
17
|
+
("chunks", "created_at"),
|
|
18
|
+
("chunk_claims", "created_at"),
|
|
19
|
+
("claims", "ingested_at"),
|
|
20
|
+
("claim_extraction_decisions", "decided_at"),
|
|
21
|
+
("testimony_currency_events", "occurred_at"),
|
|
22
|
+
)
|
|
23
|
+
_VIEWS = (
|
|
24
|
+
"v_graph_survivor",
|
|
25
|
+
"v_graph_entities",
|
|
26
|
+
"v_graph_documents",
|
|
27
|
+
"v_graph_relates",
|
|
28
|
+
"v_graph_mentioned_in",
|
|
29
|
+
"v_graph_crossref",
|
|
30
|
+
"v_graph_is_document",
|
|
31
|
+
)
|
|
32
|
+
_VIEW_DDL = r"""-- Resolve every entity id to its final merge SURVIVOR. A merge is a REDIRECT, not a rewrite
|
|
33
|
+
-- (entities.merged_into; entity_id never reused) and relations are NOT re-pointed in PG — so endpoints
|
|
34
|
+
-- MUST be redirected here, or the rebuild silently drops every edge touching a merged entity. Cycle-safe
|
|
35
|
+
-- (merged_into acyclicity is not schema-enforced); the rebuild's validation gate (below) aborts the
|
|
36
|
+
-- snapshot if any retained endpoint fails to resolve to exactly one emitted survivor.
|
|
37
|
+
CREATE VIEW v_graph_survivor AS
|
|
38
|
+
WITH RECURSIVE chain(entity_id, cur, depth) AS (
|
|
39
|
+
SELECT entity_id, entity_id, 0 FROM entities
|
|
40
|
+
UNION ALL
|
|
41
|
+
SELECT c.entity_id, e.merged_into, c.depth + 1
|
|
42
|
+
FROM chain c JOIN entities e ON e.entity_id = c.cur
|
|
43
|
+
WHERE e.merged_into IS NOT NULL AND c.depth < 64 -- cycle / runaway guard
|
|
44
|
+
)
|
|
45
|
+
SELECT entity_id,
|
|
46
|
+
(SELECT cur FROM chain x WHERE x.entity_id = chain.entity_id ORDER BY depth DESC LIMIT 1) AS survivor
|
|
47
|
+
FROM chain GROUP BY entity_id; -- survivor = the terminal (merged_into IS NULL) node of each chain
|
|
48
|
+
|
|
49
|
+
-- Nodes: survivors only; cast timestamps. Graph-derived metrics (pagerank/graph_degree) are NOT loaded —
|
|
50
|
+
-- they are computed POST-load (D11); reprojecting a stored value is circular. entity_id stays native UUID
|
|
51
|
+
-- (PK verified in LadybugDB source/tests; STRING fallback = entity_id::text, applied uniformly to the PK
|
|
52
|
+
-- AND every endpoint).
|
|
53
|
+
CREATE VIEW v_graph_entities AS
|
|
54
|
+
SELECT entity_id AS id, type, canonical_name AS name, normalized_name,
|
|
55
|
+
profile_summary AS summary, (created_at AT TIME ZONE 'UTC') AS created_at
|
|
56
|
+
FROM entities WHERE status = 'active'; -- merged/retired entities are not nodes
|
|
57
|
+
|
|
58
|
+
CREATE VIEW v_graph_documents AS
|
|
59
|
+
SELECT d.doc_id AS id, d.title, d.source_uri,
|
|
60
|
+
(dv.published_at AT TIME ZONE 'UTC')::date AS published_at -- the CURRENT version's date (D55); NULL when unset
|
|
61
|
+
FROM documents d
|
|
62
|
+
LEFT JOIN document_versions dv
|
|
63
|
+
ON dv.deployment_id = d.deployment_id AND dv.version_id = d.current_version_id
|
|
64
|
+
WHERE d.deleted_at IS NULL; -- lineages project; a lineage mid-ingest (no current version yet) projects with NULL date (F2)
|
|
65
|
+
|
|
66
|
+
-- Edges: endpoints are the FIRST TWO columns (FROM, TO), survivor-redirected and guarded so both
|
|
67
|
+
-- endpoints exist as emitted nodes (else COPY-REL throws). Keep EVERY invalidated edge by default for
|
|
68
|
+
-- transaction-time as-of (D69): there is no invalidation-age filter and a closed valid-time fact is
|
|
69
|
+
-- unaffected. Endpoint joins are the retention boundary. Parallel edges with distinct relation_id are
|
|
70
|
+
-- PRESERVED (no blind DISTINCT — same-(s,p,o) collapse is E3's job, D43).
|
|
71
|
+
CREATE VIEW v_graph_relates AS
|
|
72
|
+
SELECT s1.survivor AS "from", s2.survivor AS "to",
|
|
73
|
+
r.relation_id, r.predicate, r.fact_label AS fact,
|
|
74
|
+
r.evidence_count::bigint AS evidence_count, r.contradict_count::bigint AS contradict_count,
|
|
75
|
+
r.confidence::float8 AS confidence, r.contradiction_group,
|
|
76
|
+
(r.valid_from AT TIME ZONE 'UTC') AS valid_from, (r.valid_until AT TIME ZONE 'UTC') AS valid_until,
|
|
77
|
+
(r.ingested_at AT TIME ZONE 'UTC') AS ingested_at, (r.invalidated_at AT TIME ZONE 'UTC') AS invalidated_at
|
|
78
|
+
FROM relations r
|
|
79
|
+
JOIN v_graph_survivor s1 ON s1.entity_id = r.subject_entity_id
|
|
80
|
+
JOIN v_graph_survivor s2 ON s2.entity_id = r.object_entity_id
|
|
81
|
+
JOIN entities e1 ON e1.entity_id = s1.survivor AND e1.status = 'active' -- endpoint emitted as a node
|
|
82
|
+
JOIN entities e2 ON e2.entity_id = s2.survivor AND e2.status = 'active';
|
|
83
|
+
-- relations.status (GENERATED) is DROPPED — liveness is derived in Cypher (invalidated_at IS NULL), D6.
|
|
84
|
+
|
|
85
|
+
CREATE VIEW v_graph_mentioned_in AS -- aggregate: no (entity,doc) base table
|
|
86
|
+
SELECT s.survivor AS "from", m.doc_id AS "to",
|
|
87
|
+
COUNT(*)::bigint AS mention_count, (MIN(m.created_at) AT TIME ZONE 'UTC') AS first_seen
|
|
88
|
+
FROM mentions m
|
|
89
|
+
JOIN resolution_decisions rd ON rd.mention_id = m.mention_id AND rd.superseded_by IS NULL -- live verdict
|
|
90
|
+
JOIN v_graph_survivor s ON s.entity_id = rd.entity_id
|
|
91
|
+
JOIN entities e ON e.entity_id = s.survivor AND e.status = 'active'
|
|
92
|
+
WHERE EXISTS (SELECT 1 FROM documents d WHERE d.doc_id = m.doc_id AND d.deleted_at IS NULL)
|
|
93
|
+
GROUP BY s.survivor, m.doc_id;
|
|
94
|
+
|
|
95
|
+
CREATE VIEW v_graph_crossref AS
|
|
96
|
+
SELECT from_doc_id AS "from", to_doc_id AS "to", kind::text AS kind, context
|
|
97
|
+
FROM document_crossrefs WHERE to_doc_id IS NOT NULL; -- nullable = cited-but-not-ingested → no edge
|
|
98
|
+
|
|
99
|
+
CREATE VIEW v_graph_is_document AS -- bridge: Document-typed Entity ↔ its E0 doc
|
|
100
|
+
SELECT s.survivor AS "from", d.doc_id AS "to"
|
|
101
|
+
FROM documents d
|
|
102
|
+
JOIN v_graph_survivor s ON s.entity_id = d.document_entity_id
|
|
103
|
+
JOIN entities e ON e.entity_id = s.survivor AND e.status = 'active'
|
|
104
|
+
WHERE d.document_entity_id IS NOT NULL AND d.deleted_at IS NULL;
|
|
105
|
+
"""
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def upgrade() -> None:
|
|
109
|
+
"""Register all monthly parents and create final no-filter projection views."""
|
|
110
|
+
for parent, control in _RANGE_PARENTS:
|
|
111
|
+
op.execute(
|
|
112
|
+
"SELECT public.create_parent("
|
|
113
|
+
f"p_parent_table := 'public.{parent}', "
|
|
114
|
+
f"p_control := '{control}', "
|
|
115
|
+
"p_interval := '1 month', "
|
|
116
|
+
"p_type := 'range', "
|
|
117
|
+
"p_premake := 4, "
|
|
118
|
+
"p_default_table := true, "
|
|
119
|
+
"p_automatic_maintenance := 'on', "
|
|
120
|
+
"p_jobmon := false)"
|
|
121
|
+
)
|
|
122
|
+
apply_ddl(sql=_VIEW_DDL)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def downgrade() -> None:
|
|
126
|
+
"""Drop views and unregister only the seven UGM pg_partman parents."""
|
|
127
|
+
for view_name in reversed(_VIEWS):
|
|
128
|
+
op.execute(f"DROP VIEW IF EXISTS {view_name}")
|
|
129
|
+
op.execute(
|
|
130
|
+
"""
|
|
131
|
+
DO $$
|
|
132
|
+
DECLARE
|
|
133
|
+
configured_parent text;
|
|
134
|
+
configured_template text;
|
|
135
|
+
BEGIN
|
|
136
|
+
FOR configured_parent, configured_template IN
|
|
137
|
+
SELECT parent_table, template_table
|
|
138
|
+
FROM public.part_config
|
|
139
|
+
WHERE parent_table = ANY (ARRAY[
|
|
140
|
+
'public.mentions',
|
|
141
|
+
'public.resolution_decisions',
|
|
142
|
+
'public.chunks',
|
|
143
|
+
'public.chunk_claims',
|
|
144
|
+
'public.claims',
|
|
145
|
+
'public.claim_extraction_decisions',
|
|
146
|
+
'public.testimony_currency_events'
|
|
147
|
+
])
|
|
148
|
+
LOOP
|
|
149
|
+
DELETE FROM public.part_config
|
|
150
|
+
WHERE parent_table = configured_parent;
|
|
151
|
+
IF configured_template IS NOT NULL THEN
|
|
152
|
+
EXECUTE 'DROP TABLE IF EXISTS ' || configured_template || ' CASCADE';
|
|
153
|
+
END IF;
|
|
154
|
+
END LOOP;
|
|
155
|
+
END
|
|
156
|
+
$$;
|
|
157
|
+
"""
|
|
158
|
+
)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""Add the `invalidated` adjudication outcome (WP-2.6 review verdicts).
|
|
2
|
+
|
|
3
|
+
A review's invalidate_fact verdict sets a fact's invalidated_at; recording
|
|
4
|
+
that action as `noop` would make the append-only adjudication ledger lie on
|
|
5
|
+
replay (a rebuild would retain the fact). The enum gains the truthful value.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from collections.abc import Sequence
|
|
9
|
+
|
|
10
|
+
from alembic import op
|
|
11
|
+
|
|
12
|
+
revision: str = "p2_06_0007"
|
|
13
|
+
down_revision: str | None = "p0_02_0006"
|
|
14
|
+
branch_labels: str | Sequence[str] | None = None
|
|
15
|
+
depends_on: str | Sequence[str] | None = None
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def upgrade() -> None:
|
|
19
|
+
"""Append the enum value (additive; existing rows untouched)."""
|
|
20
|
+
op.execute("ALTER TYPE adjudication_outcome ADD VALUE IF NOT EXISTS 'invalidated'")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def downgrade() -> None:
|
|
24
|
+
"""PostgreSQL cannot remove an enum value in place; the value is
|
|
25
|
+
additive and unused rows are impossible to strand, so downgrade is a
|
|
26
|
+
deliberate no-op (documented, not silent)."""
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""Add the `document_version` processing target (Phase 3, D55/D12).
|
|
2
|
+
|
|
3
|
+
With multi-version lineages, the E-chain's idempotency key must name the
|
|
4
|
+
VERSION being processed: keying convert/structure/chunk work on the lineage
|
|
5
|
+
would make a second version's work collide with the first version's
|
|
6
|
+
completed row and never run. The enum gains the precise target.
|
|
7
|
+
|
|
8
|
+
Two lifecycle audit columns land alongside it:
|
|
9
|
+
|
|
10
|
+
- ``documents.deleted_sync_cycle_id`` — a source-observed deletion is
|
|
11
|
+
stamped with the cycle that observed it, so reconciliation's
|
|
12
|
+
finalization barrier can place the deletion inside its cycle.
|
|
13
|
+
- ``connector_sync_cycles.failed_items`` — a poll pass that lost items to
|
|
14
|
+
per-item errors says so on its own row; reconciliation must never treat
|
|
15
|
+
a lossy cycle's observation set as complete.
|
|
16
|
+
|
|
17
|
+
And one constraint falls: ``UNIQUE (deployment_id, doc_id, content_hash)``
|
|
18
|
+
on ``document_versions`` encoded a one-version-per-content rule that D55
|
|
19
|
+
does not have — a version is an OBSERVATION event, and content reverted
|
|
20
|
+
A→B→A legitimately recurs as a third version of the same content object
|
|
21
|
+
(content_objects still dedups the bytes themselves).
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from collections.abc import Sequence
|
|
25
|
+
|
|
26
|
+
from alembic import op
|
|
27
|
+
|
|
28
|
+
revision: str = "p3_01_0008"
|
|
29
|
+
down_revision: str | None = "p2_06_0007"
|
|
30
|
+
branch_labels: str | Sequence[str] | None = None
|
|
31
|
+
depends_on: str | Sequence[str] | None = None
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def upgrade() -> None:
|
|
35
|
+
"""Append the enum value and the two audit columns (all additive)."""
|
|
36
|
+
op.execute(
|
|
37
|
+
"ALTER TYPE processing_target ADD VALUE IF NOT EXISTS 'document_version'"
|
|
38
|
+
)
|
|
39
|
+
op.execute("ALTER TABLE documents ADD COLUMN deleted_sync_cycle_id uuid")
|
|
40
|
+
op.execute(
|
|
41
|
+
"ALTER TABLE connector_sync_cycles"
|
|
42
|
+
" ADD COLUMN failed_items integer NOT NULL DEFAULT 0"
|
|
43
|
+
)
|
|
44
|
+
op.execute(
|
|
45
|
+
"ALTER TABLE document_versions"
|
|
46
|
+
" DROP CONSTRAINT document_versions_deployment_id_doc_id_content_hash_key"
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def downgrade() -> None:
|
|
51
|
+
"""Restore the constraint, drop the columns; the enum value stays."""
|
|
52
|
+
op.execute(
|
|
53
|
+
"ALTER TABLE document_versions"
|
|
54
|
+
" ADD CONSTRAINT document_versions_deployment_id_doc_id_content_hash_key"
|
|
55
|
+
" UNIQUE (deployment_id, doc_id, content_hash)"
|
|
56
|
+
)
|
|
57
|
+
op.execute("ALTER TABLE connector_sync_cycles DROP COLUMN failed_items")
|
|
58
|
+
op.execute("ALTER TABLE documents DROP COLUMN deleted_sync_cycle_id")
|