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.
Files changed (186) hide show
  1. rememberstack/__init__.py +9 -0
  2. rememberstack/adapters/__init__.py +42 -0
  3. rememberstack/adapters/codex_writer.py +221 -0
  4. rememberstack/adapters/markitdown_converter.py +42 -0
  5. rememberstack/adapters/openrouter.py +136 -0
  6. rememberstack/adapters/selfhost/__init__.py +54 -0
  7. rememberstack/adapters/selfhost/forget.py +66 -0
  8. rememberstack/adapters/selfhost/git.py +374 -0
  9. rememberstack/adapters/selfhost/lance.py +328 -0
  10. rememberstack/adapters/selfhost/minio.py +279 -0
  11. rememberstack/adapters/selfhost/mounts.py +249 -0
  12. rememberstack/adapters/selfhost/object_store.py +130 -0
  13. rememberstack/adapters/selfhost/projection.py +80 -0
  14. rememberstack/adapters/selfhost/queue.py +137 -0
  15. rememberstack/adapters/selfhost/telemetry.py +45 -0
  16. rememberstack/adapters/selfhost/watcher.py +70 -0
  17. rememberstack/adapters/testing/__init__.py +15 -0
  18. rememberstack/adapters/testing/cost_meter.py +13 -0
  19. rememberstack/adapters/testing/model_provider.py +83 -0
  20. rememberstack/adapters/testing/queue.py +43 -0
  21. rememberstack/adapters/testing/telemetry.py +22 -0
  22. rememberstack/client.py +19 -0
  23. rememberstack/core/__init__.py +127 -0
  24. rememberstack/core/blockizer.py +189 -0
  25. rememberstack/core/chunker.py +216 -0
  26. rememberstack/core/consumption_skill.py +275 -0
  27. rememberstack/core/conversion.py +76 -0
  28. rememberstack/core/core_manifest.py +598 -0
  29. rememberstack/core/extension_packs.py +124 -0
  30. rememberstack/core/forget.py +17 -0
  31. rememberstack/core/knowledge_authored.py +276 -0
  32. rememberstack/core/knowledge_compile.py +215 -0
  33. rememberstack/core/knowledge_fact_sheet.py +210 -0
  34. rememberstack/core/knowledge_hashing.py +68 -0
  35. rememberstack/core/knowledge_planner.py +64 -0
  36. rememberstack/core/knowledge_writer.py +175 -0
  37. rememberstack/core/ranking.py +200 -0
  38. rememberstack/core/recipe_linter.py +149 -0
  39. rememberstack/core/section_snap.py +209 -0
  40. rememberstack/core/storage_routing.py +27 -0
  41. rememberstack/eval/__init__.py +53 -0
  42. rememberstack/eval/consumption.py +141 -0
  43. rememberstack/eval/contradiction.py +184 -0
  44. rememberstack/eval/harness.py +136 -0
  45. rememberstack/eval/lifecycle.py +400 -0
  46. rememberstack/eval/operational_scale.py +49 -0
  47. rememberstack/eval/resolution.py +255 -0
  48. rememberstack/eval/retrieval_spikes.py +50 -0
  49. rememberstack/eval/skeleton.py +231 -0
  50. rememberstack/llm/__init__.py +1 -0
  51. rememberstack/model/__init__.py +589 -0
  52. rememberstack/model/adjudication.py +100 -0
  53. rememberstack/model/auth.py +27 -0
  54. rememberstack/model/blocks.py +30 -0
  55. rememberstack/model/chunks.py +190 -0
  56. rememberstack/model/claims.py +162 -0
  57. rememberstack/model/client.py +98 -0
  58. rememberstack/model/clustering.py +54 -0
  59. rememberstack/model/component_version.py +124 -0
  60. rememberstack/model/consumption.py +88 -0
  61. rememberstack/model/conversion.py +31 -0
  62. rememberstack/model/deployment.py +53 -0
  63. rememberstack/model/documents.py +168 -0
  64. rememberstack/model/envelope.py +513 -0
  65. rememberstack/model/evaluation.py +72 -0
  66. rememberstack/model/forget.py +143 -0
  67. rememberstack/model/git.py +13 -0
  68. rememberstack/model/knowledge.py +840 -0
  69. rememberstack/model/knowledge_authored.py +325 -0
  70. rememberstack/model/knowledge_planner.py +431 -0
  71. rememberstack/model/lifecycle.py +42 -0
  72. rememberstack/model/model_provider.py +78 -0
  73. rememberstack/model/mounts.py +24 -0
  74. rememberstack/model/object_store.py +21 -0
  75. rememberstack/model/operational_scale.py +59 -0
  76. rememberstack/model/operations.py +153 -0
  77. rememberstack/model/processing.py +228 -0
  78. rememberstack/model/queue.py +73 -0
  79. rememberstack/model/recipes.py +83 -0
  80. rememberstack/model/relations.py +79 -0
  81. rememberstack/model/resolution.py +83 -0
  82. rememberstack/model/retrieval_spikes.py +62 -0
  83. rememberstack/model/sections.py +120 -0
  84. rememberstack/model/telemetry.py +30 -0
  85. rememberstack/ports/__init__.py +29 -0
  86. rememberstack/ports/auth.py +16 -0
  87. rememberstack/ports/connector.py +23 -0
  88. rememberstack/ports/cost_meter.py +17 -0
  89. rememberstack/ports/forget.py +20 -0
  90. rememberstack/ports/git.py +20 -0
  91. rememberstack/ports/model_provider.py +28 -0
  92. rememberstack/ports/mounts.py +16 -0
  93. rememberstack/ports/object_store.py +27 -0
  94. rememberstack/ports/p1_index.py +92 -0
  95. rememberstack/ports/purge.py +93 -0
  96. rememberstack/ports/queue.py +23 -0
  97. rememberstack/ports/telemetry.py +21 -0
  98. rememberstack/profiles/__init__.py +22 -0
  99. rememberstack/profiles/selfhost.py +324 -0
  100. rememberstack/profiles/selfhost_forget.py +158 -0
  101. rememberstack/profiles/selfhost_operations.py +95 -0
  102. rememberstack/py.typed +1 -0
  103. rememberstack/spine/__init__.py +93 -0
  104. rememberstack/spine/admission.py +26 -0
  105. rememberstack/spine/backfill.py +168 -0
  106. rememberstack/spine/catalog_contract.py +742 -0
  107. rememberstack/spine/chunk_catalog.py +237 -0
  108. rememberstack/spine/claim_catalog.py +298 -0
  109. rememberstack/spine/clustering.py +740 -0
  110. rememberstack/spine/component_versions.py +208 -0
  111. rememberstack/spine/consumption.py +81 -0
  112. rememberstack/spine/deployment_bootstrap.py +445 -0
  113. rememberstack/spine/document_catalog.py +621 -0
  114. rememberstack/spine/entity_registry.py +205 -0
  115. rememberstack/spine/extension_packs.py +220 -0
  116. rememberstack/spine/fact_catalog.py +571 -0
  117. rememberstack/spine/forget.py +1753 -0
  118. rememberstack/spine/knowledge.py +5467 -0
  119. rememberstack/spine/lifecycle.py +1071 -0
  120. rememberstack/spine/migrations/__init__.py +1 -0
  121. rememberstack/spine/migrations/_helpers.py +153 -0
  122. rememberstack/spine/migrations/env.py +58 -0
  123. rememberstack/spine/migrations/script.py.mako +27 -0
  124. rememberstack/spine/migrations/versions/__init__.py +1 -0
  125. rememberstack/spine/migrations/versions/p0_02_0001_extensions_enums.py +189 -0
  126. rememberstack/spine/migrations/versions/p0_02_0002_infrastructure_registries.py +321 -0
  127. rememberstack/spine/migrations/versions/p0_02_0003_entities_evaluation_e0_e1.py +631 -0
  128. rememberstack/spine/migrations/versions/p0_02_0004_claims_facts_evidence.py +411 -0
  129. rememberstack/spine/migrations/versions/p0_02_0005_projection_knowledge_retrieval.py +391 -0
  130. rememberstack/spine/migrations/versions/p0_02_0006_partitions_views.py +158 -0
  131. rememberstack/spine/migrations/versions/p2_06_0007_invalidated_outcome.py +26 -0
  132. rememberstack/spine/migrations/versions/p3_01_0008_document_version_target.py +58 -0
  133. rememberstack/spine/migrations/versions/p3_05_0009_reconcile_stage.py +27 -0
  134. rememberstack/spine/migrations/versions/p3_07_0010_lifecycle_eval_suite.py +25 -0
  135. rememberstack/spine/migrations/versions/p4_01_0011_survivor_view_rewrite.py +57 -0
  136. rememberstack/spine/migrations/versions/p6_02_0012_knowledge_compile_recovery.py +58 -0
  137. rememberstack/spine/migrations/versions/p6_04_0013_knowledge_writer_ledger.py +46 -0
  138. rememberstack/spine/migrations/versions/p6_05_0014_knowledge_planner_runtime.py +217 -0
  139. rememberstack/spine/migrations/versions/p6_06_0015_authored_dispatch_runtime.py +38 -0
  140. rememberstack/spine/migrations/versions/p7_02_0016_operational_eval_suite.py +19 -0
  141. rememberstack/spine/migrations/versions/p7_05_0017_hard_forget.py +55 -0
  142. rememberstack/spine/observation_adjudication.py +778 -0
  143. rememberstack/spine/operations.py +298 -0
  144. rememberstack/spine/projection.py +662 -0
  145. rememberstack/spine/recipes.py +276 -0
  146. rememberstack/spine/resolver.py +763 -0
  147. rememberstack/spine/review.py +650 -0
  148. rememberstack/spine/settings.py +22 -0
  149. rememberstack/spine/supersession.py +510 -0
  150. rememberstack/spine/sync.py +128 -0
  151. rememberstack/spine/work_ledger.py +816 -0
  152. rememberstack/surfaces/__init__.py +110 -0
  153. rememberstack/surfaces/cli.py +447 -0
  154. rememberstack/surfaces/consumption_skill.py +87 -0
  155. rememberstack/surfaces/graph_queries.py +698 -0
  156. rememberstack/surfaces/http_api.py +377 -0
  157. rememberstack/surfaces/mcp.py +67 -0
  158. rememberstack/surfaces/query_engine.py +1591 -0
  159. rememberstack/surfaces/recipe_executor.py +185 -0
  160. rememberstack/surfaces/recipe_surface.py +219 -0
  161. rememberstack/surfaces/remote_mcp.py +133 -0
  162. rememberstack/surfaces/sdk.py +324 -0
  163. rememberstack/workers/__init__.py +155 -0
  164. rememberstack/workers/base.py +312 -0
  165. rememberstack/workers/e0.py +577 -0
  166. rememberstack/workers/e1.py +425 -0
  167. rememberstack/workers/e2.py +525 -0
  168. rememberstack/workers/e3.py +434 -0
  169. rememberstack/workers/forget.py +299 -0
  170. rememberstack/workers/knowledge_authored.py +146 -0
  171. rememberstack/workers/knowledge_driver.py +735 -0
  172. rememberstack/workers/knowledge_fact_sheet.py +123 -0
  173. rememberstack/workers/knowledge_planner.py +325 -0
  174. rememberstack/workers/knowledge_writer.py +393 -0
  175. rememberstack/workers/operations.py +42 -0
  176. rememberstack/workers/p1.py +234 -0
  177. rememberstack/workers/p2.py +513 -0
  178. rememberstack/workers/p2_analytics.py +276 -0
  179. rememberstack/workers/p3.py +673 -0
  180. rememberstack/workers/reconcile.py +485 -0
  181. rememberstack/workers/sync.py +168 -0
  182. rememberstack-0.1.0.dist-info/METADATA +213 -0
  183. rememberstack-0.1.0.dist-info/RECORD +186 -0
  184. rememberstack-0.1.0.dist-info/WHEEL +4 -0
  185. rememberstack-0.1.0.dist-info/entry_points.txt +2 -0
  186. rememberstack-0.1.0.dist-info/licenses/LICENSE +201 -0
@@ -0,0 +1,276 @@
1
+ """The recipe registry (D50): frozen query plans as rows the surfaces render.
2
+
3
+ `RecipeRegistry` is the write and read side of `retrieval_recipes`. Every
4
+ registration passes the `core` linter first, so a row that would let a recipe
5
+ misreport its grain never lands — the linter is the chain-level half of the
6
+ D41 bar, the DB CHECK the enum half. Reads return only `status='active'`
7
+ rows: those are what the MCP tool list, the CLI, and the API render from.
8
+
9
+ Adding a query pattern is inserting a row here — never new code — which is
10
+ exactly why a recipe can add no capability: the executor (surfaces) replays
11
+ whatever chain the row carries, and nothing else.
12
+ """
13
+
14
+ import json
15
+ from uuid import UUID
16
+ from uuid import uuid4
17
+
18
+ from sqlalchemy import bindparam
19
+ from sqlalchemy import JSON
20
+ from sqlalchemy import RowMapping
21
+ from sqlalchemy import text
22
+ from sqlalchemy.engine import Engine
23
+
24
+ from rememberstack.core import lint_recipe
25
+ from rememberstack.model import Grain
26
+ from rememberstack.model import Recipe
27
+ from rememberstack.model import RecipeAnswerIntent
28
+ from rememberstack.model import RecipeStep
29
+
30
+
31
+ class RecipeRegistry:
32
+ """Register and read the deployment's retrieval recipes (D50)."""
33
+
34
+ def __init__(self, *, engine: Engine) -> None:
35
+ """Bind the registry to the deployment's spine."""
36
+ self._engine = engine
37
+
38
+ def register(self, *, deployment_id: UUID, recipe: Recipe) -> None:
39
+ """Lint, then insert one recipe version (idempotent per name+version).
40
+
41
+ The linter runs BEFORE the write (`RecipeLintError` on a bad chain),
42
+ so an invalid recipe never becomes a row. Re-registering the same
43
+ `(name, version)` is a no-op, which makes seeding safe to repeat.
44
+ """
45
+ lint_recipe(recipe)
46
+ with self._engine.begin() as connection:
47
+ connection.execute(
48
+ _INSERT_RECIPE,
49
+ {
50
+ "recipe_id": uuid4(),
51
+ "deployment_id": deployment_id,
52
+ "name": recipe.name,
53
+ "description": recipe.description,
54
+ "parameters": recipe.parameters,
55
+ "chain": [step.model_dump(mode="json") for step in recipe.chain],
56
+ "output_grain": recipe.output_grain.value,
57
+ "answer_intent": recipe.answer_intent.value,
58
+ "version": recipe.version,
59
+ },
60
+ )
61
+
62
+ def active(self, *, deployment_id: UUID) -> tuple[Recipe, ...]:
63
+ """Every active recipe, name-ordered — the surface's tool list."""
64
+ with self._engine.connect() as connection:
65
+ rows = (
66
+ connection.execute(_ACTIVE_RECIPES, {"deployment_id": deployment_id})
67
+ .mappings()
68
+ .all()
69
+ )
70
+ return tuple(_recipe_from_row(row) for row in rows)
71
+
72
+ def by_name(self, *, deployment_id: UUID, name: str) -> Recipe | None:
73
+ """The latest active version of one recipe, or None if none exists."""
74
+ with self._engine.connect() as connection:
75
+ row = (
76
+ connection.execute(
77
+ _RECIPE_BY_NAME, {"deployment_id": deployment_id, "name": name}
78
+ )
79
+ .mappings()
80
+ .one_or_none()
81
+ )
82
+ return None if row is None else _recipe_from_row(row)
83
+
84
+
85
+ def _recipe_from_row(row: RowMapping) -> Recipe:
86
+ """Rebuild a Recipe (typed chain and all) from one registry row."""
87
+ raw_chain = row["chain"]
88
+ chain_items = (
89
+ raw_chain if isinstance(raw_chain, list) else json.loads(str(raw_chain))
90
+ )
91
+ raw_parameters = row["parameters"]
92
+ parameters = (
93
+ raw_parameters
94
+ if isinstance(raw_parameters, dict)
95
+ else json.loads(str(raw_parameters))
96
+ )
97
+ return Recipe(
98
+ name=str(row["name"]),
99
+ description=str(row["description"]),
100
+ parameters=parameters,
101
+ chain=tuple(RecipeStep.model_validate(item) for item in chain_items),
102
+ output_grain=Grain(row["output_grain"]),
103
+ answer_intent=RecipeAnswerIntent(row["answer_intent"]),
104
+ version=int(str(row["version"])),
105
+ )
106
+
107
+
108
+ _INSERT_RECIPE = text(
109
+ """
110
+ INSERT INTO retrieval_recipes (recipe_id, deployment_id, name, description,
111
+ parameters, chain, output_grain, answer_intent, version)
112
+ VALUES (:recipe_id, :deployment_id, :name, :description, :parameters,
113
+ :chain, CAST(:output_grain AS recipe_output_grain),
114
+ CAST(:answer_intent AS recipe_answer_intent), :version)
115
+ ON CONFLICT (deployment_id, name, version) DO NOTHING
116
+ """
117
+ ).bindparams(bindparam("parameters", type_=JSON), bindparam("chain", type_=JSON))
118
+
119
+ _RECIPE_COLUMNS = (
120
+ "name, description, parameters, chain, output_grain::text AS output_grain,"
121
+ " answer_intent::text AS answer_intent, version"
122
+ )
123
+
124
+ _ACTIVE_RECIPES = text(
125
+ f"""
126
+ SELECT {_RECIPE_COLUMNS}
127
+ FROM retrieval_recipes
128
+ WHERE deployment_id = :deployment_id AND status = 'active'
129
+ ORDER BY name, version DESC
130
+ """ # noqa: S608 — _RECIPE_COLUMNS is a module constant, not user input
131
+ )
132
+
133
+ _RECIPE_BY_NAME = text(
134
+ f"""
135
+ SELECT {_RECIPE_COLUMNS}
136
+ FROM retrieval_recipes
137
+ WHERE deployment_id = :deployment_id AND name = :name AND status = 'active'
138
+ ORDER BY version DESC
139
+ LIMIT 1
140
+ """ # noqa: S608 — _RECIPE_COLUMNS is a module constant, not user input
141
+ )
142
+
143
+
144
+ # ─────────────────────────────────────────────────────────────────────────
145
+ # The canonical recipe set (retrieval §4), each a frozen composition of the
146
+ # zero-LLM primitives. These are seeded into every deployment; the surfaces
147
+ # render their tool list from the rows, and the eval harness proves each is
148
+ # exactly its chain. Adding a query pattern is adding an entry here.
149
+ # ─────────────────────────────────────────────────────────────────────────
150
+ CANONICAL_RECIPES: tuple[Recipe, ...] = (
151
+ Recipe(
152
+ name="relation_current",
153
+ description="Current relations matching a subject and optional predicate"
154
+ " — 'who does X work for now?' (S1). Validity-filtered, fact grain.",
155
+ parameters={
156
+ "subject_entity_id": {"type": "uuid", "required": True},
157
+ "predicate": {"type": "string", "required": False},
158
+ },
159
+ chain=(
160
+ RecipeStep(
161
+ op="lookup_relations",
162
+ bind={
163
+ "subject_entity_id": "subject_entity_id",
164
+ "predicate": "predicate",
165
+ },
166
+ ),
167
+ ),
168
+ output_grain=Grain.FACT,
169
+ answer_intent=RecipeAnswerIntent.CURRENT_FACTS,
170
+ ),
171
+ Recipe(
172
+ name="observation_current",
173
+ description="Current observations on an entity — 'what do we know about"
174
+ " X now?' (S2). Validity-filtered, fact grain.",
175
+ parameters={"entity_id": {"type": "uuid", "required": True}},
176
+ chain=(RecipeStep(op="lookup_observations", bind={"entity_id": "entity_id"}),),
177
+ output_grain=Grain.FACT,
178
+ answer_intent=RecipeAnswerIntent.CURRENT_FACTS,
179
+ ),
180
+ Recipe(
181
+ name="entity_timeline",
182
+ description="An entity's facts by year — its evolution over time (S30)."
183
+ " A bounded fact aggregate, an orientation over history.",
184
+ parameters={"entity_id": {"type": "uuid", "required": True}},
185
+ chain=(
186
+ RecipeStep(
187
+ op="aggregate",
188
+ settings={"form": "timeline"},
189
+ bind={"subject_entity_id": "entity_id"},
190
+ ),
191
+ ),
192
+ output_grain=Grain.FACT,
193
+ answer_intent=RecipeAnswerIntent.ORIENTATION,
194
+ ),
195
+ Recipe(
196
+ name="claims_verbatim",
197
+ description="What sources actually asserted, verbatim, for a query"
198
+ " (S6). Evidence grain — never a current-fact answer (the D41 bar).",
199
+ parameters={
200
+ "query": {"type": "string", "required": True},
201
+ "k": {"type": "integer", "required": False, "default": 10},
202
+ },
203
+ chain=(RecipeStep(op="search_claims", bind={"query": "query", "k": "k"}),),
204
+ output_grain=Grain.EVIDENCE,
205
+ answer_intent=RecipeAnswerIntent.ASSERTION_HISTORY,
206
+ ),
207
+ Recipe(
208
+ name="claims_hybrid_rrf",
209
+ description="Verbatim claims for a query, fused across parallel channel"
210
+ " orderings by reciprocal-rank fusion (S46). Evidence grain.",
211
+ parameters={
212
+ "query": {"type": "string", "required": True},
213
+ "k": {"type": "integer", "required": False, "default": 10},
214
+ },
215
+ chain=(
216
+ RecipeStep(op="search_claims", bind={"query": "query", "k": "k"}),
217
+ RecipeStep(op="search_claims", bind={"query": "query", "k": "k"}),
218
+ RecipeStep(op="fuse", settings={"k": 60}, inputs=(0, 1)),
219
+ ),
220
+ output_grain=Grain.EVIDENCE,
221
+ answer_intent=RecipeAnswerIntent.ASSERTION_HISTORY,
222
+ ),
223
+ Recipe(
224
+ name="explain",
225
+ description="Why do we believe a relation — the fact with its evidence"
226
+ " and source handles (S5). Composite grain, the audit deepening hop.",
227
+ parameters={"relation_id": {"type": "uuid", "required": True}},
228
+ chain=(RecipeStep(op="hydrate_relation", bind={"relation_id": "relation_id"}),),
229
+ output_grain=Grain.COMPOSITE,
230
+ answer_intent=RecipeAnswerIntent.AUDIT,
231
+ ),
232
+ Recipe(
233
+ name="identity_as_of",
234
+ description="An entity's identity history — how its mentions resolved"
235
+ " and every merge it took part in (S61). Composite grain, audit.",
236
+ parameters={"entity_id": {"type": "uuid", "required": True}},
237
+ chain=(
238
+ RecipeStep(
239
+ op="transcript",
240
+ settings={"subject_kind": "entity"},
241
+ bind={"subject_id": "entity_id"},
242
+ ),
243
+ ),
244
+ output_grain=Grain.COMPOSITE,
245
+ answer_intent=RecipeAnswerIntent.AUDIT,
246
+ ),
247
+ Recipe(
248
+ name="changed_since",
249
+ description="What changed since an instant — the delta feed (S13/S14)."
250
+ " Composite grain, the change-feed intent.",
251
+ parameters={"since": {"type": "timestamp", "required": True}},
252
+ chain=(RecipeStep(op="delta", bind={"since": "since"}),),
253
+ output_grain=Grain.COMPOSITE,
254
+ answer_intent=RecipeAnswerIntent.CHANGE_FEED,
255
+ ),
256
+ Recipe(
257
+ name="pages_about",
258
+ description="Which compiled K pages exist about an entity (S31/S45) —"
259
+ " the routing index read backwards. Compiled grain, orientation.",
260
+ parameters={"entity_id": {"type": "uuid", "required": True}},
261
+ chain=(RecipeStep(op="pages_about", bind={"entity_id": "entity_id"}),),
262
+ output_grain=Grain.COMPILED,
263
+ answer_intent=RecipeAnswerIntent.ORIENTATION,
264
+ ),
265
+ )
266
+
267
+
268
+ def seed_canonical_recipes(*, registry: RecipeRegistry, deployment_id: UUID) -> int:
269
+ """Register the canonical recipe set into a deployment (idempotent).
270
+
271
+ Each recipe is linted then inserted; re-seeding is a no-op per version.
272
+ Returns how many recipes were seeded (the full canonical count).
273
+ """
274
+ for recipe in CANONICAL_RECIPES:
275
+ registry.register(deployment_id=deployment_id, recipe=recipe)
276
+ return len(CANONICAL_RECIPES)