AbstractMemory 0.3.2__tar.gz → 0.5.0__tar.gz

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 (313) hide show
  1. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/CHANGELOG.md +338 -2
  2. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/PKG-INFO +29 -3
  3. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/README.md +22 -2
  4. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/README.md +1 -0
  5. abstractmemory-0.5.0/docs/adr/0001-altered-memories-ripple.md +152 -0
  6. abstractmemory-0.5.0/docs/adr/0002-abstractmemory-owns-the-memory-graph.md +92 -0
  7. abstractmemory-0.5.0/docs/adr/0003-one-graph-ledger-provenance-and-revisions.md +274 -0
  8. abstractmemory-0.5.0/docs/adr/README.md +10 -0
  9. abstractmemory-0.5.0/docs/api.md +642 -0
  10. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/architecture.md +13 -4
  11. abstractmemory-0.5.0/docs/backlog/completed/knowledge_graph_convergence/0059_record_understanding_rewrites_in_place_with_versions.md +169 -0
  12. abstractmemory-0.5.0/docs/backlog/completed/knowledge_graph_convergence/0060_memory_task_queue.md +154 -0
  13. abstractmemory-0.5.0/docs/backlog/completed/knowledge_graph_convergence/0061_ripple_v1_over_the_task_queue.md +123 -0
  14. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/overview.md +109 -22
  15. abstractmemory-0.5.0/docs/backlog/planned/knowledge_graph_convergence/0050_entity_registry_identity_and_reversible_merges.md +42 -0
  16. abstractmemory-0.5.0/docs/backlog/planned/knowledge_graph_convergence/0051_claim_lifecycle_and_revision_log.md +39 -0
  17. abstractmemory-0.5.0/docs/backlog/planned/knowledge_graph_convergence/0052_document_knowledge_retrieval.md +37 -0
  18. abstractmemory-0.5.0/docs/backlog/planned/knowledge_graph_convergence/0053_self_organisation_communities_consolidation_reflection.md +69 -0
  19. abstractmemory-0.5.0/docs/backlog/planned/knowledge_graph_convergence/0054_ripple_propagation_and_activation.md +47 -0
  20. abstractmemory-0.5.0/docs/backlog/planned/knowledge_graph_convergence/0055_notes_and_diary_layer_for_consumers.md +36 -0
  21. abstractmemory-0.5.0/docs/backlog/planned/knowledge_graph_convergence/0056_ledger_provenance_contract_and_revision_log.md +175 -0
  22. abstractmemory-0.5.0/docs/backlog/planned/knowledge_graph_convergence/0057_one_mind_per_plane_sqlite_home.md +69 -0
  23. abstractmemory-0.5.0/docs/backlog/planned/knowledge_graph_convergence/0058_home_store_performance_indexes_vectors.md +148 -0
  24. abstractmemory-0.5.0/docs/backlog/planned/knowledge_graph_convergence/0059_record_understanding_rewrites_in_place_with_versions.md +1 -0
  25. abstractmemory-0.5.0/docs/backlog/planned/knowledge_graph_convergence/0060_memory_task_queue.md +1 -0
  26. abstractmemory-0.5.0/docs/backlog/planned/knowledge_graph_convergence/0061_ripple_v1_over_the_task_queue.md +1 -0
  27. abstractmemory-0.5.0/docs/backlog/planned/knowledge_graph_convergence/README.md +108 -0
  28. abstractmemory-0.5.0/docs/backlog/proposed/0062_write_barrier_residual_windows.md +72 -0
  29. abstractmemory-0.5.0/docs/backlog/proposed/0064_community_facts_merged_into.md +55 -0
  30. abstractmemory-0.5.0/docs/backlog/proposed/0065_embed_missing_vector_generation_bump_batching.md +57 -0
  31. abstractmemory-0.5.0/docs/backlog/proposed/0066_placement_index_misses_dissolve_only_versions.md +51 -0
  32. abstractmemory-0.5.0/docs/backlog/proposed/0067_communities_read_is_not_one_snapshot.md +50 -0
  33. abstractmemory-0.5.0/docs/backlog/proposed/0068_api_doc_queue_less_list_omits_communities.md +41 -0
  34. abstractmemory-0.5.0/docs/backlog/proposed/ripple_wave/0001_change_records_and_ripple_primitives.md +37 -0
  35. abstractmemory-0.5.0/docs/backlog/proposed/ripple_wave/0063_ripple_v1_consumer_seam.md +60 -0
  36. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/faq.md +3 -2
  37. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/getting-started.md +35 -0
  38. abstractmemory-0.5.0/docs/memory-system.md +148 -0
  39. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/operator.md +1 -1
  40. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/stores.md +44 -6
  41. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/troubleshooting.md +30 -0
  42. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/examples/entity_home_maintenance_proof.py +2 -2
  43. abstractmemory-0.5.0/llms-full.txt +1974 -0
  44. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/llms.txt +4 -1
  45. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/pyproject.toml +11 -1
  46. abstractmemory-0.5.0/release-notes.md +188 -0
  47. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/__init__.py +89 -1
  48. abstractmemory-0.5.0/src/abstractmemory/activation_gate.py +174 -0
  49. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/alive_drives.py +4 -2
  50. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/archive_import.py +5 -22
  51. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/candidate_miner.py +51 -14
  52. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/canonical_text.py +56 -18
  53. abstractmemory-0.5.0/src/abstractmemory/commit_guard.py +84 -0
  54. abstractmemory-0.5.0/src/abstractmemory/communities.py +1783 -0
  55. abstractmemory-0.5.0/src/abstractmemory/community_index.py +884 -0
  56. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/consolidation.py +45 -7
  57. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/diary.py +25 -1
  58. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/doctoring.py +73 -32
  59. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/dream_signals.py +6 -29
  60. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/engram.py +65 -17
  61. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/entity_card.py +68 -15
  62. abstractmemory-0.5.0/src/abstractmemory/formation_authoring.py +199 -0
  63. abstractmemory-0.5.0/src/abstractmemory/graph/__init__.py +60 -0
  64. abstractmemory-0.5.0/src/abstractmemory/graph/backend.py +117 -0
  65. abstractmemory-0.5.0/src/abstractmemory/graph/graph.py +1372 -0
  66. abstractmemory-0.5.0/src/abstractmemory/graph/lancedb_backend.py +584 -0
  67. abstractmemory-0.5.0/src/abstractmemory/graph/provenance.py +323 -0
  68. abstractmemory-0.5.0/src/abstractmemory/graph/revisions.py +239 -0
  69. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/identity_review.py +3 -1
  70. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/in_memory_store.py +164 -30
  71. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/journal.py +96 -6
  72. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/journal_memory.py +117 -7
  73. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/journal_sqlite.py +196 -68
  74. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/journal_sqlite_rows.py +56 -2
  75. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/lancedb_store.py +22 -3
  76. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/maintenance.py +87 -15
  77. abstractmemory-0.5.0/src/abstractmemory/memory_tasks.py +1494 -0
  78. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/probe.py +4 -4
  79. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/recall_reads.py +3 -1
  80. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/recent_records.py +2 -2
  81. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/records.py +129 -9
  82. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/redigestion.py +21 -1
  83. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/reembed.py +3 -2
  84. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/replay.py +160 -20
  85. abstractmemory-0.5.0/src/abstractmemory/ripple.py +561 -0
  86. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/seam.py +1 -1
  87. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/shelf.py +13 -9
  88. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/situate.py +2 -2
  89. abstractmemory-0.5.0/src/abstractmemory/sleep_cadence.py +687 -0
  90. abstractmemory-0.5.0/src/abstractmemory/sqlite_store.py +1206 -0
  91. abstractmemory-0.5.0/src/abstractmemory/store_tuning.py +71 -0
  92. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/system.py +49 -3
  93. abstractmemory-0.5.0/src/abstractmemory/system_understanding.py +197 -0
  94. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/tend.py +3 -1
  95. abstractmemory-0.5.0/src/abstractmemory/understanding.py +1728 -0
  96. abstractmemory-0.5.0/src/abstractmemory/vector_matrix.py +434 -0
  97. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/world_model.py +223 -34
  98. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/world_model_alias.py +99 -4
  99. abstractmemory-0.5.0/src/abstractmemory/write_barrier.py +246 -0
  100. abstractmemory-0.5.0/tests/bench/bench_graph.py +210 -0
  101. abstractmemory-0.5.0/tests/bench/bench_store.py +329 -0
  102. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/conftest.py +3 -1
  103. abstractmemory-0.5.0/tests/graph_support.py +203 -0
  104. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_archive_import.py +5 -4
  105. abstractmemory-0.5.0/tests/test_atomic_formation.py +264 -0
  106. abstractmemory-0.5.0/tests/test_cadence_cursor.py +296 -0
  107. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_candidate_miner.py +4 -2
  108. abstractmemory-0.5.0/tests/test_commit_guard.py +862 -0
  109. abstractmemory-0.5.0/tests/test_communities.py +856 -0
  110. abstractmemory-0.5.0/tests/test_communities_embed_missing.py +187 -0
  111. abstractmemory-0.5.0/tests/test_communities_never_recalled.py +283 -0
  112. abstractmemory-0.5.0/tests/test_communities_rounds.py +157 -0
  113. abstractmemory-0.5.0/tests/test_communities_scale.py +273 -0
  114. abstractmemory-0.5.0/tests/test_community_placement.py +914 -0
  115. abstractmemory-0.5.0/tests/test_declare_pending.py +468 -0
  116. abstractmemory-0.5.0/tests/test_diary_summary_authored.py +444 -0
  117. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_disposal.py +1 -1
  118. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_doctoring.py +42 -1
  119. abstractmemory-0.5.0/tests/test_dream_pass_signals.py +55 -0
  120. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_dream_resolution.py +1 -1
  121. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_dream_signals.py +6 -19
  122. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_engram.py +208 -27
  123. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_entity_card.py +63 -0
  124. abstractmemory-0.5.0/tests/test_formation_authoring.py +349 -0
  125. abstractmemory-0.5.0/tests/test_formation_concurrency.py +296 -0
  126. abstractmemory-0.5.0/tests/test_graph_conformance.py +354 -0
  127. abstractmemory-0.5.0/tests/test_graph_e2e.py +197 -0
  128. abstractmemory-0.5.0/tests/test_graph_performance.py +193 -0
  129. abstractmemory-0.5.0/tests/test_graph_provenance.py +502 -0
  130. abstractmemory-0.5.0/tests/test_graph_revisions.py +620 -0
  131. abstractmemory-0.5.0/tests/test_home_open_is_a_read.py +91 -0
  132. abstractmemory-0.5.0/tests/test_identical_authoring_settles.py +166 -0
  133. abstractmemory-0.5.0/tests/test_memory_task_queue.py +466 -0
  134. abstractmemory-0.5.0/tests/test_narrow_assertion.py +142 -0
  135. abstractmemory-0.5.0/tests/test_pending_formations.py +507 -0
  136. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_phase_artifact_pin.py +5 -1
  137. abstractmemory-0.5.0/tests/test_reading_provenance.py +212 -0
  138. abstractmemory-0.5.0/tests/test_rearm_pending.py +380 -0
  139. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_reconstruct.py +3 -3
  140. abstractmemory-0.5.0/tests/test_records_since_maintenance.py +347 -0
  141. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_replay.py +9 -1
  142. abstractmemory-0.5.0/tests/test_retitle.py +431 -0
  143. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_review_wave.py +1 -1
  144. abstractmemory-0.5.0/tests/test_rewrite_digest_in_place.py +445 -0
  145. abstractmemory-0.5.0/tests/test_ripple_v1.py +331 -0
  146. abstractmemory-0.5.0/tests/test_store_performance.py +179 -0
  147. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_store_vectors.py +1 -1
  148. abstractmemory-0.5.0/tests/test_stored_text_whole.py +119 -0
  149. abstractmemory-0.5.0/tests/test_titles_whole.py +126 -0
  150. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_two_sided_visit_contract.py +1 -1
  151. abstractmemory-0.5.0/tests/test_untitled_records.py +423 -0
  152. abstractmemory-0.5.0/tests/test_vector_encoding_marker.py +51 -0
  153. abstractmemory-0.5.0/tests/test_vector_matrix.py +569 -0
  154. abstractmemory-0.5.0/tests/test_vector_matrix_footprint.py +88 -0
  155. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_world_model.py +40 -5
  156. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_world_model_alias.py +1 -1
  157. abstractmemory-0.5.0/tests/test_world_model_rekey.py +368 -0
  158. abstractmemory-0.5.0/tests/test_write_barrier.py +690 -0
  159. abstractmemory-0.3.2/docs/api.md +0 -385
  160. abstractmemory-0.3.2/docs/memory-system.md +0 -96
  161. abstractmemory-0.3.2/llms-full.txt +0 -1532
  162. abstractmemory-0.3.2/release-notes.md +0 -13
  163. abstractmemory-0.3.2/src/abstractmemory/sleep_cadence.py +0 -74
  164. abstractmemory-0.3.2/src/abstractmemory/sqlite_store.py +0 -695
  165. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  166. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/.github/workflows/ci.yml +0 -0
  167. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/.github/workflows/release.yml +0 -0
  168. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/.gitignore +0 -0
  169. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/ACKNOWLEDGMENTS.md +0 -0
  170. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/CODE_OF_CONDUCT.md +0 -0
  171. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/CONTRIBUTING.md +0 -0
  172. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/LICENSE +0 -0
  173. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/SECURITY.md +0 -0
  174. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/0008_gateway_memory_install_and_config_boundary.md +0 -0
  175. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/002_sqlite_database_compatibility_and_store_capabilities.md +0 -0
  176. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/004_recall_trace_and_access_events_contract.md +0 -0
  177. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/005_source_linked_summaries_and_derived_assertion_lineage.md +0 -0
  178. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/007_read_only_memory_observer_contract.md +0 -0
  179. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/extension_wave/0037_familiarity_metamemory_read.md +0 -0
  180. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/extension_wave/0038_open_commitments_and_triggers.md +0 -0
  181. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/extension_wave/0039_tend_election_grammar.md +0 -0
  182. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/extension_wave/0049_stable_shelf_order_for_prefix_reuse.md +0 -0
  183. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/memory_system_v1/0009_assertion_identity_and_batch_read_contract.md +0 -0
  184. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/memory_system_v1/0010_append_only_closure_records_for_retract_and_supersede.md +0 -0
  185. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/memory_system_v1/0011_cross_backend_parity_conformance_suite.md +0 -0
  186. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/memory_system_v1/0013_store_concurrency_and_thread_safety_contract.md +0 -0
  187. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/memory_system_v1/0014_embedding_space_integrity_manifest.md +0 -0
  188. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/memory_system_v1/0017_memory_journal_and_scope_bindings_layer.md +0 -0
  189. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/memory_system_v1/0018_neurotransmitter_attention_strengthen_weaken_decay.md +0 -0
  190. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/memory_system_v1/0019_hybrid_retrieval_channels_fts_vector_exact.md +0 -0
  191. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/memory_system_v1/0020_reconstruction_shelf_and_selection_traces.md +0 -0
  192. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/memory_system_v1/0021_memory_records_and_remember_api.md +0 -0
  193. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/memory_system_v1/0022_probe_and_bounded_source_expansion.md +0 -0
  194. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/memory_system_v1/0023_maintenance_sleep_consolidate_dream.md +0 -0
  195. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/memory_system_v1/0024_memory_system_facade_and_consumer_migration.md +0 -0
  196. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/memory_system_v1/0025_graph_backend_decision_record_memgraph_rejected.md +0 -0
  197. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/memory_system_v1/0026_spreading_activation_and_working_set.md +0 -0
  198. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/memory_system_v1/0027_runtime_seam_contract_v1.md +0 -0
  199. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/memory_system_v1/0029_sleep_reactivity_dreams_as_reaction.md +0 -0
  200. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/memory_system_v1/0030_fork_comparison_adoption_wave.md +0 -0
  201. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/memory_system_v1/0031_second_fork_pass_and_lifecycle_closure.md +0 -0
  202. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/memory_system_v1/0036_third_pass_extension_wave.md +0 -0
  203. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/subconscious_wave/0032_dream_subconscious_lifecycle.md +0 -0
  204. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/subconscious_wave/0033_world_model_orientation_cards.md +0 -0
  205. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/subconscious_wave/0034_situate_temporal_relational_reconstruction.md +0 -0
  206. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/completed/subconscious_wave/0035_lessons_layer_conventions.md +0 -0
  207. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/deprecated/001_semantics_aligned_memory_record_conventions.md +0 -0
  208. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/deprecated/003_bounded_graph_traversal_over_triples.md +0 -0
  209. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/deprecated/006_deterministic_anchor_and_facet_index.md +0 -0
  210. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/planned/extension_wave/README.md +0 -0
  211. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/planned/subconscious_wave/README.md +0 -0
  212. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/proposed/extension_wave/0040_recurrence_probe_and_presentation_fold.md +0 -0
  213. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/proposed/extension_wave/0041_loss_absence_anchors.md +0 -0
  214. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/proposed/extension_wave/0042_explain_recall_serving_contract.md +0 -0
  215. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/proposed/extension_wave/0043_mind_health_report.md +0 -0
  216. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/proposed/extension_wave/0044_origin_time_axis_for_imports.md +0 -0
  217. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/proposed/extension_wave/0045_n_party_memory_contract.md +0 -0
  218. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/proposed/extension_wave/0046_transcript_adoption_verb.md +0 -0
  219. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/proposed/extension_wave/0047_cue_hygiene_at_recall_boundary.md +0 -0
  220. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/proposed/extension_wave/0048_writer_forensics_for_homes.md +0 -0
  221. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/proposed/extension_wave/README.md +0 -0
  222. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/proposed/memory_system_v1/0012_lancedb_backend_hardening_and_explicit_schema.md +0 -0
  223. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/proposed/memory_system_v1/0015_capabilities_extensions_and_deterministic_export_import.md +0 -0
  224. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/proposed/memory_system_v1/0016_semantics_vocabulary_validation_and_aliasing_module.md +0 -0
  225. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/proposed/memory_system_v1/0028_lateral_inhibition_theory.md +0 -0
  226. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/backlog/proposed/memory_system_v1/README.md +0 -0
  227. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/docs/development.md +0 -0
  228. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/examples/realistic_session.py +0 -0
  229. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/attention.py +0 -0
  230. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/channels.py +0 -0
  231. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/cognition_health.py +0 -0
  232. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/concept_anchor.py +0 -0
  233. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/disposal.py +0 -0
  234. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/dream_resolution.py +0 -0
  235. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/drive_grouping.py +0 -0
  236. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/drive_pressure.py +0 -0
  237. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/embedding_pin.py +0 -0
  238. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/embeddings.py +0 -0
  239. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/embeddings_openai_compat.py +0 -0
  240. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/engine_manifest.py +0 -0
  241. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/feelings_reads.py +0 -0
  242. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/folds.py +0 -0
  243. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/gradation.py +0 -0
  244. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/journal_common.py +0 -0
  245. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/mind_mass.py +0 -0
  246. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/models.py +0 -0
  247. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/origin_diversity.py +0 -0
  248. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/reconstruct.py +0 -0
  249. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/render_order.py +0 -0
  250. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/selection.py +0 -0
  251. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/self_component.py +0 -0
  252. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/sleep_policy.py +0 -0
  253. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/spark.py +0 -0
  254. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/spreading.py +0 -0
  255. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/store.py +0 -0
  256. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/system_access.py +0 -0
  257. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/system_valence.py +0 -0
  258. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/text_tokens.py +0 -0
  259. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/src/abstractmemory/vector_scoring.py +0 -0
  260. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/golden/pre_identity_wave_result.json +0 -0
  261. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/realistic_fixtures.py +0 -0
  262. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_access_counts.py +0 -0
  263. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_alive_drives.py +0 -0
  264. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_anchored_summon.py +0 -0
  265. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_attention.py +0 -0
  266. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_audit_wave.py +0 -0
  267. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_binding_visibility.py +0 -0
  268. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_clean_owner_keys.py +0 -0
  269. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_close_assertion.py +0 -0
  270. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_co_use_trails.py +0 -0
  271. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_cognition_health.py +0 -0
  272. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_commitments.py +0 -0
  273. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_consolidation.py +0 -0
  274. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_drive_grouping.py +0 -0
  275. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_drive_pressure.py +0 -0
  276. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_embedding_pin.py +0 -0
  277. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_engine_manifest.py +0 -0
  278. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_explain_recall.py +0 -0
  279. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_familiarity.py +0 -0
  280. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_feelings_reads.py +0 -0
  281. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_gradation.py +0 -0
  282. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_home_lease_contract.py +0 -0
  283. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_identity_review.py +0 -0
  284. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_identity_self.py +0 -0
  285. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_in_memory_query_text_fallback.py +0 -0
  286. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_journal_backends.py +0 -0
  287. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_keyword_fts.py +0 -0
  288. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_lancedb_triple_store.py +0 -0
  289. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_lessons_layer.py +0 -0
  290. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_maintenance.py +0 -0
  291. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_mind_mass.py +0 -0
  292. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_origin_diversity.py +0 -0
  293. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_participants_channel.py +0 -0
  294. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_probe.py +0 -0
  295. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_realistic_lmstudio.py +0 -0
  296. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_recall_reads.py +0 -0
  297. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_recent_records.py +0 -0
  298. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_records.py +0 -0
  299. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_redigestion.py +0 -0
  300. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_render_order.py +0 -0
  301. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_replay_idempotency.py +0 -0
  302. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_seam_addendum.py +0 -0
  303. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_seam_contracts.py +0 -0
  304. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_situate.py +0 -0
  305. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_spark.py +0 -0
  306. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_spreading.py +0 -0
  307. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_sqlite_triple_store.py +0 -0
  308. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_stm_union.py +0 -0
  309. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_system.py +0 -0
  310. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_tend.py +0 -0
  311. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_term_canonicalization.py +0 -0
  312. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_triple_store_limits.py +0 -0
  313. {abstractmemory-0.3.2 → abstractmemory-0.5.0}/tests/test_valence_gradation.py +0 -0
@@ -5,9 +5,345 @@ All notable changes to this package will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) (pre-1.0).
7
7
 
8
- ## Unreleased
8
+ ## [0.5.0] - 2026-11-10
9
+
10
+ Every memory now carries an authored title and summary, a home keeps a persistent queue of what still needs
11
+ understanding, a record's understanding is rewritten in place with every earlier reading kept, the home's topics are
12
+ formed during sleep, and a host can fence every memory write behind its Stop (backlogs 0059, 0060, 0061;
13
+ [ADR 0001](docs/adr/0001-altered-memories-ripple.md),
14
+ [ADR 0003](docs/adr/0003-one-graph-ledger-provenance-and-revisions.md) decision 6a).
15
+
16
+ ### Upgrading
17
+
18
+ - **Open homes that form records with `MemorySystem(..., task_queue=True)`.** A missing title or summary is always
19
+ stored beside the task that writes it, so these refuse a home without a task queue, before writing anything:
20
+ `world_model_pass`, `dream_pass`, `mine_candidates_pass`, `consolidation_pass`, `wake_cue_dedup_pass`,
21
+ `sleep_pass`, `communities_pass`, `embed_missing`, the ripple verbs, a `remember_many` record with `pending=...`,
22
+ and an `engram` whose unnamed spark items get no authored title (`report_only` reads still run). `declare_pending`
23
+ and `rearm_pending` answer `no_task_queue`. The queue adds its tables (`memq_*`) to the home's file on first open.
24
+ - **Pass an `author` callable.** Memory calls no model: `world_model_pass` / `world_model_update`, `dream_pass`,
25
+ `mine_candidates_pass`, `consolidation_pass`, `wake_cue_dedup_pass`, `sleep_pass`, `communities_pass` and `engram`
26
+ take `author(kind, body, context) -> {title, summary, author, reader, sources}`. Without it, or when it fails, the
27
+ records still form, pending, and every result's `authoring = {authored, failures}` names the failures
28
+ (`no_author_supplied`, `author_raised`, `invalid_result`).
29
+ - **Treat a title as optional while it is pending.** `MemoryRecordInput.title` may be `None` with
30
+ `pending=("title",)`, and every read serves a pending title as `None` (`MemoryHandle.title` is `Optional[str]`,
31
+ display blocks and `record_understanding` carry `pending`), never a placeholder or words from the body. A host's
32
+ drainer completes `title.author` / `digest.author` tasks with `retitle` / `rewrite_digest`; records stored before
33
+ 0.5.0 without an authored title or summary are brought into the same state with `declare_pending`.
34
+ `MemoryRecordInput` raises `ValueError` for an empty title without `pending=("title",)`, and for a title given
35
+ with it.
36
+ - **Memory's passes no longer store their own titles or summaries.** Cards, dreams, offers, consolidation candidates
37
+ and the dedup day summary form authored or pending; their bookkeeping text ("World model: ...", "Dream: ...") is
38
+ only the provisional body their tasks author from. `world_model_pass` no longer queues `card.author` for new cards
39
+ (`digest.author` owns the body; `card.author` remains for legacy cards).
40
+ - **Hosts that fence writes** pass `commit_guard=` and wrap the moment they flip it in `system.write_barrier()`.
41
+ Two residual windows remain: a LanceDB store takes no write lock (a LanceDB write whose guard passed before the
42
+ flip may land after it, at most one per concurrent writer; `BarrierHold.uncovered` names it with a `#FALLBACK`
43
+ warning), and the two SQLite autocommit commit points (`SQLiteTripleStore._write_pin` without a cursor, the
44
+ off-file graph's `mark_journal_applied`) are covered only by a barrier taken on the same handle.
45
+ - **Community records are never embedded and never recalled**: a store's embedding paths, recall shelves, keyword
46
+ indexes and memory scans skip kind `community` (`canonical_text.NON_EMBEDDED_KINDS`).
47
+ - `CANONICAL_TEXT_VERSION` is 3 (stored text is never cut). Record digests render as before; a plain assertion
48
+ with an `original_context` longer than 400 characters keeps its earlier text and vector until `reembed_store`
49
+ re-derives it.
50
+ - `version_count` is 1 for a record that was never rewritten (was 0); `digest_version` stays 0.
51
+ - `apply_redigestion` is deprecated (it forms a new record with zero usage); use `rewrite_digest`.
52
+
53
+ ### Added: titles and summaries are always authored
54
+
55
+ - `MemoryRecordInput(pending=(), pending_failure=None)`: `pending` is a subset of `PENDING_FIELDS`
56
+ (`{"title", "summary"}`). A pending record carries `attributes.pending = {title, summary, since, attempts}` (plus
57
+ `failure` when authoring failed) and `remember_many` queues its authoring task (`PENDING_TASK_KINDS`:
58
+ `title.author` / `digest.author`, capability `summaries`, `FORMATION_PRIORITY`). A pending summary is refused on
59
+ the entity's own words (`UNDERSTANDING_PROTECTED_KINDS`), except a public diary projection's summary.
60
+ - The host's `author` callable on every pass (`formation_authoring`): authored fields are stored with their
61
+ provenance (`title_provenance`, `understanding`, version 0, cause `formation`) and owe no task; a standing record is
62
+ never authored again.
63
+ - `engram(..., author=None)`: a spark item without a `name` has its title authored before it forms (it was
64
+ `<section>-<ordinal>`, such as `trait-0`), else it forms pending; a `name` stays the title. `EngramResult.authoring`.
65
+ - `retitle(record_id, *, title, author, cause, expected_version, ...)`: changes only a record's title, in place, for
66
+ every kind; the body and the reading stay byte-identical, the previous title is kept as a version, `title_version`
67
+ is the compare-and-set. Refusals: `empty_title`, `hash_chained` (an owner-direct diary entry whose `entry_hash`
68
+ attests its title), `closed`, `stale`, `embedder_unavailable`. A digest or card reading that changes the title
69
+ writes the title version too.
70
+ - `declare_pending(record_id, *, fields=("title", "summary"), cause="repair", reason=None)`: a stored record whose
71
+ title or summary was never authored gets exactly the state of a record formed pending (marker and tasks in one
72
+ transaction; a declared title is stored `None`, its old title kept as a version). Idempotent (`already_pending`).
73
+ - `rearm_pending(record_id, ...)` re-queues the authoring task of a pending field whose tasks all ran out, and
74
+ `pending_records(*, scopes=None, live_task=False)` lists the records still pending, with their live and unowned
75
+ fields.
76
+ - A public diary entry's summary is authored like any record's (at formation, or declared pending for an existing
77
+ entry); its body, the book's entry and every hash chain are untouched. Owner-direct, hash-chained and private
78
+ entries stay protected (`diary.diary_summary_refusal`).
79
+ - `rekey_world_model(old_key, new_key, *, scope, owner_id, author, cause, ...)`: moves a standing card to a new key
80
+ in place and keeps the old key as an alias, so a retitled interest's next `world_model_pass` forms no second card.
81
+ An untitled interest's card is keyed `topic:<graph id>` and `retitle` re-keys it when the title lands
82
+ (`card_rekey` in the result).
83
+ - `REWRITE_CAUSES` gains `repair` (a correction of what a process wrote wrong).
84
+
85
+ ### Added: understanding rewritten in place (0059)
86
+
87
+ - `rewrite_digest`: replaces a record's digest, title and keywords in place. The record keeps its graph id, digest
88
+ assertion id, edges, usage counts and journal; its keyword entry and vector are replaced in the same transaction.
89
+ `expected_version` is a compare-and-set; each reading records `author` (`AUTHOR_KINDS`), `reader`
90
+ (`{provider, model, thinking}`), `sources` (mandatory for a model author) and `cause`. Refusals are named results
91
+ that write nothing. Results carry `cosine_distance` between the old and new vectors.
92
+ - `narrate_dream` (a narration beside a dream's summary), `revert_digest`, `versions`, `current_of`,
93
+ `record_understanding`, `understanding_fields`; `author_world_model` rewrites a card in place by default (accepts
94
+ `reader`, `sources`, `expected_fingerprint`; `in_place=False` keeps the revision path).
95
+ - The journal's version family `UnderstandingVersion`, and the opt-in replay family `revision`
96
+ (`OPT_IN_FAMILIES`; the default six families are unchanged). Display blocks carry the reading's provenance
97
+ (`digest_method`, `digest_version`, `version_count`, `authored_by`, `reader`, `understood_at`, `cause`).
98
+ - Every record says who wrote its words, when and why, even when its writer stamped nothing: a row without a stamp
99
+ reads as its formation reading, derived from its origin (`understanding.reading_provenance`); `remember_many`
100
+ records that reading at formation.
101
+
102
+ ### Added: the memory task queue (0060) and ripple v1 (0061)
103
+
104
+ - `MemorySystem(task_queue=True)` keeps its queue in the home's file (`memq_tasks`, `memq_log`, `memq_windows`,
105
+ `memq_ripples`, `memq_ripple_gates`, `memq_maintenance`; a private in-memory database for the in-memory store). `system.tasks` (`MemoryTaskQueue`): `enqueue`, `select_for_window(budget_seconds, sensitivity)` (activation
106
+ through ADR 0001's logistic gate, strongest first, bounded by the window's time; every live task selected or left
107
+ out with a reason), `claim` / `ack` / `release` (leases, attempts, defer without spending an attempt), `left_out`.
108
+ `understanding_debt`, `enqueue_debt` (the backfill, dry-run by default) and `task_packet` on `MemorySystem`. The
109
+ understanding verbs accept `task_id=` and settle the task in their own transaction.
110
+ - A formed record and the tasks it owes commit together (`memory_tasks.form_with_tasks`): one transaction on the
111
+ SQLite home; on the in-memory pair a failure rolls back exactly that attempt's rows, bindings and tasks.
112
+ - `maintenance_due(..., tasks=)` reports pending tasks and is due when ripple or night-only work is pending.
113
+ - Ripple v1: `seed_ripple`, `settle_reconsideration`, `form_consolidation` (night only), `refresh_ripples`,
114
+ `revert_ripple`, and the reads `ripples` / `ripple`. Candidates by relation, by the cards built on a memory and by
115
+ vector similarity; impact decays per hop through the logistic gate (floor 0.1), at most 2 hops and 20
116
+ reconsiderations per ripple and per window; protected kinds are never reconsidered; every gate decision is stored
117
+ with its potential.
118
+
119
+ ### Added: communities (topics)
120
+
121
+ - A community is a formed record of kind `community` (`abstractmemory.communities.COMMUNITY_KIND`), one record per
122
+ version, with a stable `attributes.community_key` across versions. `communities_pass(system, *, scopes, owner_id,
123
+ author, cancelled, ...)`, which a host runs during its sleep, detects them (deterministic warm-started Louvain over
124
+ the vectored records, at most 5 rounds), attaches vector-less records through their engraved relations, lays them
125
+ out, authors the changed ones and writes the version in one guarded transaction. `embed_missing(...)` embeds the
126
+ formed records that have no vector with the store's own embedder.
127
+ - Placement at formation: on a `task_queue=True` home, `remember_many` places every record it forms in its
128
+ provisional community inside the formation's transaction (nearest centroid, else the majority community of its
129
+ formation edges) and writes one `placed` journal event (an audit kind, never scored).
130
+ - Reads (`abstractmemory.community_index`): `communities(system, *, scopes, owner_id, version=None)` (the payload
131
+ version 2 a host serves, with each community's `facts`: span, activity, hub, bridges, paths,
132
+ `changed_since_last_sleep`) and `community_of(system, record_id)`. A community record replays like any formed
133
+ record; its binding envelope draws only `refines`.
134
+ - Topic titles come first: a community's `title.author` / `digest.author` tasks are queued at `COMMUNITY_PRIORITY`
135
+ (3, ahead of every other pending record's `FORMATION_PRIORITY` 5), so a drainer with a small budget names the
136
+ topics before a long repair tail. `communities_pass`'s `budget` goes to its topics, largest first, one call per
137
+ topic for both its title and its summary (`None` authors every topic); the receipt carries `budget` and
138
+ `budget_spent`. A topic's briefing keeps its member lines within 1500 tokens, the first line too.
139
+
140
+ ### Added: sleep cadence
141
+
142
+ - `records_since_maintenance(system, *, scopes=None, after=None) -> {count, last_maintenance_at, since,
143
+ boundary_source, fragmented}`: the host's idle → sleep threshold. `sleep_pass` records when a whole night ran to
144
+ its end (a cancelled, `report_only` or anchored night records nothing; a cycle window is recorded as kind `cycle`
145
+ and does not reset the count); `after` is the host's own last maintenance, and the later of the two is the
146
+ boundary. `fragmented = {count, share, provisional, unvectored, pending}` says how much of the live home a sleep
147
+ would make whole. `MemoryTaskQueue.record_maintenance` / `last_maintenance`.
148
+ - `sleep_pass(..., cancelled=None)`: the host's Stop check, read at every sub-phase boundary and immediately before
149
+ the completion marker; a stopped night records no completion and carries `cancelled_after`.
150
+
151
+ ### Added: the Stop fence hooks
152
+
153
+ - `MemorySystem(..., commit_guard=None)`: the host's `guard(where)` is installed on the store and journal and called
154
+ inside every write transaction immediately before its COMMIT, once per outermost transaction, whoever writes (the
155
+ facade, `MemoryGraph`, the task queue, the sleep passes). Raising rolls the write back; nothing of it lands and the
156
+ exception reaches the caller unchanged. A store or journal type whose writes do not call a guard is refused
157
+ (`TypeError`), and so is a second, different guard (`ValueError`).
158
+ - `MemorySystem.write_barrier(*, timeout=None)` / `write_barrier(system, *, timeout=None)`: a context manager the
159
+ host wraps around its flip of the guard. It holds this home's in-process locks in the writers' own order and one
160
+ `BEGIN IMMEDIATE` per distinct SQLite file, so every transaction whose guard passed commits before the block and
161
+ every later one calls its guard after it. It writes nothing; `WriteBarrierTimeout` names the lock or file still
162
+ held.
9
163
 
10
- *No unreleased changes.*
164
+ ### Changed
165
+
166
+ - Stored text is never cut: a world-model card quotes its evidence whole, a dream signal's `fragment` is kept whole
167
+ (`dream_signals.FRAGMENT_CAP` is gone), an assertion's `original_context` renders whole in the canonical text, a
168
+ plain assertion's "s p o" display title and an imported file's prose are kept whole. Readers shorten text at
169
+ display time (`canonical_text.short_title`).
170
+ - Titles are explicit and whole: a card formed from an interest keeps the interest's whole subject head as its
171
+ target; lesson-candidate, interest-candidate and group-offer titles are no longer bounded.
172
+ - `world_model_pass`: an interest whose title heads to an alias of a card counts as an election of the card's
173
+ primary key.
174
+ - `dream_pass` returns `signals` and `signals_omitted`.
175
+ - `journal_cold_cut` copies the version family and the task queue.
176
+ - The identity card's `lessons` section also counts the lessons written in the diary (`diary_type='lesson'`), once
177
+ each when a lesson record derives from the entry.
178
+ - The identity card's record briefs carry the reading fields (`authored_by`, `understood_at`, `cause`,
179
+ `digest_version`, `version_count`); diary-redacted replay blocks carry `authored_by`, `understood_at` and `cause`,
180
+ never the entry's words.
181
+
182
+ ### Fixed
183
+
184
+ - `records_since_maintenance(...)["fragmented"]["count"]` counts each live record once: a record both vector-less
185
+ and pending, or placed and pending, is one fragmented record, and a placement whose record has been closed since
186
+ counts in `provisional` only, so `share` never exceeds 1.0. The per-kind counts are unchanged.
187
+ - Identical authored words settle a pending field: an in-place write whose words equal the provisional ones clears
188
+ the marker, completes the task and records the reading (it answered `unchanged` and left the task leased).
189
+ - On the in-memory pair, formation and rewriting share one lock (they could deadlock), and a failed formation
190
+ removes only its own rows and bindings, never a concurrent writer's.
191
+ - `form_with_tasks` calls the commit guard immediately before its COMMITs, after the rows, bindings and tasks.
192
+ - A completed task no longer carries the error of an earlier failed attempt (the failure stays in the task log).
193
+ - The wake-cue dedup pass no longer tokenizes a missing title as "None".
194
+
195
+ ### Deprecated
196
+
197
+ - `apply_redigestion` (emits `DeprecationWarning`): use `rewrite_digest`.
198
+
199
+ ## [0.4.0] - 2026-10-27
200
+
201
+ The memory graph ([ADR 0003](docs/adr/0003-one-graph-ledger-provenance-and-revisions.md), backlogs 0056-0058):
202
+ `abstractmemory.graph.MemoryGraph` is the only manipulation surface of a mind; every change is a revision, every
203
+ memory points back to the ledger, and every database is a connector behind the graph (SQLite the default). The home
204
+ store holds a notebook-sized corpus. The API is additive: every 0.3.x call keeps working (`close_assertion` stays;
205
+ `ClosureRecord` gains only the `merged` kind). Operator decisions adopted (2026-10-27): visibility is strict
206
+ ownership (lineage never crosses owners; ADR 0003 decision 2); stores are connectors behind `MemoryGraph`, SQLite the
207
+ default (decision 3); the vector re-encoding below is a documented one-way migration with a `vector_encoding` marker.
208
+
209
+ ### Upgrade notes: ONE-WAY migration
210
+
211
+ - Opening a SQLite home with 0.4.0 rewrites its JSON-text vectors as float32 BLOBs. A 0.3.x reader decodes JSON
212
+ vectors only: on a home a 0.4.0 process has written it silently finds no vectors (zero semantic hits, no error).
213
+ Every process sharing a home or a plane must move to 0.4.0 together; an entity home copied to a 0.3.x install
214
+ loses semantic recall. A 0.4.0 home declares it: `<table>_meta` key `vector_encoding` = `float32-blob`
215
+ (`abstractmemory.vector_matrix.VECTOR_ENCODING_KEY`), written by the first write or by the upgrade, never by a
216
+ plain open.
217
+ - Graph homes add four tables (`memg_revisions`, `memg_provenance`, `memg_derivations`, `memg_history`) on first
218
+ use; nothing else in an existing file changes shape.
219
+
220
+ ### Added
221
+
222
+ - **Connectors** (ADR 0003 decision 3, operator decision 2026-10-27): `MemoryGraph` is the only manipulation
223
+ surface of a mind and every store is a connector behind it: `abstractmemory.graph.backend` (`GraphBackend`,
224
+ `GraphTx` Protocols with their invariants; `register_backend`, `backend_for`, `registered_backends`). SQLite (the
225
+ default for planes and entity homes) and in-memory are declared implementations; a new LanceDB connector
226
+ (`abstractmemory.graph.lancedb_backend`, over `LanceDBTripleStore`: explicit Arrow schemas, a staged transaction,
227
+ a log-first commit, `repair()` re-derives a half-projected revision from the log). One conformance suite,
228
+ `tests/test_graph_conformance.py`, runs every connector; the LanceDB connector cannot promise serialized writers
229
+ across processes nor invisibility of a half-projected revision before `repair()` (strict xfails).
230
+ - **`abstractmemory.graph`**, the one write path of a mind:
231
+ - `SourceRef` (`run`, `step` with the ledger row address `(run_id, seq)`, `seq` 1-based, `artifact`, `message`, `event`,
232
+ `diary_entry`; optional `runtime_id`; one canonical `key()`), validated per kind (`InvalidSourceRef`); a
233
+ `run` / `step` ref naming a synthetic run id (`SYNTHETIC_RUN_ID_PREFIXES`: `chat-`, `diary:`,
234
+ `session_memory_`, `global_memory`) is refused.
235
+ - `Provenance(sources, derived_from, actor, reader, reason, extra)`, strict about its shape;
236
+ `Provenance.from_legacy(...)` lifts the old flat keys (`run_id`, `span_id`, `payload_ref`, `entry_id`, ...)
237
+ in one place, never fabricates a reference (a synthetic run id stays in `extra`), and reads the mixed shape
238
+ the runtime stamps (flat keys plus `sources`: flat keys into `extra`).
239
+ - `Revision` (`revision_id`, `scope`, `owner_id`, `cause`, `occurred_at`, `recorded_at`, `ops`, `provenance`,
240
+ `summary`) with the ops `assert`, `close` (`retract` / `supersede` / `reinterpreted` / `merged`, replacement
241
+ ids, ripple source and hops) and `narrow`. Every time a revision carries is parsed and normalized to one
242
+ UTC text form; a non-timestamp is refused. A close ends the row at the earlier of its current end and the
243
+ close (so `TripleQuery(active_at=)` and ranked recall agree after every close); a close or narrow before the
244
+ claim's `valid_from` is refused.
245
+ - `MemoryGraph(store, journal).apply_revision(rev)`: refuses a memory that is neither sourced nor derived from a
246
+ grounded memory (`ProvenanceRequired`; chains that never reach a source and cycles included); applies all ops
247
+ in ONE SQLite transaction (triples and their keyword rows, window changes, the journal closure when the
248
+ journal shares the file, the revision, provenance, derivation and history rows), or not at all; idempotent on
249
+ the revision id; deterministic ids so the logged revision replays identically. A store row written outside
250
+ the graph is adopted only by an `import` / `migration` revision that carries it as stored (logged with its
251
+ previous provenance, so a replay reproduces it); a different claim under an id the graph holds is refused;
252
+ a close/narrow-only revision must name a cause other than the memories it changes; a `derived_from` across
253
+ owners is refused (other owners' knowledge enters as a source). Re-observation, not duplication: an open
254
+ assert of a claim the graph holds open records its sources on the held memory (`re_observed`, history
255
+ `re-observed`) instead of a second row. Record time is the store's: a fresh apply stamps `recorded_at` with
256
+ its clock (`apply_revision(rev, replay=True)`, used by `replay_into`, keeps the logged value). A revision
257
+ already in the log returns its logged outcome. Every memory is also indexed by the sources of the revision
258
+ that wrote it (`via`). `SourceRef.digest`: an optional sha256 of the verbatim, beside the address.
259
+ - Reads, all bounded index reads: `history(memory_id)` (asserted / closed / narrowed, by which revision, with
260
+ its cause), `sources_of(memory_id, transitive=True)`, `derived_from_source(ref)` (a `run` ref matches
261
+ everything stamped with that run), the lossless change feed `revisions(after=cursor)` (a cursor beyond the
262
+ log's head is refused), `replay_into(target)` (an empty home replays to the same file, adoptions included),
263
+ `names_ref(ref, owner_ids)` (the owner gate in one index probe), and `repair()` for closures a crash left
264
+ unwritten when the journal lives in another file (never needed for same-file plane and entity homes).
265
+ - Four tables in the home file: `memg_revisions`, `memg_provenance`, `memg_derivations`, `memg_history`.
266
+ - **`narrow_assertion(assertion_id, valid_until)`** on `SQLiteTripleStore` and `InMemoryTripleStore`: moves an
267
+ already-closed validity window earlier and never widens it (`ValueError` for an open window or a value that is
268
+ not a timestamp; `False` for an unknown id or a date at or after the current end, compared as instants). `LanceDBTripleStore.narrow_assertion` raises
269
+ `NotImplementedError` (on LanceDB a window changes through the graph's LanceDB connector). AbstractNote no longer
270
+ needs to write the store's private table.
271
+ - **Closure kind `merged`** (`abstractmemory.journal.CLOSURE_KINDS`): the memory was merged into another, named in
272
+ `replacement_ids`. `close_assertions` and `close_record` accept it.
273
+ - Docs: `api.md` (the graph section and its tables), `memory-system.md` ("Time axes", "Provenance").
274
+ - Measured at 50,000 assertions (`tests/bench/bench_graph.py`): `history` 0.02 ms, `sources_of` 0.04 ms,
275
+ `derived_from_source` by step 0.05 ms and by run 0.8 ms, a change-feed page of 100 revisions 4 ms; the 0.3
276
+ alternative (scanning provenance JSON) took 18 ms on vectorless rows and 38 ms with 384-d vectors in the rows.
277
+
278
+ ### Performance (0058)
279
+
280
+ Backlog 0058 (ADR 0003 decisions 3 and 12): the SQLite home store holds a
281
+ notebook-sized corpus. Measured with `tests/bench/bench_store.py`, `main`
282
+ versus this release on the same machine, back to back: subject + owner query
283
+ at 50k rows 14.8 ms -> 0.33 ms; scope "latest 100" 377 ms -> 0.9 ms; scope
284
+ full scan 2.6 s -> 0.5 s; vector query at 50k 5.3 s -> 1.4 ms (first query of
285
+ a handle 0.44 s, it builds the matrix); file 449 MB -> 122 MB; MemorySystem
286
+ `reconstruct` at 20k records 2.7 s -> 0.2 s; `maintenance_due` at 20k 1.9 s ->
287
+ 0.07 ms when nothing is new, 0.1 s after new records. Full table: backlog
288
+ 0058's Report.
289
+
290
+ - **Owner-filtered reads use the indexes.** The owner filter is now
291
+ `owner_id = ?` instead of `COALESCE(owner_id, '') = ?` (same rows: the
292
+ filter only applies to a non-empty owner, which a NULL or empty stored owner
293
+ never equals). A new index `idx_<table>_scope_owner_observed (scope,
294
+ owner_id, observed_at, assertion_id)` serves "latest N in a (scope, owner)",
295
+ as-of windows and per-pair scans in query order without sorting the
296
+ partition; reads anchored on ids, a subject or an object use their own index
297
+ and check scope/owner per row. Existing homes gain the index when the store
298
+ is opened; no row is rewritten. `SQLiteTripleStore.query_plan(q)` returns
299
+ SQLite's `EXPLAIN QUERY PLAN` lines for a query (tests pin the plans).
300
+ - **Structured reads no longer fetch the vector column.** `query` (without
301
+ `query_text`/`query_vector`) and `query_keywords` select the assertion
302
+ columns only, instead of `SELECT *` dragging the stored embedding (several KB
303
+ per row) and the canonical text through every scan. They no longer read the
304
+ embedding pin either (it guards semantic queries only). Semantic queries and
305
+ `stored_vector` still read the vector; `TripleAssertion` is unchanged.
306
+ - **Vectors are float32 BLOBs.** `SQLiteTripleStore` stores vectors as float32
307
+ little-endian BLOBs (4 bytes per dimension instead of ~20 bytes of JSON
308
+ text). Homes holding JSON vectors are upgraded in place when the store opens:
309
+ rows above the `vector_blob_high_water` cursor are rewritten in bounded
310
+ transactions (idempotent; an interrupted upgrade resumes; ~5 s once for 50k
311
+ rows of 384-d vectors). Stored precision is float32: a score differs from
312
+ the float64 value an embedder returned by about 1e-7. A value float32 cannot
313
+ hold raises `ValueError` at write (zero rows written) instead of being
314
+ stored as infinity; `stored_vector` returns the float32 values. One-way: see
315
+ "Upgrade notes" above.
316
+ - **Opening a home is a read.** `SQLiteTripleStore` and `SQLiteJournal` take no write lock when opening an
317
+ up-to-date home (the keyword-index and vector backfills run only when there is work; every insert path keeps
318
+ their cursors at the head; the journal checks its schema in a deferred transaction), so a reader never waits
319
+ behind a writer (before: up to `busy_timeout`, then "database is locked").
320
+ - **Matrix cache footprint.** A (re)build reserves exactly the table's vector rows (one allocation); appends
321
+ grow by at most 10 % (`store_tuning.VECTOR_MATRIX_GROWTH`; no doubling). Per process that queries a home:
322
+ rows x dims x 4 B plus about 170 B per row (`store_tuning.py`). Measured at 100k x 1024: 424 MB held (552 MB
323
+ with doubling), build peak 460 MB (833 MB).
324
+ - **Vector queries from an in-process matrix cache.** With numpy installed
325
+ (new extra `abstractmemory[fast]`; also in `all`, `all-apple`, `all-gpu`
326
+ and `test`), vector queries are served from a float32 matrix built at a
327
+ handle's first semantic query, appended with rows written since by any
328
+ handle or process, and rebuilt when the vectors are rewritten
329
+ (`replace_vectors`, the upgrade; `vector_generation` in the meta sidecar).
330
+ Results are the reference scan's (`vector_scoring.rank_by_cosine`): same
331
+ rows, same order (ties in rowid order), bit-identical scores — a float32
332
+ pass picks the candidates with a margin above its error bound, and they are
333
+ re-scored with the reference arithmetic. Without numpy, or when a stored
334
+ vector cannot be scored exactly (mixed dimensions, non-finite values), the
335
+ Python scan answers, labelled once per handle with a `#FALLBACK`
336
+ `RuntimeWarning`. `SQLiteTripleStore.vector_engine` reports the path.
337
+ - **`maintenance_due` bounded by a cursor.** For the SQLite and in-memory
338
+ stores the answer is folded from the new store change feed
339
+ `assertions_after(cursor, *, scope, owner_id, limit)`: a check reads only the
340
+ rows written since the previous check of the same (store, journal, scopes)
341
+ and re-reads the journal's formation bindings only when the journal moved.
342
+ `last_maintenance_seq` uses the same fold. The answer is the full scan's
343
+ (other stores keep the scan).
344
+ - Tuning constants of the store (margins, batch and page sizes) live in
345
+ `abstractmemory.store_tuning`, each with its bound or measurement.
346
+ - The benchmark lives in the repository: `tests/bench/bench_store.py`.
11
347
 
12
348
  ## [0.3.2] - 2026-10-20
13
349
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: AbstractMemory
3
- Version: 0.3.2
3
+ Version: 0.5.0
4
4
  Summary: AbstractMemory: temporal, provenance-aware semantic memory primitives for AbstractFramework.
5
5
  Project-URL: AbstractFramework (monorepo), https://github.com/lpalbou/abstractframework
6
6
  Author: Laurent-Philippe Albou
@@ -19,18 +19,24 @@ Classifier: Programming Language :: Python :: 3.13
19
19
  Requires-Python: >=3.10
20
20
  Provides-Extra: all
21
21
  Requires-Dist: lancedb; extra == 'all'
22
+ Requires-Dist: numpy>=1.24; extra == 'all'
22
23
  Provides-Extra: all-apple
23
24
  Requires-Dist: lancedb; extra == 'all-apple'
25
+ Requires-Dist: numpy>=1.24; extra == 'all-apple'
24
26
  Provides-Extra: all-gpu
25
27
  Requires-Dist: lancedb; extra == 'all-gpu'
28
+ Requires-Dist: numpy>=1.24; extra == 'all-gpu'
26
29
  Provides-Extra: apple
27
30
  Provides-Extra: dev
28
31
  Requires-Dist: pytest>=7.0.0; extra == 'dev'
32
+ Provides-Extra: fast
33
+ Requires-Dist: numpy>=1.24; extra == 'fast'
29
34
  Provides-Extra: gpu
30
35
  Provides-Extra: lancedb
31
36
  Requires-Dist: lancedb; extra == 'lancedb'
32
37
  Provides-Extra: test
33
38
  Requires-Dist: lancedb; extra == 'test'
39
+ Requires-Dist: numpy>=1.24; extra == 'test'
34
40
  Requires-Dist: pytest>=7.0.0; extra == 'test'
35
41
  Description-Content-Type: text/markdown
36
42
 
@@ -49,6 +55,15 @@ Storage never decays and nothing is ever deleted; only retrieval strength change
49
55
  - The authoritative export list is [`src/abstractmemory/__init__.py`](src/abstractmemory/__init__.py); [`docs/api.md`](docs/api.md) documents it.
50
56
  - Requires Python 3.10+.
51
57
 
58
+ ## What's new in 0.5.0
59
+
60
+ - Every memory's title and summary is authored: memory's passes take a host `author` callable, and a record whose authoring failed forms pending, with its task, until a reader completes it (`retitle`, `rewrite_digest`, `declare_pending`, `rearm_pending`).
61
+ - A persistent task queue per home (`MemorySystem(task_queue=True)`), ripple v1, and understanding rewritten in place with every earlier reading kept as a version.
62
+ - Topics: `community` records formed during sleep, with provisional placement of each new record at formation.
63
+ - The sleep cadence read `records_since_maintenance`, and the Stop fence hooks `commit_guard` and `write_barrier`.
64
+
65
+ Upgrading from 0.4.x: see the "Upgrading" notes in [`CHANGELOG.md`](CHANGELOG.md).
66
+
52
67
  ## Ecosystem (AbstractFramework)
53
68
 
54
69
  AbstractMemory is a component of the **AbstractFramework** ecosystem. It has no dependency on AbstractCore or AbstractRuntime; embeddings for semantic retrieval can come from any OpenAI-compatible `/embeddings` endpoint (`OpenAICompatTextEmbedder`), from an AbstractGateway deployment (`AbstractGatewayTextEmbedder`), or from your own `TextEmbedder` implementation.
@@ -86,6 +101,13 @@ Optional LanceDB backend:
86
101
  python -m pip install -e ".[lancedb]"
87
102
  ```
88
103
 
104
+ Fast vector search on the SQLite store (numpy; without it the store serves the
105
+ same results from a labelled Python scan):
106
+
107
+ ```bash
108
+ python -m pip install -e ".[fast]"
109
+ ```
110
+
89
111
  PyPI (packaged release):
90
112
 
91
113
  ```bash
@@ -93,7 +115,7 @@ python -m pip install AbstractMemory
93
115
  python -m pip install "AbstractMemory[lancedb]"
94
116
  ```
95
117
 
96
- The distribution name is `AbstractMemory` (pip is case-insensitive); the import name is `abstractmemory`. The `[apple]`/`[gpu]` extras are no-op compatibility aliases; `[all]`, `[all-apple]`, and `[all-gpu]` install the LanceDB backend.
118
+ The distribution name is `AbstractMemory` (pip is case-insensitive); the import name is `abstractmemory`. The `[apple]`/`[gpu]` extras are no-op compatibility aliases; `[fast]` installs numpy for the SQLite store's vector matrix cache; `[all]`, `[all-apple]`, and `[all-gpu]` install the LanceDB backend and numpy.
97
119
 
98
120
  ## Quick example — layer 1 (triples)
99
121
 
@@ -141,6 +163,10 @@ result = system.reconstruct(Stimulus(cue_text="pool outage"), scopes=[("session"
141
163
  system.commit_selection(result.trace_id, [h.record_id for h in result.handles[:2]])
142
164
  ```
143
165
 
166
+ ## The memory graph: revisions and provenance
167
+
168
+ `abstractmemory.graph` is the write path of a mind (0.4.0): every change to the graph is one `Revision` (a cause such as `ingest`, `reinterpret` or `maintenance`, plus `assert` / `close` / `narrow` operations applied together and atomically, once per revision id), and every memory must name where it came from in AbstractRuntime's ledger (a `SourceRef` to a run, a step `(run_id, seq)`, an artifact, a message, an event or a diary entry) or the memories it was derived from; a write with neither is refused with `ProvenanceRequired`. `MemoryGraph(store, journal)` then answers `history(memory_id)` (asserted, closed, narrowed: by which revision and why), `sources_of(memory_id)`, `derived_from_source(ref)`, a lossless change feed `revisions(after=cursor)`, and `replay_into(...)`. The database is a connector behind the graph (`abstractmemory.graph.backend`): SQLite by default, LanceDB and in-memory held to the same conformance suite. See [`docs/api.md`](docs/api.md#the-memory-graph-revisions-and-provenance) and the "Time axes" and "Provenance" sections of [`docs/memory-system.md`](docs/memory-system.md).
169
+
144
170
  ## Documentation
145
171
 
146
172
  - Getting started: [`docs/getting-started.md`](docs/getting-started.md)
@@ -164,7 +190,7 @@ system.commit_selection(result.trace_id, [h.record_id for h in result.handles[:2
164
190
 
165
191
  ## Design principles
166
192
 
167
- - **Append-only, no deletion**: updates are new assertions; belief revision is closure records (retract/supersede/reinterpreted); forgetting is decay of retrieval strength plus closures and silencing — the substrate is lossless.
193
+ - **Append-only, no deletion**: updates are new assertions; belief revision is closure records (retract/supersede/reinterpreted/merged); forgetting is decay of retrieval strength plus closures and silencing — the substrate is lossless. The one mutable cell is a record's understanding: `rewrite_digest` and `retitle` rewrite a digest or a title in place and keep every earlier reading as a version.
168
194
  - **Reads are pure**: reconstruction, inspection, replay, and the entity card deposit nothing. `commit_selection` is the only strengthening path.
169
195
  - **One seq axis**: the journal assigns a monotonic `seq` to every record; any past state is reproducible by anchoring reads at `as_of`.
170
196
  - **Works-or-loud**: degraded paths are labeled `#FALLBACK` in result warnings; invalid inputs raise actionable errors instead of silently meaning something else.
@@ -13,6 +13,15 @@ Storage never decays and nothing is ever deleted; only retrieval strength change
13
13
  - The authoritative export list is [`src/abstractmemory/__init__.py`](src/abstractmemory/__init__.py); [`docs/api.md`](docs/api.md) documents it.
14
14
  - Requires Python 3.10+.
15
15
 
16
+ ## What's new in 0.5.0
17
+
18
+ - Every memory's title and summary is authored: memory's passes take a host `author` callable, and a record whose authoring failed forms pending, with its task, until a reader completes it (`retitle`, `rewrite_digest`, `declare_pending`, `rearm_pending`).
19
+ - A persistent task queue per home (`MemorySystem(task_queue=True)`), ripple v1, and understanding rewritten in place with every earlier reading kept as a version.
20
+ - Topics: `community` records formed during sleep, with provisional placement of each new record at formation.
21
+ - The sleep cadence read `records_since_maintenance`, and the Stop fence hooks `commit_guard` and `write_barrier`.
22
+
23
+ Upgrading from 0.4.x: see the "Upgrading" notes in [`CHANGELOG.md`](CHANGELOG.md).
24
+
16
25
  ## Ecosystem (AbstractFramework)
17
26
 
18
27
  AbstractMemory is a component of the **AbstractFramework** ecosystem. It has no dependency on AbstractCore or AbstractRuntime; embeddings for semantic retrieval can come from any OpenAI-compatible `/embeddings` endpoint (`OpenAICompatTextEmbedder`), from an AbstractGateway deployment (`AbstractGatewayTextEmbedder`), or from your own `TextEmbedder` implementation.
@@ -50,6 +59,13 @@ Optional LanceDB backend:
50
59
  python -m pip install -e ".[lancedb]"
51
60
  ```
52
61
 
62
+ Fast vector search on the SQLite store (numpy; without it the store serves the
63
+ same results from a labelled Python scan):
64
+
65
+ ```bash
66
+ python -m pip install -e ".[fast]"
67
+ ```
68
+
53
69
  PyPI (packaged release):
54
70
 
55
71
  ```bash
@@ -57,7 +73,7 @@ python -m pip install AbstractMemory
57
73
  python -m pip install "AbstractMemory[lancedb]"
58
74
  ```
59
75
 
60
- The distribution name is `AbstractMemory` (pip is case-insensitive); the import name is `abstractmemory`. The `[apple]`/`[gpu]` extras are no-op compatibility aliases; `[all]`, `[all-apple]`, and `[all-gpu]` install the LanceDB backend.
76
+ The distribution name is `AbstractMemory` (pip is case-insensitive); the import name is `abstractmemory`. The `[apple]`/`[gpu]` extras are no-op compatibility aliases; `[fast]` installs numpy for the SQLite store's vector matrix cache; `[all]`, `[all-apple]`, and `[all-gpu]` install the LanceDB backend and numpy.
61
77
 
62
78
  ## Quick example — layer 1 (triples)
63
79
 
@@ -105,6 +121,10 @@ result = system.reconstruct(Stimulus(cue_text="pool outage"), scopes=[("session"
105
121
  system.commit_selection(result.trace_id, [h.record_id for h in result.handles[:2]])
106
122
  ```
107
123
 
124
+ ## The memory graph: revisions and provenance
125
+
126
+ `abstractmemory.graph` is the write path of a mind (0.4.0): every change to the graph is one `Revision` (a cause such as `ingest`, `reinterpret` or `maintenance`, plus `assert` / `close` / `narrow` operations applied together and atomically, once per revision id), and every memory must name where it came from in AbstractRuntime's ledger (a `SourceRef` to a run, a step `(run_id, seq)`, an artifact, a message, an event or a diary entry) or the memories it was derived from; a write with neither is refused with `ProvenanceRequired`. `MemoryGraph(store, journal)` then answers `history(memory_id)` (asserted, closed, narrowed: by which revision and why), `sources_of(memory_id)`, `derived_from_source(ref)`, a lossless change feed `revisions(after=cursor)`, and `replay_into(...)`. The database is a connector behind the graph (`abstractmemory.graph.backend`): SQLite by default, LanceDB and in-memory held to the same conformance suite. See [`docs/api.md`](docs/api.md#the-memory-graph-revisions-and-provenance) and the "Time axes" and "Provenance" sections of [`docs/memory-system.md`](docs/memory-system.md).
127
+
108
128
  ## Documentation
109
129
 
110
130
  - Getting started: [`docs/getting-started.md`](docs/getting-started.md)
@@ -128,7 +148,7 @@ system.commit_selection(result.trace_id, [h.record_id for h in result.handles[:2
128
148
 
129
149
  ## Design principles
130
150
 
131
- - **Append-only, no deletion**: updates are new assertions; belief revision is closure records (retract/supersede/reinterpreted); forgetting is decay of retrieval strength plus closures and silencing — the substrate is lossless.
151
+ - **Append-only, no deletion**: updates are new assertions; belief revision is closure records (retract/supersede/reinterpreted/merged); forgetting is decay of retrieval strength plus closures and silencing — the substrate is lossless. The one mutable cell is a record's understanding: `rewrite_digest` and `retitle` rewrite a digest or a title in place and keep every earlier reading as a version.
132
152
  - **Reads are pure**: reconstruction, inspection, replay, and the entity card deposit nothing. `commit_selection` is the only strengthening path.
133
153
  - **One seq axis**: the journal assigns a monotonic `seq` to every record; any past state is reproducible by anchoring reads at `as_of`.
134
154
  - **Works-or-loud**: degraded paths are labeled `#FALLBACK` in result warnings; invalid inputs raise actionable errors instead of silently meaning something else.
@@ -19,6 +19,7 @@ AbstractMemory is a Python library for durable, append-only agent memory: tempor
19
19
  - FAQ: [`faq.md`](faq.md) — common questions and current limits.
20
20
  - Troubleshooting: [`troubleshooting.md`](troubleshooting.md) — symptom-oriented fixes for setup, retrieval, embedding-space, durability, and maintenance problems.
21
21
  - Development: [`development.md`](development.md) — local setup, tests, and the design backlog.
22
+ - Architecture decisions: [`adr/README.md`](adr/README.md) — durable rules, including ADR 0001 (an altered memory ripples through the memories connected to it) and ADR 0002 (AbstractMemory owns the semantic temporal memory graph and all of its processing; applications build on it).
22
23
 
23
24
  ## Related
24
25