engram 0.3.0 → 0.5.0

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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +118 -0
  3. data/README.md +409 -39
  4. data/lib/engram/adapters/in_memory_processed_turns.rb +40 -8
  5. data/lib/engram/adapters/in_memory_store.rb +49 -11
  6. data/lib/engram/adapters/null_embedder.rb +9 -0
  7. data/lib/engram/adapters/pgvector_store.rb +67 -20
  8. data/lib/engram/adapters/ruby_llm_embedder.rb +45 -4
  9. data/lib/engram/configuration.rb +5 -1
  10. data/lib/engram/consolidators/heuristic_consolidator.rb +7 -1
  11. data/lib/engram/consolidators/llm_consolidator.rb +44 -12
  12. data/lib/engram/embedding_metadata.rb +135 -0
  13. data/lib/engram/extractors/llm_extractor.rb +16 -6
  14. data/lib/engram/instrumentation.rb +57 -0
  15. data/lib/engram/memory.rb +42 -17
  16. data/lib/engram/memory_kind.rb +19 -0
  17. data/lib/engram/persistence.rb +39 -0
  18. data/lib/engram/persistence_policy.rb +45 -0
  19. data/lib/engram/ports/memory_store.rb +16 -8
  20. data/lib/engram/ports/processed_turns.rb +16 -8
  21. data/lib/engram/provenance.rb +257 -0
  22. data/lib/engram/rails/cache_processed_turns.rb +51 -10
  23. data/lib/engram/rails/observe_job.rb +5 -0
  24. data/lib/engram/rails/tasks.rake +26 -0
  25. data/lib/engram/railtie.rb +4 -0
  26. data/lib/engram/record.rb +8 -3
  27. data/lib/engram/reserved_metadata.rb +52 -0
  28. data/lib/engram/use_cases/forget.rb +6 -2
  29. data/lib/engram/use_cases/inject.rb +17 -3
  30. data/lib/engram/use_cases/observe.rb +83 -19
  31. data/lib/engram/use_cases/rebuild_embeddings.rb +189 -0
  32. data/lib/engram/use_cases/recall.rb +28 -9
  33. data/lib/engram/version.rb +1 -1
  34. data/lib/engram.rb +11 -0
  35. data/lib/generators/engram/install_generator.rb +10 -0
  36. data/lib/generators/engram/templates/create_engram_memories.rb.tt +10 -3
  37. metadata +14 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9afed525e71087af57cf1297cc80b4547abbe4df9e1077282ba0427cfeb5a708
4
- data.tar.gz: 461907e0eafb4bed9442475a0bea0c2830cff62ac55291b7dc3eb9aeb8930b52
3
+ metadata.gz: 8a38dfd456e4e89f37a9d4d8949a5bb77b9736d95621e9172ba1db72fb3a5771
4
+ data.tar.gz: 0b537ee13bea0313fd770c529024af45e9ace8fb84f7e49621c2dc7b9d6b888c
5
5
  SHA512:
6
- metadata.gz: d1fc61bad8a535990c93aa6f12401ffa4a18605357e1782b9e41be4a3d6ddbd9b4a00f805dba904c987db74a65773952cbfad806a60dfbe49a12e3b899cdbb16
7
- data.tar.gz: 771b6d7030dd2ae664457c7eba01c7edd1f80f82af5a5566e57c93a97cf9bd1ab34077b638508789e40c7a3128645c0cfc7391fe5fd26d79dec22162696218f8
6
+ metadata.gz: 768d5d18a9ce04f60db58957127df76fbdc30482df4976d7d04b082af005850ba821ba45a35417c33946668af60331e869cf930e6239409ba10168a453f58665
7
+ data.tar.gz: 7ec7997ba40947deede93b6e970a549bf6caae32eed79f0e4c3922ebecbf05bc1545b5565afc521c9dab6c0f95b27898b3ae9bd9f3f57d9935a48d18e9211322
data/CHANGELOG.md CHANGED
@@ -5,6 +5,119 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [0.5.0] - 2026-07-17
9
+
10
+ ### Added
11
+ - Embedding provenance metadata is stored with new memories so applications can detect model
12
+ and dimension drift during store search result validation.
13
+ - `Memory#rebuild_embeddings` and `Engram::UseCases::RebuildEmbeddings` for scoped,
14
+ deterministic rebuilding of stale vectors plus provenance metadata.
15
+ - Added a focused rake task `engram:rebuild_embeddings` with batch control and optional
16
+ forced full-scope rebuild mode for recovery after provider/model changes. The task is
17
+ packaged with the gem and loaded into host Rails apps by the Railtie, where it depends on
18
+ `:environment` so app initializers run first. `STALE_ONLY` accepts `false`, `0`, or `no`.
19
+
20
+ ### Changed
21
+ - `MemoryStore` mutations now require an explicit `scope:` and enforce the `(scope, id)` boundary
22
+ for update, delete, and touch operations. Custom stores must adopt the new scoped signatures;
23
+ `update` returns the updated record or raises `Engram::Error`, while delete and touch return an
24
+ affected-row count.
25
+ - **Breaking (pre-1.0):** the `ProcessedTurns` port migrated from the previous check/mark API
26
+ to `claim`, `complete`, `release`, and `completed?`; custom adapters must implement the new
27
+ claim lifecycle. A successful claim returns a truthy opaque token.
28
+ - Observation idempotency now uses atomic, scope-aware claims with an in-progress lease and
29
+ completed state. `InMemoryProcessedTurns` is thread-safe and releases failures immediately.
30
+ Generic cache release is a no-op until lease expiry because ActiveSupport cache has no atomic
31
+ compare-and-delete; completion never deletes a possibly newer claim. Completed markers
32
+ suppress later calls only for their configured `ttl`. A failed completion write leaves the
33
+ lease to suppress work until expiry, after which already-applied work may replay. `lease_ttl`
34
+ should cover the longest observation while remaining much shorter than `ttl`, and
35
+ `Rails::CacheProcessedTurns` uses atomic `unless_exist` writes with separate claim and
36
+ completion keys. This coordinates concurrent work but does not make multi-decision memory
37
+ persistence and claim completion a crash-proof transaction. Lease expiry may permit overlap,
38
+ so claims do not guarantee ownership, fencing, or exactly-once execution.
39
+ - Added API stability and migration posture documentation for pre-1.0 freeze planning, including public surface boundaries and legacy compatibility points.
40
+ - Store search result validation now raises a clear `Engram::Error` when stored embedding
41
+ metadata or vector dimensions conflict with the active embedder, while legacy records without
42
+ metadata remain searchable when their vector dimensions match the active embedder.
43
+ - Caller metadata keys named `_engram` are now reserved for Engram-owned embedding provenance;
44
+ rename any application metadata stored under that key before adding new memories.
45
+ - `RubyLLMEmbedder` now requests explicitly configured `dimensions:` from the provider (on
46
+ RubyLLM versions that support the option) and validates every returned vector against the
47
+ configured dimensions, raising a clear `Engram::Error` on mismatch. Previously the option
48
+ was recorded in metadata but never sent or checked, so a mismatch surfaced later as opaque
49
+ pgvector insert failures. If you use a model whose native vector size differs from 1536,
50
+ set `dimensions:` to that model's actual output size.
51
+
52
+ ### Fixed
53
+ - `Observe` now raises `Engram::ObservationInProgressError` when a turn is claimed but not
54
+ completed, rather than reporting a successful no-op. `ObserveJob` retries this error with
55
+ backoff that outlasts the default claim lease; direct callers should handle it as retryable.
56
+ - Stale detection in `rebuild_embeddings` now compares against the embedder's declared
57
+ dimensions instead of the stored record's vector length, so a dimensions-only embedder
58
+ change marks existing rows stale. Previously the default stale-only rebuild silently
59
+ skipped every row after such a change. Embedders that do not declare dimensions keep the
60
+ previous record-length comparison.
61
+ - `LLMConsolidator` now ignores malformed decisions and rejects `update`/`forget` targets
62
+ that were not shown to the model, preventing invalid model output from partially applying
63
+ a turn. Cross-scope updates from custom consolidators still raise in `Observe`.
64
+
65
+ ## [0.4.0] - 2026-06-06
66
+
67
+ ### Added
68
+ - Canonical memory kinds: `fact`, `preference`, `instruction`, and `episodic`.
69
+ - Typed recall filters via `kinds:` for `Memory#recall` and prompt injection.
70
+ - Typed XML-like memory injection with escaped content and `kind` attributes.
71
+ - Default `PersistencePolicy` that rejects obvious secrets/tokens/passwords and transient
72
+ task-progress memories before storage.
73
+ - `before_persist` hook and caller-provided denylist redaction support.
74
+ - Optional `ActiveSupport::Notifications` instrumentation around the observe/recall/inject
75
+ pipeline (`*.engram` events) with a configurable `instrumentation_scope_identifier` for
76
+ privacy-safe scope tagging. Stays a no-op when ActiveSupport is not loaded, so the core
77
+ remains dependency-free.
78
+ - Documentation for provider-agnostic model configuration, pgvector setup, production
79
+ readiness, prompt-injection safety, and real-provider eval smoke testing.
80
+ - `SECURITY.md` threat model covering prompt-injection boundaries, secret handling, and
81
+ the untrusted-input posture of recalled memories.
82
+ - `rake eval:real` for RubyLLM-backed eval smoke runs that keep provider configuration
83
+ delegated to RubyLLM.
84
+
85
+ ### Changed
86
+ - Legacy `semantic` memories are normalized to `fact` in Ruby and included by `kinds: [:fact]`
87
+ filters for compatibility.
88
+ - `Memory#add` returns `nil` when the persistence policy rejects a memory.
89
+ - Redacted or otherwise modified records have embeddings recomputed before storage.
90
+ - Rails generator default memory kind is now `fact` instead of `semantic`.
91
+ - Install generator and `create_engram_memories` template harden pgvector setup: clearer
92
+ extension installation guidance, safer defaults, and explicit dimension handling.
93
+ - `InMemoryStore` and `PgvectorStore` enforce scope isolation defensively so recall, update,
94
+ and delete operations cannot cross scopes even when callers pass mismatched ids.
95
+ - README status, feature overview, Rails setup, development commands, and roadmap now reflect
96
+ the current pre-1.0 API surface.
97
+ - Real-provider eval setup delegates provider-specific RubyLLM configuration to RubyLLM
98
+ instead of hardcoding credential environment variable names in Engram.
99
+ - Real-provider eval forces UTF-8 external encoding before loading RubyLLM so smoke runs work
100
+ even when the shell locale defaults Ruby to US-ASCII.
101
+ - RubyLLM provider configuration failures now show an eval-specific setup hint instead of a raw
102
+ provider stack trace.
103
+
104
+ ### Security
105
+ - Memory persistence rejects common secret and credential patterns by default.
106
+ - Documentation now calls out that recalled memories are untrusted user-derived context, not
107
+ system instructions or authorization facts.
108
+ - Published a memory security threat model in `SECURITY.md` covering the boundaries Engram
109
+ enforces and the ones the host application must enforce.
110
+ - Store-level scope isolation guarantees prevent cross-scope memory leakage on misuse.
111
+
112
+ ### Upgrade notes
113
+ - Existing rows with `kind = "semantic"` continue to work: Engram treats them as `fact` at
114
+ read time for recall filters; existing rows are not rewritten. New generated migrations
115
+ default to `fact`.
116
+ - If application code assumed `Memory#add` always returns a record, handle `nil` for rejected
117
+ memories.
118
+ - If you change embedding providers/models, verify the generated pgvector column dimension
119
+ matches the embedding vector length.
120
+
8
121
  ## [0.3.0] - 2026-05-25 — idempotency, smarter recall, forgetting
9
122
 
10
123
  ### Added
@@ -15,6 +128,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
15
128
  - `touch_on_recall` and `MemoryStore#touch` to update `last_accessed_at` on recall.
16
129
  - `UseCases::Forget` and `Memory#forget_stale` to prune memories by age and importance.
17
130
 
131
+ ### Fixed
132
+ - Extractor and consolidator JSON schemas now satisfy OpenAI strict structured outputs
133
+ (`additionalProperties: false`, every property in `required`, nullable `target_id`), so the
134
+ RubyLLM + OpenAI path works end to end. A schema-conformance spec guards against regressions.
135
+
18
136
  ## [0.2.0] — extract → consolidate
19
137
 
20
138
  ### Added