@edihasaj/recall 0.5.2

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.
Files changed (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +409 -0
  3. package/dist/chunk-4CV4JOE5.js +27 -0
  4. package/dist/chunk-4CV4JOE5.js.map +1 -0
  5. package/dist/chunk-A5UIRZU6.js +469 -0
  6. package/dist/chunk-A5UIRZU6.js.map +1 -0
  7. package/dist/chunk-AYHFPCGY.js +964 -0
  8. package/dist/chunk-AYHFPCGY.js.map +1 -0
  9. package/dist/chunk-DNFKAHS6.js +204 -0
  10. package/dist/chunk-DNFKAHS6.js.map +1 -0
  11. package/dist/chunk-GC5XMBG4.js +551 -0
  12. package/dist/chunk-GC5XMBG4.js.map +1 -0
  13. package/dist/chunk-IILLSHLM.js +3021 -0
  14. package/dist/chunk-IILLSHLM.js.map +1 -0
  15. package/dist/chunk-LVQW6WHK.js +146 -0
  16. package/dist/chunk-LVQW6WHK.js.map +1 -0
  17. package/dist/chunk-LZ6PMQRX.js +955 -0
  18. package/dist/chunk-LZ6PMQRX.js.map +1 -0
  19. package/dist/chunk-PC43MBX5.js +2960 -0
  20. package/dist/chunk-PC43MBX5.js.map +1 -0
  21. package/dist/chunk-VEPXEHRZ.js +1763 -0
  22. package/dist/chunk-VEPXEHRZ.js.map +1 -0
  23. package/dist/cleanup-TVOX2S2S.js +28 -0
  24. package/dist/cleanup-TVOX2S2S.js.map +1 -0
  25. package/dist/cli.js +3425 -0
  26. package/dist/cli.js.map +1 -0
  27. package/dist/daemon.js +1298 -0
  28. package/dist/daemon.js.map +1 -0
  29. package/dist/dispatcher-UGMU6THT.js +15 -0
  30. package/dist/dispatcher-UGMU6THT.js.map +1 -0
  31. package/dist/keychain-5QG52ANO.js +22 -0
  32. package/dist/keychain-5QG52ANO.js.map +1 -0
  33. package/dist/mcp.js +21 -0
  34. package/dist/mcp.js.map +1 -0
  35. package/dist/quality-Z7LPMMBC.js +17 -0
  36. package/dist/quality-Z7LPMMBC.js.map +1 -0
  37. package/dist/sync-server.js +225 -0
  38. package/dist/sync-server.js.map +1 -0
  39. package/dist/tasks-UOLSPXJQ.js +61 -0
  40. package/dist/tasks-UOLSPXJQ.js.map +1 -0
  41. package/dist/usage-CY3V72YN.js +101 -0
  42. package/dist/usage-CY3V72YN.js.map +1 -0
  43. package/drizzle/0000_initial_create.sql +240 -0
  44. package/drizzle/0001_rich_liz_osborn.sql +21 -0
  45. package/drizzle/0002_unknown_spot.sql +18 -0
  46. package/drizzle/0003_red_wendigo.sql +19 -0
  47. package/drizzle/0004_early_carlie_cooper.sql +1 -0
  48. package/drizzle/0005_simple_emma_frost.sql +96 -0
  49. package/drizzle/0006_keen_mongoose.sql +2 -0
  50. package/drizzle/0007_flawless_maximus.sql +15 -0
  51. package/drizzle/meta/0000_snapshot.json +1630 -0
  52. package/drizzle/meta/0001_snapshot.json +1773 -0
  53. package/drizzle/meta/0002_snapshot.json +1891 -0
  54. package/drizzle/meta/0003_snapshot.json +2014 -0
  55. package/drizzle/meta/0004_snapshot.json +2022 -0
  56. package/drizzle/meta/0005_snapshot.json +2064 -0
  57. package/drizzle/meta/0006_snapshot.json +2078 -0
  58. package/drizzle/meta/0007_snapshot.json +2183 -0
  59. package/drizzle/meta/_journal.json +62 -0
  60. package/package.json +64 -0
  61. package/scripts/recall-claude +7 -0
  62. package/scripts/recall-codex +7 -0
  63. package/scripts/recall-session +71 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,101 @@
1
+ import {
2
+ llmUsage
3
+ } from "./chunk-A5UIRZU6.js";
4
+ import "./chunk-4CV4JOE5.js";
5
+
6
+ // src/llm/usage.ts
7
+ import { desc, gte, sql } from "drizzle-orm";
8
+ function summarizeUsage(db, opts = {}) {
9
+ const sinceIso = opts.sinceIso ?? defaultSinceIso();
10
+ const untilIso = (/* @__PURE__ */ new Date()).toISOString();
11
+ const whereClause = gte(llmUsage.created_at, sinceIso);
12
+ const [totals] = db.select({
13
+ total_calls: sql`count(*)`.as("total_calls"),
14
+ ok_calls: sql`sum(case when ${llmUsage.ok} = 1 then 1 else 0 end)`.as("ok_calls"),
15
+ error_calls: sql`sum(case when ${llmUsage.ok} = 0 then 1 else 0 end)`.as("error_calls"),
16
+ total_prompt_tokens: sql`coalesce(sum(${llmUsage.prompt_tokens}), 0)`.as("total_prompt_tokens"),
17
+ total_completion_tokens: sql`coalesce(sum(${llmUsage.completion_tokens}), 0)`.as("total_completion_tokens"),
18
+ total_tokens: sql`coalesce(sum(${llmUsage.total_tokens}), 0)`.as("total_tokens"),
19
+ total_cost_usd: sql`coalesce(sum(${llmUsage.cost_usd}), 0)`.as("total_cost_usd")
20
+ }).from(llmUsage).where(whereClause).all();
21
+ const byModel = db.select({
22
+ provider: llmUsage.provider,
23
+ model: llmUsage.model,
24
+ calls: sql`count(*)`.as("calls"),
25
+ total_tokens: sql`coalesce(sum(${llmUsage.total_tokens}), 0)`.as("total_tokens"),
26
+ cost_usd: sql`coalesce(sum(${llmUsage.cost_usd}), 0)`.as("cost_usd")
27
+ }).from(llmUsage).where(whereClause).groupBy(llmUsage.provider, llmUsage.model).orderBy(desc(sql`count(*)`)).all();
28
+ const recent = db.select({
29
+ created_at: llmUsage.created_at,
30
+ provider: llmUsage.provider,
31
+ model: llmUsage.model,
32
+ task_kind: llmUsage.task_kind,
33
+ total_tokens: llmUsage.total_tokens,
34
+ cost_usd: llmUsage.cost_usd,
35
+ ok: llmUsage.ok
36
+ }).from(llmUsage).where(whereClause).orderBy(desc(llmUsage.created_at)).limit(opts.recentLimit ?? 10).all();
37
+ return {
38
+ since: sinceIso,
39
+ until: untilIso,
40
+ total_calls: totals?.total_calls ?? 0,
41
+ ok_calls: totals?.ok_calls ?? 0,
42
+ error_calls: totals?.error_calls ?? 0,
43
+ total_prompt_tokens: totals?.total_prompt_tokens ?? 0,
44
+ total_completion_tokens: totals?.total_completion_tokens ?? 0,
45
+ total_tokens: totals?.total_tokens ?? 0,
46
+ total_cost_usd: totals?.total_cost_usd ?? 0,
47
+ by_model: byModel.map((row) => ({
48
+ provider: row.provider,
49
+ model: row.model,
50
+ calls: row.calls,
51
+ total_tokens: row.total_tokens,
52
+ cost_usd: row.cost_usd
53
+ })),
54
+ recent: recent.map((row) => ({
55
+ created_at: row.created_at,
56
+ provider: row.provider,
57
+ model: row.model,
58
+ task_kind: row.task_kind,
59
+ total_tokens: row.total_tokens,
60
+ cost_usd: row.cost_usd,
61
+ ok: row.ok
62
+ }))
63
+ };
64
+ }
65
+ function formatUsageReport(summary) {
66
+ const lines = [
67
+ "# Recall LLM Usage",
68
+ `Window: ${summary.since} \u2192 ${summary.until}`,
69
+ `Total calls: ${summary.total_calls} (ok=${summary.ok_calls} err=${summary.error_calls})`,
70
+ `Total tokens: ${summary.total_tokens.toLocaleString()} (in=${summary.total_prompt_tokens.toLocaleString()} out=${summary.total_completion_tokens.toLocaleString()})`,
71
+ `Total cost: $${summary.total_cost_usd.toFixed(4)}`
72
+ ];
73
+ if (summary.by_model.length > 0) {
74
+ lines.push("", "## By model");
75
+ for (const row of summary.by_model) {
76
+ lines.push(
77
+ ` ${row.provider}/${row.model} calls=${row.calls} tokens=${row.total_tokens.toLocaleString()} cost=$${row.cost_usd.toFixed(4)}`
78
+ );
79
+ }
80
+ }
81
+ if (summary.recent.length > 0) {
82
+ lines.push("", "## Recent calls");
83
+ for (const row of summary.recent) {
84
+ const cost = row.cost_usd != null ? `$${row.cost_usd.toFixed(4)}` : "\u2014";
85
+ lines.push(
86
+ ` ${row.created_at} ${row.ok ? "ok " : "ERR"} ${row.provider}/${row.model} ${row.task_kind} tokens=${row.total_tokens} ${cost}`
87
+ );
88
+ }
89
+ }
90
+ return lines.join("\n");
91
+ }
92
+ function defaultSinceIso() {
93
+ const d = /* @__PURE__ */ new Date();
94
+ d.setUTCDate(d.getUTCDate() - 30);
95
+ return d.toISOString();
96
+ }
97
+ export {
98
+ formatUsageReport,
99
+ summarizeUsage
100
+ };
101
+ //# sourceMappingURL=usage-CY3V72YN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/llm/usage.ts"],"sourcesContent":["import { and, desc, gte, sql } from \"drizzle-orm\";\nimport type { RecallDb } from \"../db/client.js\";\nimport { llmUsage } from \"../db/schema.js\";\n\nexport interface UsageSummary {\n since: string;\n until: string;\n total_calls: number;\n ok_calls: number;\n error_calls: number;\n total_prompt_tokens: number;\n total_completion_tokens: number;\n total_tokens: number;\n total_cost_usd: number;\n by_model: Array<{\n provider: string;\n model: string;\n calls: number;\n total_tokens: number;\n cost_usd: number;\n }>;\n recent: Array<{\n created_at: string;\n provider: string;\n model: string;\n task_kind: string;\n total_tokens: number;\n cost_usd: number | null;\n ok: boolean;\n }>;\n}\n\nexport function summarizeUsage(\n db: RecallDb,\n opts: { sinceIso?: string; recentLimit?: number } = {},\n): UsageSummary {\n const sinceIso = opts.sinceIso ?? defaultSinceIso();\n const untilIso = new Date().toISOString();\n\n const whereClause = gte(llmUsage.created_at, sinceIso);\n\n const [totals] = db\n .select({\n total_calls: sql<number>`count(*)`.as(\"total_calls\"),\n ok_calls: sql<number>`sum(case when ${llmUsage.ok} = 1 then 1 else 0 end)`.as(\"ok_calls\"),\n error_calls: sql<number>`sum(case when ${llmUsage.ok} = 0 then 1 else 0 end)`.as(\"error_calls\"),\n total_prompt_tokens: sql<number>`coalesce(sum(${llmUsage.prompt_tokens}), 0)`.as(\"total_prompt_tokens\"),\n total_completion_tokens: sql<number>`coalesce(sum(${llmUsage.completion_tokens}), 0)`.as(\"total_completion_tokens\"),\n total_tokens: sql<number>`coalesce(sum(${llmUsage.total_tokens}), 0)`.as(\"total_tokens\"),\n total_cost_usd: sql<number>`coalesce(sum(${llmUsage.cost_usd}), 0)`.as(\"total_cost_usd\"),\n })\n .from(llmUsage)\n .where(whereClause)\n .all();\n\n const byModel = db\n .select({\n provider: llmUsage.provider,\n model: llmUsage.model,\n calls: sql<number>`count(*)`.as(\"calls\"),\n total_tokens: sql<number>`coalesce(sum(${llmUsage.total_tokens}), 0)`.as(\"total_tokens\"),\n cost_usd: sql<number>`coalesce(sum(${llmUsage.cost_usd}), 0)`.as(\"cost_usd\"),\n })\n .from(llmUsage)\n .where(whereClause)\n .groupBy(llmUsage.provider, llmUsage.model)\n .orderBy(desc(sql`count(*)`))\n .all();\n\n const recent = db\n .select({\n created_at: llmUsage.created_at,\n provider: llmUsage.provider,\n model: llmUsage.model,\n task_kind: llmUsage.task_kind,\n total_tokens: llmUsage.total_tokens,\n cost_usd: llmUsage.cost_usd,\n ok: llmUsage.ok,\n })\n .from(llmUsage)\n .where(whereClause)\n .orderBy(desc(llmUsage.created_at))\n .limit(opts.recentLimit ?? 10)\n .all();\n\n return {\n since: sinceIso,\n until: untilIso,\n total_calls: totals?.total_calls ?? 0,\n ok_calls: totals?.ok_calls ?? 0,\n error_calls: totals?.error_calls ?? 0,\n total_prompt_tokens: totals?.total_prompt_tokens ?? 0,\n total_completion_tokens: totals?.total_completion_tokens ?? 0,\n total_tokens: totals?.total_tokens ?? 0,\n total_cost_usd: totals?.total_cost_usd ?? 0,\n by_model: byModel.map((row) => ({\n provider: row.provider,\n model: row.model,\n calls: row.calls,\n total_tokens: row.total_tokens,\n cost_usd: row.cost_usd,\n })),\n recent: recent.map((row) => ({\n created_at: row.created_at,\n provider: row.provider,\n model: row.model,\n task_kind: row.task_kind,\n total_tokens: row.total_tokens,\n cost_usd: row.cost_usd,\n ok: row.ok,\n })),\n };\n}\n\nexport function formatUsageReport(summary: UsageSummary): string {\n const lines: string[] = [\n \"# Recall LLM Usage\",\n `Window: ${summary.since} → ${summary.until}`,\n `Total calls: ${summary.total_calls} (ok=${summary.ok_calls} err=${summary.error_calls})`,\n `Total tokens: ${summary.total_tokens.toLocaleString()} (in=${summary.total_prompt_tokens.toLocaleString()} out=${summary.total_completion_tokens.toLocaleString()})`,\n `Total cost: $${summary.total_cost_usd.toFixed(4)}`,\n ];\n\n if (summary.by_model.length > 0) {\n lines.push(\"\", \"## By model\");\n for (const row of summary.by_model) {\n lines.push(\n ` ${row.provider}/${row.model} calls=${row.calls} tokens=${row.total_tokens.toLocaleString()} cost=$${row.cost_usd.toFixed(4)}`,\n );\n }\n }\n\n if (summary.recent.length > 0) {\n lines.push(\"\", \"## Recent calls\");\n for (const row of summary.recent) {\n const cost = row.cost_usd != null ? `$${row.cost_usd.toFixed(4)}` : \"—\";\n lines.push(\n ` ${row.created_at} ${row.ok ? \"ok \" : \"ERR\"} ${row.provider}/${row.model} ${row.task_kind} tokens=${row.total_tokens} ${cost}`,\n );\n }\n }\n\n return lines.join(\"\\n\");\n}\n\nfunction defaultSinceIso(): string {\n const d = new Date();\n d.setUTCDate(d.getUTCDate() - 30);\n return d.toISOString();\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,240 @@
1
+ CREATE TABLE `activity_events` (
2
+ `id` text PRIMARY KEY NOT NULL,
3
+ `session_id` text,
4
+ `repo` text,
5
+ `path` text,
6
+ `source` text NOT NULL,
7
+ `event_type` text NOT NULL,
8
+ `memory_ids` text DEFAULT '[]' NOT NULL,
9
+ `request` text DEFAULT '{}' NOT NULL,
10
+ `result` text DEFAULT '{}' NOT NULL,
11
+ `created_at` text NOT NULL
12
+ );
13
+ --> statement-breakpoint
14
+ CREATE INDEX `idx_activity_session` ON `activity_events` (`session_id`);--> statement-breakpoint
15
+ CREATE INDEX `idx_activity_repo` ON `activity_events` (`repo`);--> statement-breakpoint
16
+ CREATE INDEX `idx_activity_event_type` ON `activity_events` (`event_type`);--> statement-breakpoint
17
+ CREATE INDEX `idx_activity_created` ON `activity_events` (`created_at`);--> statement-breakpoint
18
+ CREATE TABLE `approval_requests` (
19
+ `id` text PRIMARY KEY NOT NULL,
20
+ `memory_id` text NOT NULL,
21
+ `org_id` text NOT NULL,
22
+ `requested_by` text NOT NULL,
23
+ `status` text DEFAULT 'pending' NOT NULL,
24
+ `reviewed_by` text,
25
+ `reason` text,
26
+ `created_at` text NOT NULL,
27
+ `resolved_at` text,
28
+ FOREIGN KEY (`memory_id`) REFERENCES `memories`(`id`) ON UPDATE no action ON DELETE no action
29
+ );
30
+ --> statement-breakpoint
31
+ CREATE INDEX `idx_approval_org` ON `approval_requests` (`org_id`);--> statement-breakpoint
32
+ CREATE INDEX `idx_approval_status` ON `approval_requests` (`status`);--> statement-breakpoint
33
+ CREATE TABLE `audit_trail` (
34
+ `id` text PRIMARY KEY NOT NULL,
35
+ `memory_id` text NOT NULL,
36
+ `action` text NOT NULL,
37
+ `actor` text NOT NULL,
38
+ `before_snapshot` text,
39
+ `after_snapshot` text,
40
+ `reason` text,
41
+ `timestamp` text NOT NULL
42
+ );
43
+ --> statement-breakpoint
44
+ CREATE INDEX `idx_audit_memory` ON `audit_trail` (`memory_id`);--> statement-breakpoint
45
+ CREATE INDEX `idx_audit_timestamp` ON `audit_trail` (`timestamp`);--> statement-breakpoint
46
+ CREATE TABLE `contradictions` (
47
+ `id` text PRIMARY KEY NOT NULL,
48
+ `memory_a_id` text NOT NULL,
49
+ `memory_b_id` text NOT NULL,
50
+ `contradiction_type` text NOT NULL,
51
+ `severity` text NOT NULL,
52
+ `description` text NOT NULL,
53
+ `resolved` integer DEFAULT false NOT NULL,
54
+ `resolution` text,
55
+ `detected_at` text NOT NULL,
56
+ `resolved_at` text,
57
+ FOREIGN KEY (`memory_a_id`) REFERENCES `memories`(`id`) ON UPDATE no action ON DELETE no action,
58
+ FOREIGN KEY (`memory_b_id`) REFERENCES `memories`(`id`) ON UPDATE no action ON DELETE no action
59
+ );
60
+ --> statement-breakpoint
61
+ CREATE INDEX `idx_contradictions_resolved` ON `contradictions` (`resolved`);--> statement-breakpoint
62
+ CREATE TABLE `eval_sessions` (
63
+ `id` text PRIMARY KEY NOT NULL,
64
+ `repo` text NOT NULL,
65
+ `started_at` text NOT NULL,
66
+ `ended_at` text,
67
+ `memories_injected` integer DEFAULT 0 NOT NULL,
68
+ `memories_followed` integer DEFAULT 0 NOT NULL,
69
+ `memories_overridden` integer DEFAULT 0 NOT NULL,
70
+ `user_corrections` integer DEFAULT 0 NOT NULL,
71
+ `test_passes` integer DEFAULT 0 NOT NULL,
72
+ `test_failures` integer DEFAULT 0 NOT NULL
73
+ );
74
+ --> statement-breakpoint
75
+ CREATE INDEX `idx_eval_repo` ON `eval_sessions` (`repo`);--> statement-breakpoint
76
+ CREATE TABLE `feedback_events` (
77
+ `id` text PRIMARY KEY NOT NULL,
78
+ `memory_id` text NOT NULL,
79
+ `session_id` text NOT NULL,
80
+ `injected` integer NOT NULL,
81
+ `outcome` text NOT NULL,
82
+ `timestamp` text NOT NULL,
83
+ FOREIGN KEY (`memory_id`) REFERENCES `memories`(`id`) ON UPDATE no action ON DELETE no action
84
+ );
85
+ --> statement-breakpoint
86
+ CREATE INDEX `idx_feedback_memory` ON `feedback_events` (`memory_id`);--> statement-breakpoint
87
+ CREATE INDEX `idx_feedback_session` ON `feedback_events` (`session_id`);--> statement-breakpoint
88
+ CREATE TABLE `history_snippet_embeddings` (
89
+ `snippet_id` text PRIMARY KEY NOT NULL,
90
+ `model` text NOT NULL,
91
+ `embedding_dimensions` integer NOT NULL,
92
+ `index_dimensions` integer NOT NULL,
93
+ `version` text NOT NULL,
94
+ `content_hash` text NOT NULL,
95
+ `updated_at` text NOT NULL,
96
+ `embedding` blob NOT NULL,
97
+ FOREIGN KEY (`snippet_id`) REFERENCES `history_snippets`(`id`) ON UPDATE no action ON DELETE cascade
98
+ );
99
+ --> statement-breakpoint
100
+ CREATE INDEX `idx_history_embeddings_model` ON `history_snippet_embeddings` (`model`);--> statement-breakpoint
101
+ CREATE INDEX `idx_history_embeddings_updated` ON `history_snippet_embeddings` (`updated_at`);--> statement-breakpoint
102
+ CREATE TABLE `history_snippets` (
103
+ `id` text PRIMARY KEY NOT NULL,
104
+ `repo` text,
105
+ `session_id` text,
106
+ `kind` text NOT NULL,
107
+ `text` text NOT NULL,
108
+ `source_activity_ids` text DEFAULT '[]' NOT NULL,
109
+ `created_at` text NOT NULL,
110
+ `updated_at` text NOT NULL
111
+ );
112
+ --> statement-breakpoint
113
+ CREATE INDEX `idx_history_repo` ON `history_snippets` (`repo`);--> statement-breakpoint
114
+ CREATE INDEX `idx_history_session` ON `history_snippets` (`session_id`);--> statement-breakpoint
115
+ CREATE INDEX `idx_history_kind` ON `history_snippets` (`kind`);--> statement-breakpoint
116
+ CREATE INDEX `idx_history_created` ON `history_snippets` (`created_at`);--> statement-breakpoint
117
+ CREATE TABLE `hook_calls` (
118
+ `id` text PRIMARY KEY NOT NULL,
119
+ `event` text NOT NULL,
120
+ `agent` text NOT NULL,
121
+ `duration_ms` integer NOT NULL,
122
+ `ok` integer NOT NULL,
123
+ `created_at` text NOT NULL
124
+ );
125
+ --> statement-breakpoint
126
+ CREATE INDEX `idx_hook_calls_event` ON `hook_calls` (`event`);--> statement-breakpoint
127
+ CREATE INDEX `idx_hook_calls_agent` ON `hook_calls` (`agent`);--> statement-breakpoint
128
+ CREATE INDEX `idx_hook_calls_created` ON `hook_calls` (`created_at`);--> statement-breakpoint
129
+ CREATE TABLE `implicit_signals` (
130
+ `id` text PRIMARY KEY NOT NULL,
131
+ `memory_id` text NOT NULL,
132
+ `session_id` text NOT NULL,
133
+ `signal_type` text NOT NULL,
134
+ `timestamp` text NOT NULL,
135
+ `context` text,
136
+ FOREIGN KEY (`memory_id`) REFERENCES `memories`(`id`) ON UPDATE no action ON DELETE no action
137
+ );
138
+ --> statement-breakpoint
139
+ CREATE INDEX `idx_implicit_memory` ON `implicit_signals` (`memory_id`);--> statement-breakpoint
140
+ CREATE INDEX `idx_implicit_session` ON `implicit_signals` (`session_id`);--> statement-breakpoint
141
+ CREATE TABLE `memories` (
142
+ `id` text PRIMARY KEY NOT NULL,
143
+ `type` text NOT NULL,
144
+ `text` text NOT NULL,
145
+ `scope` text NOT NULL,
146
+ `path_scope` text,
147
+ `repo` text,
148
+ `status` text NOT NULL,
149
+ `confidence` real DEFAULT 0 NOT NULL,
150
+ `source` text NOT NULL,
151
+ `evidence` text DEFAULT '[]' NOT NULL,
152
+ `capture_context` text,
153
+ `supersedes` text,
154
+ `created_at` text NOT NULL,
155
+ `updated_at` text NOT NULL,
156
+ `last_validated_at` text,
157
+ `last_injected_at` text,
158
+ `injection_count` integer DEFAULT 0 NOT NULL,
159
+ `override_count` integer DEFAULT 0 NOT NULL,
160
+ `repetition_count` integer DEFAULT 0 NOT NULL,
161
+ `team_id` text,
162
+ `sync_version` integer DEFAULT 0 NOT NULL
163
+ );
164
+ --> statement-breakpoint
165
+ CREATE INDEX `idx_memories_repo` ON `memories` (`repo`);--> statement-breakpoint
166
+ CREATE INDEX `idx_memories_status` ON `memories` (`status`);--> statement-breakpoint
167
+ CREATE INDEX `idx_memories_repo_status` ON `memories` (`repo`,`status`);--> statement-breakpoint
168
+ CREATE INDEX `idx_memories_team` ON `memories` (`team_id`);--> statement-breakpoint
169
+ CREATE TABLE `memory_embeddings` (
170
+ `memory_id` text PRIMARY KEY NOT NULL,
171
+ `model` text NOT NULL,
172
+ `embedding_dimensions` integer NOT NULL,
173
+ `index_dimensions` integer NOT NULL,
174
+ `version` text NOT NULL,
175
+ `content_hash` text NOT NULL,
176
+ `updated_at` text NOT NULL,
177
+ `embedding` blob NOT NULL,
178
+ FOREIGN KEY (`memory_id`) REFERENCES `memories`(`id`) ON UPDATE no action ON DELETE cascade
179
+ );
180
+ --> statement-breakpoint
181
+ CREATE INDEX `idx_memory_embeddings_model` ON `memory_embeddings` (`model`);--> statement-breakpoint
182
+ CREATE INDEX `idx_memory_embeddings_updated` ON `memory_embeddings` (`updated_at`);--> statement-breakpoint
183
+ CREATE TABLE `memory_injections` (
184
+ `id` text PRIMARY KEY NOT NULL,
185
+ `memory_id` text NOT NULL,
186
+ `session_id` text NOT NULL,
187
+ `repo` text,
188
+ `injected_at` text NOT NULL,
189
+ `outcome` text,
190
+ `outcome_at` text,
191
+ FOREIGN KEY (`memory_id`) REFERENCES `memories`(`id`) ON UPDATE no action ON DELETE cascade
192
+ );
193
+ --> statement-breakpoint
194
+ CREATE INDEX `idx_memory_injections_memory` ON `memory_injections` (`memory_id`);--> statement-breakpoint
195
+ CREATE INDEX `idx_memory_injections_session` ON `memory_injections` (`session_id`);--> statement-breakpoint
196
+ CREATE UNIQUE INDEX `uq_memory_injections_memory_session` ON `memory_injections` (`memory_id`,`session_id`);--> statement-breakpoint
197
+ CREATE TABLE `memory_maintenance_tasks` (
198
+ `id` text PRIMARY KEY NOT NULL,
199
+ `kind` text NOT NULL,
200
+ `status` text NOT NULL,
201
+ `priority` integer DEFAULT 0 NOT NULL,
202
+ `repo` text,
203
+ `target_key` text NOT NULL,
204
+ `payload` text NOT NULL,
205
+ `result` text,
206
+ `failure_reason` text,
207
+ `claimed_by` text,
208
+ `claimed_at` text,
209
+ `claim_expires_at` text,
210
+ `submitted_at` text,
211
+ `completed_at` text,
212
+ `created_at` text NOT NULL,
213
+ `attempts` integer DEFAULT 0 NOT NULL,
214
+ `max_attempts` integer DEFAULT 3 NOT NULL
215
+ );
216
+ --> statement-breakpoint
217
+ CREATE INDEX `idx_mmt_status_priority` ON `memory_maintenance_tasks` (`status`,`priority`,`created_at`);--> statement-breakpoint
218
+ CREATE INDEX `idx_mmt_repo_status` ON `memory_maintenance_tasks` (`repo`,`status`);--> statement-breakpoint
219
+ CREATE INDEX `idx_mmt_claim_expires` ON `memory_maintenance_tasks` (`claim_expires_at`);--> statement-breakpoint
220
+ CREATE INDEX `idx_mmt_kind_target` ON `memory_maintenance_tasks` (`kind`,`target_key`);--> statement-breakpoint
221
+ CREATE TABLE `policy_rules` (
222
+ `id` text PRIMARY KEY NOT NULL,
223
+ `org_id` text NOT NULL,
224
+ `rule_type` text NOT NULL,
225
+ `config` text DEFAULT '{}' NOT NULL,
226
+ `enabled` integer DEFAULT true NOT NULL,
227
+ `created_at` text NOT NULL,
228
+ `updated_at` text NOT NULL
229
+ );
230
+ --> statement-breakpoint
231
+ CREATE INDEX `idx_policy_org` ON `policy_rules` (`org_id`);--> statement-breakpoint
232
+ CREATE TABLE `sync_state` (
233
+ `id` text PRIMARY KEY NOT NULL,
234
+ `remote_url` text,
235
+ `team_id` text,
236
+ `last_push_at` text,
237
+ `last_pull_at` text,
238
+ `last_push_version` integer DEFAULT 0 NOT NULL,
239
+ `last_pull_version` integer DEFAULT 0 NOT NULL
240
+ );
@@ -0,0 +1,21 @@
1
+ CREATE TABLE `llm_usage` (
2
+ `id` text PRIMARY KEY NOT NULL,
3
+ `provider` text NOT NULL,
4
+ `model` text NOT NULL,
5
+ `task_kind` text NOT NULL,
6
+ `task_id` text,
7
+ `repo` text,
8
+ `prompt_tokens` integer DEFAULT 0 NOT NULL,
9
+ `completion_tokens` integer DEFAULT 0 NOT NULL,
10
+ `total_tokens` integer DEFAULT 0 NOT NULL,
11
+ `cost_usd` real,
12
+ `duration_ms` integer DEFAULT 0 NOT NULL,
13
+ `ok` integer DEFAULT true NOT NULL,
14
+ `error` text,
15
+ `created_at` text NOT NULL
16
+ );
17
+ --> statement-breakpoint
18
+ CREATE INDEX `idx_llm_usage_created` ON `llm_usage` (`created_at`);--> statement-breakpoint
19
+ CREATE INDEX `idx_llm_usage_provider_model` ON `llm_usage` (`provider`,`model`);--> statement-breakpoint
20
+ CREATE INDEX `idx_llm_usage_task_kind` ON `llm_usage` (`task_kind`);--> statement-breakpoint
21
+ CREATE INDEX `idx_llm_usage_repo` ON `llm_usage` (`repo`);
@@ -0,0 +1,18 @@
1
+ CREATE TABLE `maintenance_cleanup_log` (
2
+ `id` text PRIMARY KEY NOT NULL,
3
+ `run_id` text NOT NULL,
4
+ `action` text NOT NULL,
5
+ `memory_id` text NOT NULL,
6
+ `related_memory_id` text,
7
+ `before_snapshot` text,
8
+ `after_snapshot` text,
9
+ `details` text DEFAULT '{}' NOT NULL,
10
+ `reverted` integer DEFAULT false NOT NULL,
11
+ `reverted_at` text,
12
+ `created_at` text NOT NULL
13
+ );
14
+ --> statement-breakpoint
15
+ CREATE INDEX `idx_cleanup_log_run` ON `maintenance_cleanup_log` (`run_id`);--> statement-breakpoint
16
+ CREATE INDEX `idx_cleanup_log_memory` ON `maintenance_cleanup_log` (`memory_id`);--> statement-breakpoint
17
+ CREATE INDEX `idx_cleanup_log_action` ON `maintenance_cleanup_log` (`action`);--> statement-breakpoint
18
+ CREATE INDEX `idx_cleanup_log_created` ON `maintenance_cleanup_log` (`created_at`);
@@ -0,0 +1,19 @@
1
+ CREATE TABLE `quality_snapshots` (
2
+ `id` text PRIMARY KEY NOT NULL,
3
+ `taken_at` text NOT NULL,
4
+ `window_start` text NOT NULL,
5
+ `window_end` text NOT NULL,
6
+ `injections_total` integer NOT NULL,
7
+ `injections_resolved` integer NOT NULL,
8
+ `injections_followed` integer NOT NULL,
9
+ `injections_overridden` integer NOT NULL,
10
+ `injections_contradicted` integer NOT NULL,
11
+ `injections_ignored` integer NOT NULL,
12
+ `followed_rate_resolved` real,
13
+ `active_rule_count` integer NOT NULL,
14
+ `active_command_count` integer NOT NULL,
15
+ `candidate_correction_count` integer NOT NULL,
16
+ `notes` text
17
+ );
18
+ --> statement-breakpoint
19
+ CREATE INDEX `idx_quality_snapshots_taken` ON `quality_snapshots` (`taken_at`);
@@ -0,0 +1 @@
1
+ ALTER TABLE `memories` ADD `auto_inject` integer DEFAULT true NOT NULL;
@@ -0,0 +1,96 @@
1
+ ALTER TABLE `activity_events` ADD `dedupe_key` text;--> statement-breakpoint
2
+ UPDATE `activity_events`
3
+ SET `dedupe_key` =
4
+ 'activity' || char(31) ||
5
+ coalesce(`session_id`, '') || char(31) ||
6
+ coalesce(`repo`, '') || char(31) ||
7
+ coalesce(`path`, '') || char(31) ||
8
+ `source` || char(31) ||
9
+ `event_type` || char(31) ||
10
+ `request` || char(31) ||
11
+ `result`
12
+ WHERE `session_id` IS NOT NULL
13
+ AND `id` IN (
14
+ SELECT `id` FROM (
15
+ SELECT
16
+ `id`,
17
+ row_number() OVER (
18
+ PARTITION BY
19
+ coalesce(`session_id`, ''),
20
+ coalesce(`repo`, ''),
21
+ coalesce(`path`, ''),
22
+ `source`,
23
+ `event_type`,
24
+ `request`,
25
+ `result`
26
+ ORDER BY `created_at`, `id`
27
+ ) AS `rn`
28
+ FROM `activity_events`
29
+ WHERE `session_id` IS NOT NULL
30
+ )
31
+ WHERE `rn` = 1
32
+ );--> statement-breakpoint
33
+ CREATE UNIQUE INDEX `uq_activity_events_dedupe_key` ON `activity_events` (`dedupe_key`);--> statement-breakpoint
34
+ ALTER TABLE `history_snippets` ADD `dedupe_key` text;--> statement-breakpoint
35
+ UPDATE `history_snippets`
36
+ SET `dedupe_key` =
37
+ 'history' || char(31) ||
38
+ coalesce(`repo`, '') || char(31) ||
39
+ coalesce(`session_id`, '') || char(31) ||
40
+ `kind` || char(31) ||
41
+ lower(trim(rtrim(`text`, ' .;:,!?`')))
42
+ WHERE `id` IN (
43
+ SELECT `id` FROM (
44
+ SELECT
45
+ `id`,
46
+ row_number() OVER (
47
+ PARTITION BY
48
+ coalesce(`repo`, ''),
49
+ coalesce(`session_id`, ''),
50
+ `kind`,
51
+ lower(trim(rtrim(`text`, ' .;:,!?`')))
52
+ ORDER BY `created_at`, `id`
53
+ ) AS `rn`
54
+ FROM `history_snippets`
55
+ )
56
+ WHERE `rn` = 1
57
+ );--> statement-breakpoint
58
+ CREATE UNIQUE INDEX `uq_history_snippets_dedupe_key` ON `history_snippets` (`dedupe_key`);--> statement-breakpoint
59
+ ALTER TABLE `memories` ADD `dedupe_key` text;--> statement-breakpoint
60
+ UPDATE `memories`
61
+ SET `dedupe_key` =
62
+ 'memory' || char(31) ||
63
+ `type` || char(31) ||
64
+ `scope` || char(31) ||
65
+ coalesce(`repo`, '') || char(31) ||
66
+ coalesce(`path_scope`, '') || char(31) ||
67
+ lower(trim(rtrim(`text`, ' .;:,!?`')))
68
+ WHERE `status` != 'rejected'
69
+ AND `id` IN (
70
+ SELECT `id` FROM (
71
+ SELECT
72
+ `id`,
73
+ row_number() OVER (
74
+ PARTITION BY
75
+ `type`,
76
+ `scope`,
77
+ coalesce(`repo`, ''),
78
+ coalesce(`path_scope`, ''),
79
+ lower(trim(rtrim(`text`, ' .;:,!?`')))
80
+ ORDER BY
81
+ CASE `status`
82
+ WHEN 'active' THEN 0
83
+ WHEN 'candidate' THEN 1
84
+ WHEN 'transient' THEN 2
85
+ ELSE 3
86
+ END,
87
+ `confidence` DESC,
88
+ `created_at`,
89
+ `id`
90
+ ) AS `rn`
91
+ FROM `memories`
92
+ WHERE `status` != 'rejected'
93
+ )
94
+ WHERE `rn` = 1
95
+ );--> statement-breakpoint
96
+ CREATE UNIQUE INDEX `uq_memories_dedupe_key` ON `memories` (`dedupe_key`);
@@ -0,0 +1,2 @@
1
+ ALTER TABLE `hook_calls` ADD `dedupe_key` text;--> statement-breakpoint
2
+ CREATE UNIQUE INDEX `uq_hook_calls_dedupe_key` ON `hook_calls` (`dedupe_key`);
@@ -0,0 +1,15 @@
1
+ CREATE TABLE `history_injections` (
2
+ `id` text PRIMARY KEY NOT NULL,
3
+ `snippet_id` text NOT NULL,
4
+ `session_id` text NOT NULL,
5
+ `repo` text,
6
+ `injected_at` text NOT NULL,
7
+ FOREIGN KEY (`snippet_id`) REFERENCES `history_snippets`(`id`) ON UPDATE no action ON DELETE cascade
8
+ );
9
+ --> statement-breakpoint
10
+ CREATE INDEX `idx_history_injections_snippet` ON `history_injections` (`snippet_id`);--> statement-breakpoint
11
+ CREATE INDEX `idx_history_injections_session` ON `history_injections` (`session_id`);--> statement-breakpoint
12
+ CREATE INDEX `idx_history_injections_repo` ON `history_injections` (`repo`);--> statement-breakpoint
13
+ CREATE UNIQUE INDEX `uq_history_injections_snippet_session` ON `history_injections` (`snippet_id`,`session_id`);--> statement-breakpoint
14
+ ALTER TABLE `quality_snapshots` ADD `history_injections_total` integer DEFAULT 0 NOT NULL;--> statement-breakpoint
15
+ ALTER TABLE `quality_snapshots` ADD `history_snippets_injected` integer DEFAULT 0 NOT NULL;