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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +118 -0
- data/README.md +409 -39
- data/lib/engram/adapters/in_memory_processed_turns.rb +40 -8
- data/lib/engram/adapters/in_memory_store.rb +49 -11
- data/lib/engram/adapters/null_embedder.rb +9 -0
- data/lib/engram/adapters/pgvector_store.rb +67 -20
- data/lib/engram/adapters/ruby_llm_embedder.rb +45 -4
- data/lib/engram/configuration.rb +5 -1
- data/lib/engram/consolidators/heuristic_consolidator.rb +7 -1
- data/lib/engram/consolidators/llm_consolidator.rb +44 -12
- data/lib/engram/embedding_metadata.rb +135 -0
- data/lib/engram/extractors/llm_extractor.rb +16 -6
- data/lib/engram/instrumentation.rb +57 -0
- data/lib/engram/memory.rb +42 -17
- data/lib/engram/memory_kind.rb +19 -0
- data/lib/engram/persistence.rb +39 -0
- data/lib/engram/persistence_policy.rb +45 -0
- data/lib/engram/ports/memory_store.rb +16 -8
- data/lib/engram/ports/processed_turns.rb +16 -8
- data/lib/engram/provenance.rb +257 -0
- data/lib/engram/rails/cache_processed_turns.rb +51 -10
- data/lib/engram/rails/observe_job.rb +5 -0
- data/lib/engram/rails/tasks.rake +26 -0
- data/lib/engram/railtie.rb +4 -0
- data/lib/engram/record.rb +8 -3
- data/lib/engram/reserved_metadata.rb +52 -0
- data/lib/engram/use_cases/forget.rb +6 -2
- data/lib/engram/use_cases/inject.rb +17 -3
- data/lib/engram/use_cases/observe.rb +83 -19
- data/lib/engram/use_cases/rebuild_embeddings.rb +189 -0
- data/lib/engram/use_cases/recall.rb +28 -9
- data/lib/engram/version.rb +1 -1
- data/lib/engram.rb +11 -0
- data/lib/generators/engram/install_generator.rb +10 -0
- data/lib/generators/engram/templates/create_engram_memories.rb.tt +10 -3
- metadata +14 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8a38dfd456e4e89f37a9d4d8949a5bb77b9736d95621e9172ba1db72fb3a5771
|
|
4
|
+
data.tar.gz: 0b537ee13bea0313fd770c529024af45e9ace8fb84f7e49621c2dc7b9d6b888c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|