shellbrain 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.
- app/__init__.py +1 -0
- app/__main__.py +7 -0
- app/boot/__init__.py +1 -0
- app/boot/admin_db.py +88 -0
- app/boot/config.py +14 -0
- app/boot/create_policy.py +52 -0
- app/boot/db.py +70 -0
- app/boot/embeddings.py +55 -0
- app/boot/home.py +45 -0
- app/boot/migrations.py +61 -0
- app/boot/read_policy.py +179 -0
- app/boot/repos.py +15 -0
- app/boot/retrieval.py +3 -0
- app/boot/thresholds.py +19 -0
- app/boot/update_policy.py +34 -0
- app/boot/use_cases.py +22 -0
- app/config/__init__.py +1 -0
- app/config/defaults/create_policy.yaml +7 -0
- app/config/defaults/read_policy.yaml +25 -0
- app/config/defaults/runtime.yaml +10 -0
- app/config/defaults/thresholds.yaml +3 -0
- app/config/defaults/update_policy.yaml +5 -0
- app/config/loader.py +58 -0
- app/core/__init__.py +1 -0
- app/core/contracts/__init__.py +1 -0
- app/core/contracts/errors.py +29 -0
- app/core/contracts/requests.py +211 -0
- app/core/contracts/responses.py +15 -0
- app/core/entities/__init__.py +1 -0
- app/core/entities/associations.py +58 -0
- app/core/entities/episodes.py +66 -0
- app/core/entities/evidence.py +29 -0
- app/core/entities/facts.py +30 -0
- app/core/entities/guidance.py +47 -0
- app/core/entities/identity.py +48 -0
- app/core/entities/memory.py +34 -0
- app/core/entities/runtime_context.py +19 -0
- app/core/entities/session_state.py +31 -0
- app/core/entities/telemetry.py +152 -0
- app/core/entities/utility.py +14 -0
- app/core/interfaces/__init__.py +1 -0
- app/core/interfaces/clock.py +12 -0
- app/core/interfaces/config.py +28 -0
- app/core/interfaces/embeddings.py +12 -0
- app/core/interfaces/idgen.py +11 -0
- app/core/interfaces/repos.py +279 -0
- app/core/interfaces/retrieval.py +20 -0
- app/core/interfaces/session_state_store.py +33 -0
- app/core/interfaces/unit_of_work.py +50 -0
- app/core/policies/__init__.py +1 -0
- app/core/policies/_shared/__init__.py +1 -0
- app/core/policies/_shared/executor.py +132 -0
- app/core/policies/_shared/side_effects.py +9 -0
- app/core/policies/create_policy/__init__.py +1 -0
- app/core/policies/create_policy/pipeline.py +96 -0
- app/core/policies/read_policy/__init__.py +1 -0
- app/core/policies/read_policy/bm25.py +114 -0
- app/core/policies/read_policy/context_pack_builder.py +140 -0
- app/core/policies/read_policy/expansion.py +132 -0
- app/core/policies/read_policy/fusion_rrf.py +34 -0
- app/core/policies/read_policy/lexical_query.py +101 -0
- app/core/policies/read_policy/pipeline.py +93 -0
- app/core/policies/read_policy/scenario_lift.py +11 -0
- app/core/policies/read_policy/scoring.py +61 -0
- app/core/policies/read_policy/seed_retrieval.py +54 -0
- app/core/policies/read_policy/utility_prior.py +11 -0
- app/core/policies/update_policy/__init__.py +1 -0
- app/core/policies/update_policy/pipeline.py +80 -0
- app/core/use_cases/__init__.py +1 -0
- app/core/use_cases/build_guidance.py +85 -0
- app/core/use_cases/create_memory.py +26 -0
- app/core/use_cases/manage_session_state.py +159 -0
- app/core/use_cases/read_memory.py +21 -0
- app/core/use_cases/record_episode_sync_telemetry.py +19 -0
- app/core/use_cases/record_operation_telemetry.py +32 -0
- app/core/use_cases/sync_episode.py +162 -0
- app/core/use_cases/update_memory.py +40 -0
- app/migrations/__init__.py +1 -0
- app/migrations/env.py +65 -0
- app/migrations/versions/20260226_0001_initial_schema.py +232 -0
- app/migrations/versions/20260312_0002_add_hard_invariants.py +60 -0
- app/migrations/versions/20260312_0003_drop_create_confidence.py +40 -0
- app/migrations/versions/20260313_0004_episode_sync_hardening.py +71 -0
- app/migrations/versions/20260313_0005_evidence_episode_event_refs.py +45 -0
- app/migrations/versions/20260318_0006_usage_telemetry_schema.py +175 -0
- app/migrations/versions/20260319_0007_identity_session_guidance.py +49 -0
- app/migrations/versions/20260320_0008_instance_metadata_and_backup_safety.py +31 -0
- app/migrations/versions/__init__.py +1 -0
- app/periphery/__init__.py +1 -0
- app/periphery/admin/__init__.py +1 -0
- app/periphery/admin/backup.py +360 -0
- app/periphery/admin/destructive_guard.py +32 -0
- app/periphery/admin/doctor.py +192 -0
- app/periphery/admin/init.py +996 -0
- app/periphery/admin/instance_guard.py +211 -0
- app/periphery/admin/machine_state.py +354 -0
- app/periphery/admin/privileges.py +42 -0
- app/periphery/admin/repo_state.py +266 -0
- app/periphery/admin/restore.py +30 -0
- app/periphery/cli/__init__.py +1 -0
- app/periphery/cli/handlers.py +830 -0
- app/periphery/cli/hydration.py +119 -0
- app/periphery/cli/main.py +710 -0
- app/periphery/cli/presenter_json.py +10 -0
- app/periphery/cli/schema_validation.py +201 -0
- app/periphery/db/__init__.py +1 -0
- app/periphery/db/engine.py +10 -0
- app/periphery/db/models/__init__.py +1 -0
- app/periphery/db/models/associations.py +55 -0
- app/periphery/db/models/episodes.py +55 -0
- app/periphery/db/models/evidence.py +19 -0
- app/periphery/db/models/experiences.py +33 -0
- app/periphery/db/models/instance_metadata.py +17 -0
- app/periphery/db/models/memories.py +39 -0
- app/periphery/db/models/metadata.py +6 -0
- app/periphery/db/models/registry.py +18 -0
- app/periphery/db/models/telemetry.py +174 -0
- app/periphery/db/models/utility.py +19 -0
- app/periphery/db/models/views.py +154 -0
- app/periphery/db/repos/__init__.py +1 -0
- app/periphery/db/repos/relational/__init__.py +1 -0
- app/periphery/db/repos/relational/associations_repo.py +117 -0
- app/periphery/db/repos/relational/episodes_repo.py +188 -0
- app/periphery/db/repos/relational/evidence_repo.py +82 -0
- app/periphery/db/repos/relational/experiences_repo.py +41 -0
- app/periphery/db/repos/relational/memories_repo.py +99 -0
- app/periphery/db/repos/relational/read_policy_repo.py +202 -0
- app/periphery/db/repos/relational/telemetry_repo.py +161 -0
- app/periphery/db/repos/relational/utility_repo.py +30 -0
- app/periphery/db/repos/semantic/__init__.py +1 -0
- app/periphery/db/repos/semantic/keyword_retrieval_repo.py +63 -0
- app/periphery/db/repos/semantic/semantic_retrieval_repo.py +111 -0
- app/periphery/db/session.py +10 -0
- app/periphery/db/uow.py +75 -0
- app/periphery/embeddings/__init__.py +1 -0
- app/periphery/embeddings/local_provider.py +35 -0
- app/periphery/embeddings/query_vector_search.py +18 -0
- app/periphery/episodes/__init__.py +1 -0
- app/periphery/episodes/claude_code.py +387 -0
- app/periphery/episodes/codex.py +423 -0
- app/periphery/episodes/launcher.py +66 -0
- app/periphery/episodes/normalization.py +31 -0
- app/periphery/episodes/poller.py +299 -0
- app/periphery/episodes/source_discovery.py +66 -0
- app/periphery/episodes/tool_filter.py +165 -0
- app/periphery/identity/__init__.py +1 -0
- app/periphery/identity/claude_hook_install.py +67 -0
- app/periphery/identity/claude_runtime.py +83 -0
- app/periphery/identity/codex_runtime.py +32 -0
- app/periphery/identity/compatibility.py +38 -0
- app/periphery/identity/resolver.py +163 -0
- app/periphery/session_state/__init__.py +1 -0
- app/periphery/session_state/file_store.py +100 -0
- app/periphery/telemetry/__init__.py +33 -0
- app/periphery/telemetry/operation_summary.py +299 -0
- app/periphery/telemetry/session_selection.py +156 -0
- app/periphery/telemetry/sync_summary.py +65 -0
- app/periphery/validation/__init__.py +1 -0
- app/periphery/validation/integrity_validation.py +253 -0
- app/periphery/validation/semantic_validation.py +94 -0
- shellbrain-0.1.0.dist-info/METADATA +130 -0
- shellbrain-0.1.0.dist-info/RECORD +165 -0
- shellbrain-0.1.0.dist-info/WHEEL +5 -0
- shellbrain-0.1.0.dist-info/entry_points.txt +2 -0
- shellbrain-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
"""This migration creates the initial PostgreSQL schema, indexes, and derived views."""
|
|
2
|
+
|
|
3
|
+
from alembic import op
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
revision = "20260226_0001"
|
|
7
|
+
down_revision = None
|
|
8
|
+
branch_labels = None
|
|
9
|
+
depends_on = None
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def upgrade() -> None:
|
|
13
|
+
"""This function applies the initial schema for shellbrain storage and retrieval."""
|
|
14
|
+
|
|
15
|
+
op.execute(
|
|
16
|
+
"""
|
|
17
|
+
CREATE EXTENSION IF NOT EXISTS vector;
|
|
18
|
+
|
|
19
|
+
CREATE TABLE memories (
|
|
20
|
+
id TEXT PRIMARY KEY,
|
|
21
|
+
repo_id TEXT NOT NULL,
|
|
22
|
+
scope TEXT NOT NULL CHECK (scope IN ('repo', 'global')),
|
|
23
|
+
kind TEXT NOT NULL CHECK (kind IN ('problem', 'solution', 'failed_tactic', 'fact', 'preference', 'change')),
|
|
24
|
+
text TEXT NOT NULL,
|
|
25
|
+
create_confidence DOUBLE PRECISION CHECK (create_confidence >= 0 AND create_confidence <= 1),
|
|
26
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
27
|
+
archived BOOLEAN NOT NULL DEFAULT FALSE
|
|
28
|
+
);
|
|
29
|
+
CREATE INDEX idx_memories_repo_scope_kind ON memories(repo_id, scope, kind);
|
|
30
|
+
CREATE INDEX idx_memories_created_at ON memories(created_at);
|
|
31
|
+
CREATE INDEX idx_memories_text_fts ON memories USING GIN (to_tsvector('english', text));
|
|
32
|
+
|
|
33
|
+
CREATE TABLE episodes (
|
|
34
|
+
id TEXT PRIMARY KEY,
|
|
35
|
+
repo_id TEXT NOT NULL,
|
|
36
|
+
thread_id TEXT,
|
|
37
|
+
title TEXT,
|
|
38
|
+
objective TEXT,
|
|
39
|
+
status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'closed', 'archived')),
|
|
40
|
+
started_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
41
|
+
ended_at TIMESTAMPTZ,
|
|
42
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
43
|
+
);
|
|
44
|
+
CREATE INDEX idx_episodes_repo_status_started ON episodes(repo_id, status, started_at);
|
|
45
|
+
CREATE INDEX idx_episodes_repo_thread ON episodes(repo_id, thread_id);
|
|
46
|
+
|
|
47
|
+
CREATE TABLE episode_events (
|
|
48
|
+
id TEXT PRIMARY KEY,
|
|
49
|
+
episode_id TEXT NOT NULL REFERENCES episodes(id) ON DELETE CASCADE,
|
|
50
|
+
seq INTEGER NOT NULL CHECK (seq > 0),
|
|
51
|
+
source TEXT NOT NULL CHECK (source IN ('user', 'assistant', 'tool', 'system')),
|
|
52
|
+
content TEXT NOT NULL,
|
|
53
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
54
|
+
UNIQUE (episode_id, seq)
|
|
55
|
+
);
|
|
56
|
+
CREATE INDEX idx_episode_events_episode_created ON episode_events(episode_id, created_at);
|
|
57
|
+
|
|
58
|
+
CREATE TABLE session_transfers (
|
|
59
|
+
id TEXT PRIMARY KEY,
|
|
60
|
+
repo_id TEXT NOT NULL,
|
|
61
|
+
from_episode_id TEXT NOT NULL REFERENCES episodes(id) ON DELETE CASCADE,
|
|
62
|
+
to_episode_id TEXT NOT NULL REFERENCES episodes(id) ON DELETE CASCADE,
|
|
63
|
+
event_id TEXT NOT NULL REFERENCES episode_events(id) ON DELETE CASCADE,
|
|
64
|
+
transfer_kind TEXT NOT NULL CHECK (transfer_kind IN ('message_handoff', 'context_summary', 'task_split', 'task_merge')),
|
|
65
|
+
rationale TEXT,
|
|
66
|
+
transferred_by TEXT,
|
|
67
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
68
|
+
UNIQUE (from_episode_id, to_episode_id, event_id, transfer_kind)
|
|
69
|
+
);
|
|
70
|
+
CREATE INDEX idx_session_transfers_from ON session_transfers(from_episode_id, created_at);
|
|
71
|
+
CREATE INDEX idx_session_transfers_to ON session_transfers(to_episode_id, created_at);
|
|
72
|
+
CREATE INDEX idx_session_transfers_event ON session_transfers(event_id);
|
|
73
|
+
|
|
74
|
+
CREATE TABLE memory_embeddings (
|
|
75
|
+
memory_id TEXT PRIMARY KEY REFERENCES memories(id) ON DELETE CASCADE,
|
|
76
|
+
model TEXT NOT NULL,
|
|
77
|
+
dim INTEGER NOT NULL CHECK (dim > 0),
|
|
78
|
+
vector VECTOR NOT NULL,
|
|
79
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
CREATE TABLE problem_attempts (
|
|
83
|
+
problem_id TEXT NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
|
|
84
|
+
attempt_id TEXT NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
|
|
85
|
+
role TEXT NOT NULL CHECK (role IN ('solution', 'failed_tactic')),
|
|
86
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
87
|
+
PRIMARY KEY (problem_id, attempt_id)
|
|
88
|
+
);
|
|
89
|
+
CREATE INDEX idx_problem_attempts_problem ON problem_attempts(problem_id);
|
|
90
|
+
CREATE INDEX idx_problem_attempts_attempt ON problem_attempts(attempt_id);
|
|
91
|
+
|
|
92
|
+
CREATE TABLE fact_updates (
|
|
93
|
+
id TEXT PRIMARY KEY,
|
|
94
|
+
old_fact_id TEXT NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
|
|
95
|
+
change_id TEXT NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
|
|
96
|
+
new_fact_id TEXT NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
|
|
97
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
98
|
+
UNIQUE (old_fact_id, change_id, new_fact_id)
|
|
99
|
+
);
|
|
100
|
+
CREATE INDEX idx_fact_updates_old_fact ON fact_updates(old_fact_id);
|
|
101
|
+
CREATE INDEX idx_fact_updates_new_fact ON fact_updates(new_fact_id);
|
|
102
|
+
|
|
103
|
+
CREATE TABLE association_edges (
|
|
104
|
+
id TEXT PRIMARY KEY,
|
|
105
|
+
repo_id TEXT NOT NULL,
|
|
106
|
+
from_memory_id TEXT NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
|
|
107
|
+
to_memory_id TEXT NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
|
|
108
|
+
relation_type TEXT NOT NULL CHECK (relation_type IN ('depends_on', 'associated_with')),
|
|
109
|
+
source_mode TEXT NOT NULL DEFAULT 'agent' CHECK (source_mode IN ('agent', 'implicit', 'mixed')),
|
|
110
|
+
state TEXT NOT NULL DEFAULT 'tentative' CHECK (state IN ('tentative', 'confirmed', 'deprecated')),
|
|
111
|
+
strength DOUBLE PRECISION NOT NULL DEFAULT 0 CHECK (strength >= 0 AND strength <= 1),
|
|
112
|
+
obs_count INTEGER NOT NULL DEFAULT 0 CHECK (obs_count >= 0),
|
|
113
|
+
positive_obs INTEGER NOT NULL DEFAULT 0 CHECK (positive_obs >= 0),
|
|
114
|
+
negative_obs INTEGER NOT NULL DEFAULT 0 CHECK (negative_obs >= 0),
|
|
115
|
+
salience_sum DOUBLE PRECISION NOT NULL DEFAULT 0 CHECK (salience_sum >= 0),
|
|
116
|
+
last_reinforced_at TIMESTAMPTZ,
|
|
117
|
+
last_used_at TIMESTAMPTZ,
|
|
118
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
119
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
120
|
+
CHECK (from_memory_id <> to_memory_id),
|
|
121
|
+
UNIQUE (repo_id, from_memory_id, to_memory_id, relation_type)
|
|
122
|
+
);
|
|
123
|
+
CREATE INDEX idx_assoc_edges_from ON association_edges(repo_id, from_memory_id, relation_type, state, strength);
|
|
124
|
+
CREATE INDEX idx_assoc_edges_to ON association_edges(repo_id, to_memory_id, relation_type, state, strength);
|
|
125
|
+
|
|
126
|
+
CREATE TABLE association_observations (
|
|
127
|
+
id TEXT PRIMARY KEY,
|
|
128
|
+
repo_id TEXT NOT NULL,
|
|
129
|
+
edge_id TEXT REFERENCES association_edges(id) ON DELETE CASCADE,
|
|
130
|
+
from_memory_id TEXT NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
|
|
131
|
+
to_memory_id TEXT NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
|
|
132
|
+
relation_type TEXT NOT NULL CHECK (relation_type IN ('depends_on', 'associated_with')),
|
|
133
|
+
source TEXT NOT NULL CHECK (source IN ('agent_explicit', 'implicit_coactivation', 'agent_feedback')),
|
|
134
|
+
problem_id TEXT REFERENCES memories(id) ON DELETE SET NULL,
|
|
135
|
+
episode_id TEXT REFERENCES episodes(id) ON DELETE SET NULL,
|
|
136
|
+
valence DOUBLE PRECISION NOT NULL CHECK (valence >= -1 AND valence <= 1),
|
|
137
|
+
salience DOUBLE PRECISION NOT NULL DEFAULT 0.5 CHECK (salience >= 0 AND salience <= 1),
|
|
138
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
139
|
+
CHECK (from_memory_id <> to_memory_id)
|
|
140
|
+
);
|
|
141
|
+
CREATE INDEX idx_assoc_obs_pair_time ON association_observations(repo_id, from_memory_id, to_memory_id, created_at);
|
|
142
|
+
CREATE INDEX idx_assoc_obs_problem ON association_observations(repo_id, problem_id, created_at);
|
|
143
|
+
CREATE INDEX idx_assoc_obs_episode ON association_observations(repo_id, episode_id, created_at);
|
|
144
|
+
|
|
145
|
+
CREATE TABLE utility_observations (
|
|
146
|
+
id TEXT PRIMARY KEY,
|
|
147
|
+
memory_id TEXT NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
|
|
148
|
+
problem_id TEXT NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
|
|
149
|
+
vote DOUBLE PRECISION NOT NULL CHECK (vote >= -1 AND vote <= 1),
|
|
150
|
+
rationale TEXT,
|
|
151
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
152
|
+
);
|
|
153
|
+
CREATE INDEX idx_utility_obs_shellbrain ON utility_observations(memory_id);
|
|
154
|
+
CREATE INDEX idx_utility_obs_problem ON utility_observations(problem_id);
|
|
155
|
+
CREATE INDEX idx_utility_obs_created_at ON utility_observations(created_at);
|
|
156
|
+
|
|
157
|
+
CREATE TABLE evidence_refs (
|
|
158
|
+
id TEXT PRIMARY KEY,
|
|
159
|
+
repo_id TEXT NOT NULL,
|
|
160
|
+
ref TEXT NOT NULL,
|
|
161
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
162
|
+
);
|
|
163
|
+
CREATE UNIQUE INDEX uq_evidence_repo_ref ON evidence_refs(repo_id, ref);
|
|
164
|
+
|
|
165
|
+
CREATE TABLE memory_evidence (
|
|
166
|
+
memory_id TEXT NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
|
|
167
|
+
evidence_id TEXT NOT NULL REFERENCES evidence_refs(id) ON DELETE CASCADE,
|
|
168
|
+
PRIMARY KEY (memory_id, evidence_id)
|
|
169
|
+
);
|
|
170
|
+
CREATE INDEX idx_memory_evidence_evidence ON memory_evidence(evidence_id);
|
|
171
|
+
|
|
172
|
+
CREATE TABLE association_edge_evidence (
|
|
173
|
+
edge_id TEXT NOT NULL REFERENCES association_edges(id) ON DELETE CASCADE,
|
|
174
|
+
evidence_id TEXT NOT NULL REFERENCES evidence_refs(id) ON DELETE CASCADE,
|
|
175
|
+
PRIMARY KEY (edge_id, evidence_id)
|
|
176
|
+
);
|
|
177
|
+
CREATE INDEX idx_assoc_edge_evidence_evidence ON association_edge_evidence(evidence_id);
|
|
178
|
+
|
|
179
|
+
CREATE VIEW current_fact_snapshot AS
|
|
180
|
+
SELECT m.*
|
|
181
|
+
FROM memories m
|
|
182
|
+
WHERE m.kind = 'fact'
|
|
183
|
+
AND m.archived = FALSE
|
|
184
|
+
AND NOT EXISTS (
|
|
185
|
+
SELECT 1 FROM fact_updates fu WHERE fu.old_fact_id = m.id
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
CREATE VIEW global_utility AS
|
|
189
|
+
SELECT memory_id, AVG(vote) AS utility_mean, COUNT(*) AS observations
|
|
190
|
+
FROM utility_observations
|
|
191
|
+
GROUP BY memory_id;
|
|
192
|
+
|
|
193
|
+
CREATE VIEW direct_dependency_counts AS
|
|
194
|
+
SELECT repo_id, from_memory_id AS memory_id, COUNT(*) AS dependency_count
|
|
195
|
+
FROM association_edges
|
|
196
|
+
WHERE relation_type = 'depends_on' AND state != 'deprecated'
|
|
197
|
+
GROUP BY repo_id, from_memory_id;
|
|
198
|
+
|
|
199
|
+
CREATE VIEW direct_dependent_counts AS
|
|
200
|
+
SELECT repo_id, to_memory_id AS memory_id, COUNT(*) AS dependent_count
|
|
201
|
+
FROM association_edges
|
|
202
|
+
WHERE relation_type = 'depends_on' AND state != 'deprecated'
|
|
203
|
+
GROUP BY repo_id, to_memory_id;
|
|
204
|
+
"""
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def downgrade() -> None:
|
|
209
|
+
"""This function removes the initial schema, indexes, and derived views."""
|
|
210
|
+
|
|
211
|
+
op.execute(
|
|
212
|
+
"""
|
|
213
|
+
DROP VIEW IF EXISTS direct_dependent_counts;
|
|
214
|
+
DROP VIEW IF EXISTS direct_dependency_counts;
|
|
215
|
+
DROP VIEW IF EXISTS global_utility;
|
|
216
|
+
DROP VIEW IF EXISTS current_fact_snapshot;
|
|
217
|
+
|
|
218
|
+
DROP TABLE IF EXISTS association_edge_evidence;
|
|
219
|
+
DROP TABLE IF EXISTS memory_evidence;
|
|
220
|
+
DROP TABLE IF EXISTS evidence_refs;
|
|
221
|
+
DROP TABLE IF EXISTS utility_observations;
|
|
222
|
+
DROP TABLE IF EXISTS association_observations;
|
|
223
|
+
DROP TABLE IF EXISTS association_edges;
|
|
224
|
+
DROP TABLE IF EXISTS fact_updates;
|
|
225
|
+
DROP TABLE IF EXISTS problem_attempts;
|
|
226
|
+
DROP TABLE IF EXISTS memory_embeddings;
|
|
227
|
+
DROP TABLE IF EXISTS session_transfers;
|
|
228
|
+
DROP TABLE IF EXISTS episode_events;
|
|
229
|
+
DROP TABLE IF EXISTS episodes;
|
|
230
|
+
DROP TABLE IF EXISTS memories;
|
|
231
|
+
"""
|
|
232
|
+
)
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""Add hard schema invariants for episodes, problem attempts, and fact updates."""
|
|
2
|
+
|
|
3
|
+
from alembic import op
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
revision = "20260312_0002"
|
|
7
|
+
down_revision = "20260226_0001"
|
|
8
|
+
branch_labels = None
|
|
9
|
+
depends_on = None
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def upgrade() -> None:
|
|
13
|
+
"""Apply additional DB-level constraints that encode obvious write invariants."""
|
|
14
|
+
|
|
15
|
+
op.execute(
|
|
16
|
+
"""
|
|
17
|
+
ALTER TABLE episodes
|
|
18
|
+
ADD CONSTRAINT ck_episodes_ended_after_started
|
|
19
|
+
CHECK (ended_at IS NULL OR ended_at >= started_at);
|
|
20
|
+
|
|
21
|
+
ALTER TABLE session_transfers
|
|
22
|
+
ADD CONSTRAINT ck_session_transfers_distinct_episodes
|
|
23
|
+
CHECK (from_episode_id <> to_episode_id);
|
|
24
|
+
|
|
25
|
+
ALTER TABLE problem_attempts
|
|
26
|
+
ADD CONSTRAINT ck_problem_attempts_distinct_memories
|
|
27
|
+
CHECK (problem_id <> attempt_id);
|
|
28
|
+
|
|
29
|
+
ALTER TABLE fact_updates
|
|
30
|
+
ADD CONSTRAINT ck_fact_updates_distinct_fact_endpoints
|
|
31
|
+
CHECK (old_fact_id <> new_fact_id);
|
|
32
|
+
|
|
33
|
+
ALTER TABLE fact_updates
|
|
34
|
+
ADD CONSTRAINT ck_fact_updates_change_id_distinct
|
|
35
|
+
CHECK (change_id <> old_fact_id AND change_id <> new_fact_id);
|
|
36
|
+
"""
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def downgrade() -> None:
|
|
41
|
+
"""Remove the added DB-level invariant constraints."""
|
|
42
|
+
|
|
43
|
+
op.execute(
|
|
44
|
+
"""
|
|
45
|
+
ALTER TABLE fact_updates
|
|
46
|
+
DROP CONSTRAINT IF EXISTS ck_fact_updates_change_id_distinct;
|
|
47
|
+
|
|
48
|
+
ALTER TABLE fact_updates
|
|
49
|
+
DROP CONSTRAINT IF EXISTS ck_fact_updates_distinct_fact_endpoints;
|
|
50
|
+
|
|
51
|
+
ALTER TABLE problem_attempts
|
|
52
|
+
DROP CONSTRAINT IF EXISTS ck_problem_attempts_distinct_memories;
|
|
53
|
+
|
|
54
|
+
ALTER TABLE session_transfers
|
|
55
|
+
DROP CONSTRAINT IF EXISTS ck_session_transfers_distinct_episodes;
|
|
56
|
+
|
|
57
|
+
ALTER TABLE episodes
|
|
58
|
+
DROP CONSTRAINT IF EXISTS ck_episodes_ended_after_started;
|
|
59
|
+
"""
|
|
60
|
+
)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""Drop create_confidence from memories after removing it from the write contract."""
|
|
2
|
+
|
|
3
|
+
from alembic import op
|
|
4
|
+
|
|
5
|
+
from app.periphery.db.models.views import CURRENT_FACT_SNAPSHOT_SQL
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
revision = "20260312_0003"
|
|
9
|
+
down_revision = "20260312_0002"
|
|
10
|
+
branch_labels = None
|
|
11
|
+
depends_on = None
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def upgrade() -> None:
|
|
15
|
+
"""Remove the obsolete create_confidence column from memories."""
|
|
16
|
+
|
|
17
|
+
op.execute(
|
|
18
|
+
"""
|
|
19
|
+
DROP VIEW IF EXISTS current_fact_snapshot;
|
|
20
|
+
|
|
21
|
+
ALTER TABLE memories
|
|
22
|
+
DROP COLUMN IF EXISTS create_confidence;
|
|
23
|
+
"""
|
|
24
|
+
)
|
|
25
|
+
op.execute(CURRENT_FACT_SNAPSHOT_SQL)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def downgrade() -> None:
|
|
29
|
+
"""Restore the removed create_confidence column for downgrade compatibility."""
|
|
30
|
+
|
|
31
|
+
op.execute(
|
|
32
|
+
"""
|
|
33
|
+
DROP VIEW IF EXISTS current_fact_snapshot;
|
|
34
|
+
|
|
35
|
+
ALTER TABLE memories
|
|
36
|
+
ADD COLUMN IF NOT EXISTS create_confidence DOUBLE PRECISION
|
|
37
|
+
CHECK (create_confidence >= 0 AND create_confidence <= 1);
|
|
38
|
+
"""
|
|
39
|
+
)
|
|
40
|
+
op.execute(CURRENT_FACT_SNAPSHOT_SQL)
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"""Add explicit host session metadata and upstream event dedupe for episodes."""
|
|
2
|
+
|
|
3
|
+
from alembic import op
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
revision = "20260313_0004"
|
|
7
|
+
down_revision = "20260312_0003"
|
|
8
|
+
branch_labels = None
|
|
9
|
+
depends_on = None
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def upgrade() -> None:
|
|
13
|
+
"""Add host-app identity and upstream event keys for episodic sync."""
|
|
14
|
+
|
|
15
|
+
op.execute(
|
|
16
|
+
"""
|
|
17
|
+
ALTER TABLE episodes
|
|
18
|
+
ADD COLUMN host_app TEXT;
|
|
19
|
+
|
|
20
|
+
UPDATE episodes
|
|
21
|
+
SET host_app = CASE
|
|
22
|
+
WHEN thread_id LIKE 'codex:%' THEN 'codex'
|
|
23
|
+
WHEN thread_id LIKE 'claude_code:%' THEN 'claude_code'
|
|
24
|
+
ELSE 'unknown'
|
|
25
|
+
END
|
|
26
|
+
WHERE host_app IS NULL;
|
|
27
|
+
|
|
28
|
+
ALTER TABLE episodes
|
|
29
|
+
ALTER COLUMN host_app SET NOT NULL;
|
|
30
|
+
|
|
31
|
+
ALTER TABLE episode_events
|
|
32
|
+
ADD COLUMN host_event_key TEXT;
|
|
33
|
+
|
|
34
|
+
UPDATE episode_events
|
|
35
|
+
SET host_event_key = 'legacy:' || id
|
|
36
|
+
WHERE host_event_key IS NULL;
|
|
37
|
+
|
|
38
|
+
ALTER TABLE episode_events
|
|
39
|
+
ALTER COLUMN host_event_key SET NOT NULL;
|
|
40
|
+
|
|
41
|
+
DROP INDEX IF EXISTS idx_episodes_repo_thread;
|
|
42
|
+
|
|
43
|
+
ALTER TABLE episodes
|
|
44
|
+
ADD CONSTRAINT uq_episodes_repo_thread UNIQUE (repo_id, thread_id);
|
|
45
|
+
|
|
46
|
+
ALTER TABLE episode_events
|
|
47
|
+
ADD CONSTRAINT uq_episode_events_host_event_key UNIQUE (episode_id, host_event_key);
|
|
48
|
+
"""
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def downgrade() -> None:
|
|
53
|
+
"""Remove episode sync hardening columns and constraints."""
|
|
54
|
+
|
|
55
|
+
op.execute(
|
|
56
|
+
"""
|
|
57
|
+
ALTER TABLE episode_events
|
|
58
|
+
DROP CONSTRAINT IF EXISTS uq_episode_events_host_event_key;
|
|
59
|
+
|
|
60
|
+
ALTER TABLE episodes
|
|
61
|
+
DROP CONSTRAINT IF EXISTS uq_episodes_repo_thread;
|
|
62
|
+
|
|
63
|
+
CREATE INDEX IF NOT EXISTS idx_episodes_repo_thread ON episodes(repo_id, thread_id);
|
|
64
|
+
|
|
65
|
+
ALTER TABLE episode_events
|
|
66
|
+
DROP COLUMN IF EXISTS host_event_key;
|
|
67
|
+
|
|
68
|
+
ALTER TABLE episodes
|
|
69
|
+
DROP COLUMN IF EXISTS host_app;
|
|
70
|
+
"""
|
|
71
|
+
)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""Attach evidence references directly to stored episode events."""
|
|
2
|
+
|
|
3
|
+
from alembic import op
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
revision = "20260313_0005"
|
|
7
|
+
down_revision = "20260313_0004"
|
|
8
|
+
branch_labels = None
|
|
9
|
+
depends_on = None
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def upgrade() -> None:
|
|
13
|
+
"""Add episode_event-backed evidence references while preserving legacy ref strings."""
|
|
14
|
+
|
|
15
|
+
op.execute(
|
|
16
|
+
"""
|
|
17
|
+
ALTER TABLE evidence_refs
|
|
18
|
+
ADD COLUMN episode_event_id TEXT REFERENCES episode_events(id);
|
|
19
|
+
|
|
20
|
+
UPDATE evidence_refs AS er
|
|
21
|
+
SET episode_event_id = er.ref
|
|
22
|
+
FROM episode_events AS ee
|
|
23
|
+
JOIN episodes AS ep ON ep.id = ee.episode_id
|
|
24
|
+
WHERE er.episode_event_id IS NULL
|
|
25
|
+
AND er.ref = ee.id
|
|
26
|
+
AND er.repo_id = ep.repo_id;
|
|
27
|
+
|
|
28
|
+
ALTER TABLE evidence_refs
|
|
29
|
+
ADD CONSTRAINT uq_evidence_repo_episode_event UNIQUE (repo_id, episode_event_id);
|
|
30
|
+
"""
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def downgrade() -> None:
|
|
35
|
+
"""Remove episode-event-backed evidence reference storage."""
|
|
36
|
+
|
|
37
|
+
op.execute(
|
|
38
|
+
"""
|
|
39
|
+
ALTER TABLE evidence_refs
|
|
40
|
+
DROP CONSTRAINT IF EXISTS uq_evidence_repo_episode_event;
|
|
41
|
+
|
|
42
|
+
ALTER TABLE evidence_refs
|
|
43
|
+
DROP COLUMN IF EXISTS episode_event_id;
|
|
44
|
+
"""
|
|
45
|
+
)
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"""Create low-overhead usage telemetry storage and analytics views."""
|
|
2
|
+
|
|
3
|
+
from alembic import op
|
|
4
|
+
|
|
5
|
+
from app.periphery.db.models.views import (
|
|
6
|
+
USAGE_COMMAND_DAILY_SQL,
|
|
7
|
+
USAGE_MEMORY_RETRIEVAL_SQL,
|
|
8
|
+
USAGE_SESSION_PROTOCOL_SQL,
|
|
9
|
+
USAGE_SYNC_HEALTH_SQL,
|
|
10
|
+
USAGE_WRITE_EFFECTS_SQL,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
revision = "20260318_0006"
|
|
14
|
+
down_revision = "20260313_0005"
|
|
15
|
+
branch_labels = None
|
|
16
|
+
depends_on = None
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def upgrade() -> None:
|
|
20
|
+
"""Create telemetry tables, indexes, and derived analytics views."""
|
|
21
|
+
|
|
22
|
+
op.execute(
|
|
23
|
+
"""
|
|
24
|
+
CREATE TABLE operation_invocations (
|
|
25
|
+
id TEXT PRIMARY KEY,
|
|
26
|
+
command TEXT NOT NULL CHECK (command IN ('read', 'create', 'update', 'events')),
|
|
27
|
+
repo_id TEXT NOT NULL,
|
|
28
|
+
repo_root TEXT NOT NULL,
|
|
29
|
+
no_sync BOOLEAN NOT NULL DEFAULT FALSE,
|
|
30
|
+
selected_host_app TEXT,
|
|
31
|
+
selected_host_session_key TEXT,
|
|
32
|
+
selected_thread_id TEXT,
|
|
33
|
+
selected_episode_id TEXT,
|
|
34
|
+
matching_candidate_count INTEGER NOT NULL DEFAULT 0 CHECK (matching_candidate_count >= 0),
|
|
35
|
+
selection_ambiguous BOOLEAN NOT NULL DEFAULT FALSE,
|
|
36
|
+
outcome TEXT NOT NULL CHECK (outcome IN ('ok', 'error')),
|
|
37
|
+
error_stage TEXT,
|
|
38
|
+
error_code TEXT,
|
|
39
|
+
error_message TEXT,
|
|
40
|
+
total_latency_ms INTEGER NOT NULL CHECK (total_latency_ms >= 0),
|
|
41
|
+
poller_start_attempted BOOLEAN NOT NULL DEFAULT FALSE,
|
|
42
|
+
poller_started BOOLEAN NOT NULL DEFAULT FALSE,
|
|
43
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
44
|
+
);
|
|
45
|
+
CREATE INDEX idx_operation_invocations_repo_created_at
|
|
46
|
+
ON operation_invocations(repo_id, created_at);
|
|
47
|
+
CREATE INDEX idx_operation_invocations_command_created_at
|
|
48
|
+
ON operation_invocations(command, created_at);
|
|
49
|
+
CREATE INDEX idx_operation_invocations_thread_created_at
|
|
50
|
+
ON operation_invocations(selected_thread_id, created_at)
|
|
51
|
+
WHERE selected_thread_id IS NOT NULL;
|
|
52
|
+
|
|
53
|
+
CREATE TABLE read_invocation_summaries (
|
|
54
|
+
invocation_id TEXT PRIMARY KEY REFERENCES operation_invocations(id) ON DELETE CASCADE,
|
|
55
|
+
query_text TEXT NOT NULL,
|
|
56
|
+
mode TEXT NOT NULL,
|
|
57
|
+
requested_limit INTEGER,
|
|
58
|
+
effective_limit INTEGER NOT NULL CHECK (effective_limit >= 0),
|
|
59
|
+
include_global BOOLEAN,
|
|
60
|
+
kinds_filter JSONB,
|
|
61
|
+
direct_count INTEGER NOT NULL CHECK (direct_count >= 0),
|
|
62
|
+
explicit_related_count INTEGER NOT NULL CHECK (explicit_related_count >= 0),
|
|
63
|
+
implicit_related_count INTEGER NOT NULL CHECK (implicit_related_count >= 0),
|
|
64
|
+
total_returned INTEGER NOT NULL CHECK (total_returned >= 0),
|
|
65
|
+
zero_results BOOLEAN NOT NULL,
|
|
66
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
CREATE TABLE read_result_items (
|
|
70
|
+
invocation_id TEXT NOT NULL REFERENCES operation_invocations(id) ON DELETE CASCADE,
|
|
71
|
+
ordinal INTEGER NOT NULL CHECK (ordinal > 0),
|
|
72
|
+
memory_id TEXT NOT NULL,
|
|
73
|
+
kind TEXT NOT NULL,
|
|
74
|
+
section TEXT NOT NULL,
|
|
75
|
+
priority INTEGER NOT NULL CHECK (priority > 0),
|
|
76
|
+
why_included TEXT NOT NULL,
|
|
77
|
+
anchor_memory_id TEXT,
|
|
78
|
+
relation_type TEXT,
|
|
79
|
+
PRIMARY KEY (invocation_id, ordinal)
|
|
80
|
+
);
|
|
81
|
+
CREATE INDEX idx_read_result_items_memory_invocation
|
|
82
|
+
ON read_result_items(memory_id, invocation_id);
|
|
83
|
+
|
|
84
|
+
CREATE TABLE write_invocation_summaries (
|
|
85
|
+
invocation_id TEXT PRIMARY KEY REFERENCES operation_invocations(id) ON DELETE CASCADE,
|
|
86
|
+
operation_command TEXT NOT NULL CHECK (operation_command IN ('create', 'update')),
|
|
87
|
+
target_memory_id TEXT NOT NULL,
|
|
88
|
+
target_kind TEXT,
|
|
89
|
+
update_type TEXT,
|
|
90
|
+
scope TEXT,
|
|
91
|
+
evidence_ref_count INTEGER NOT NULL DEFAULT 0 CHECK (evidence_ref_count >= 0),
|
|
92
|
+
planned_effect_count INTEGER NOT NULL CHECK (planned_effect_count >= 0),
|
|
93
|
+
created_memory_count INTEGER NOT NULL DEFAULT 0 CHECK (created_memory_count >= 0),
|
|
94
|
+
archived_memory_count INTEGER NOT NULL DEFAULT 0 CHECK (archived_memory_count >= 0),
|
|
95
|
+
utility_observation_count INTEGER NOT NULL DEFAULT 0 CHECK (utility_observation_count >= 0),
|
|
96
|
+
association_effect_count INTEGER NOT NULL DEFAULT 0 CHECK (association_effect_count >= 0),
|
|
97
|
+
fact_update_count INTEGER NOT NULL DEFAULT 0 CHECK (fact_update_count >= 0),
|
|
98
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
CREATE TABLE write_effect_items (
|
|
102
|
+
invocation_id TEXT NOT NULL REFERENCES operation_invocations(id) ON DELETE CASCADE,
|
|
103
|
+
ordinal INTEGER NOT NULL CHECK (ordinal > 0),
|
|
104
|
+
effect_type TEXT NOT NULL,
|
|
105
|
+
repo_id TEXT NOT NULL,
|
|
106
|
+
primary_memory_id TEXT,
|
|
107
|
+
secondary_memory_id TEXT,
|
|
108
|
+
params_json JSONB NOT NULL DEFAULT '{}'::jsonb,
|
|
109
|
+
PRIMARY KEY (invocation_id, ordinal)
|
|
110
|
+
);
|
|
111
|
+
CREATE INDEX idx_write_effect_items_repo_effect_invocation
|
|
112
|
+
ON write_effect_items(repo_id, effect_type, invocation_id);
|
|
113
|
+
|
|
114
|
+
CREATE TABLE episode_sync_runs (
|
|
115
|
+
id TEXT PRIMARY KEY,
|
|
116
|
+
source TEXT NOT NULL CHECK (source IN ('events_inline', 'poller')),
|
|
117
|
+
invocation_id TEXT REFERENCES operation_invocations(id) ON DELETE SET NULL,
|
|
118
|
+
repo_id TEXT NOT NULL,
|
|
119
|
+
host_app TEXT NOT NULL,
|
|
120
|
+
host_session_key TEXT NOT NULL,
|
|
121
|
+
thread_id TEXT NOT NULL,
|
|
122
|
+
episode_id TEXT,
|
|
123
|
+
transcript_path TEXT,
|
|
124
|
+
outcome TEXT NOT NULL CHECK (outcome IN ('ok', 'error')),
|
|
125
|
+
error_stage TEXT,
|
|
126
|
+
error_message TEXT,
|
|
127
|
+
duration_ms INTEGER NOT NULL CHECK (duration_ms >= 0),
|
|
128
|
+
imported_event_count INTEGER NOT NULL DEFAULT 0 CHECK (imported_event_count >= 0),
|
|
129
|
+
total_event_count INTEGER NOT NULL DEFAULT 0 CHECK (total_event_count >= 0),
|
|
130
|
+
user_event_count INTEGER NOT NULL DEFAULT 0 CHECK (user_event_count >= 0),
|
|
131
|
+
assistant_event_count INTEGER NOT NULL DEFAULT 0 CHECK (assistant_event_count >= 0),
|
|
132
|
+
tool_event_count INTEGER NOT NULL DEFAULT 0 CHECK (tool_event_count >= 0),
|
|
133
|
+
system_event_count INTEGER NOT NULL DEFAULT 0 CHECK (system_event_count >= 0),
|
|
134
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
135
|
+
);
|
|
136
|
+
CREATE INDEX idx_episode_sync_runs_repo_host_created_at
|
|
137
|
+
ON episode_sync_runs(repo_id, host_app, created_at);
|
|
138
|
+
CREATE INDEX idx_episode_sync_runs_thread_created_at
|
|
139
|
+
ON episode_sync_runs(thread_id, created_at);
|
|
140
|
+
|
|
141
|
+
CREATE TABLE episode_sync_tool_types (
|
|
142
|
+
sync_run_id TEXT NOT NULL REFERENCES episode_sync_runs(id) ON DELETE CASCADE,
|
|
143
|
+
tool_type TEXT NOT NULL,
|
|
144
|
+
event_count INTEGER NOT NULL CHECK (event_count >= 0),
|
|
145
|
+
PRIMARY KEY (sync_run_id, tool_type)
|
|
146
|
+
);
|
|
147
|
+
"""
|
|
148
|
+
)
|
|
149
|
+
op.execute(USAGE_COMMAND_DAILY_SQL)
|
|
150
|
+
op.execute(USAGE_MEMORY_RETRIEVAL_SQL)
|
|
151
|
+
op.execute(USAGE_WRITE_EFFECTS_SQL)
|
|
152
|
+
op.execute(USAGE_SYNC_HEALTH_SQL)
|
|
153
|
+
op.execute(USAGE_SESSION_PROTOCOL_SQL)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def downgrade() -> None:
|
|
157
|
+
"""Drop telemetry views, indexes, and tables."""
|
|
158
|
+
|
|
159
|
+
op.execute(
|
|
160
|
+
"""
|
|
161
|
+
DROP VIEW IF EXISTS usage_session_protocol;
|
|
162
|
+
DROP VIEW IF EXISTS usage_sync_health;
|
|
163
|
+
DROP VIEW IF EXISTS usage_write_effects;
|
|
164
|
+
DROP VIEW IF EXISTS usage_memory_retrieval;
|
|
165
|
+
DROP VIEW IF EXISTS usage_command_daily;
|
|
166
|
+
|
|
167
|
+
DROP TABLE IF EXISTS episode_sync_tool_types;
|
|
168
|
+
DROP TABLE IF EXISTS episode_sync_runs;
|
|
169
|
+
DROP TABLE IF EXISTS write_effect_items;
|
|
170
|
+
DROP TABLE IF EXISTS write_invocation_summaries;
|
|
171
|
+
DROP TABLE IF EXISTS read_result_items;
|
|
172
|
+
DROP TABLE IF EXISTS read_invocation_summaries;
|
|
173
|
+
DROP TABLE IF EXISTS operation_invocations;
|
|
174
|
+
"""
|
|
175
|
+
)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""Extend telemetry storage with caller identity and guidance metadata."""
|
|
2
|
+
|
|
3
|
+
from alembic import op
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
revision = "20260319_0007"
|
|
7
|
+
down_revision = "20260318_0006"
|
|
8
|
+
branch_labels = None
|
|
9
|
+
depends_on = None
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def upgrade() -> None:
|
|
13
|
+
"""Add identity and guidance columns to operation telemetry."""
|
|
14
|
+
|
|
15
|
+
op.execute(
|
|
16
|
+
"""
|
|
17
|
+
ALTER TABLE operation_invocations
|
|
18
|
+
ADD COLUMN IF NOT EXISTS caller_id TEXT;
|
|
19
|
+
|
|
20
|
+
ALTER TABLE operation_invocations
|
|
21
|
+
ADD COLUMN IF NOT EXISTS caller_trust_level TEXT;
|
|
22
|
+
|
|
23
|
+
ALTER TABLE operation_invocations
|
|
24
|
+
ADD COLUMN IF NOT EXISTS identity_failure_code TEXT;
|
|
25
|
+
|
|
26
|
+
ALTER TABLE operation_invocations
|
|
27
|
+
ADD COLUMN IF NOT EXISTS guidance_codes JSONB NOT NULL DEFAULT '[]'::jsonb;
|
|
28
|
+
"""
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def downgrade() -> None:
|
|
33
|
+
"""Drop identity and guidance columns from operation telemetry."""
|
|
34
|
+
|
|
35
|
+
op.execute(
|
|
36
|
+
"""
|
|
37
|
+
ALTER TABLE operation_invocations
|
|
38
|
+
DROP COLUMN IF EXISTS guidance_codes;
|
|
39
|
+
|
|
40
|
+
ALTER TABLE operation_invocations
|
|
41
|
+
DROP COLUMN IF EXISTS identity_failure_code;
|
|
42
|
+
|
|
43
|
+
ALTER TABLE operation_invocations
|
|
44
|
+
DROP COLUMN IF EXISTS caller_trust_level;
|
|
45
|
+
|
|
46
|
+
ALTER TABLE operation_invocations
|
|
47
|
+
DROP COLUMN IF EXISTS caller_id;
|
|
48
|
+
"""
|
|
49
|
+
)
|