@oh-my-pi/pi-mnemopi 18.18.1 → 18.18.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [18.18.2] - 2026-11-08
6
+
7
+ ### Fixed
8
+
9
+ - Fixed recall returning episodic summaries for working memories that had been invalidated.
10
+
5
11
  ## [18.18.1] - 2026-11-08
6
12
 
7
13
  ### Fixed
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/pi-mnemopi",
4
- "version": "18.18.1",
4
+ "version": "18.18.2",
5
5
  "description": "Local SQLite memory engine for omp agents",
6
6
  "homepage": "https://omp.sh",
7
7
  "author": {
@@ -42,10 +42,10 @@
42
42
  "fmt": "oxfmt --no-error-on-unmatched-pattern 'src/**/*.{ts,tsx}' '{test,bench,examples,scripts}/**/*.ts' '*.ts'"
43
43
  },
44
44
  "dependencies": {
45
- "@oh-my-pi/pi-ai": "18.18.1",
46
- "@oh-my-pi/pi-catalog": "18.18.1",
47
- "@oh-my-pi/pi-natives": "18.18.1",
48
- "@oh-my-pi/pi-utils": "18.18.1"
45
+ "@oh-my-pi/pi-ai": "18.18.2",
46
+ "@oh-my-pi/pi-catalog": "18.18.2",
47
+ "@oh-my-pi/pi-natives": "18.18.2",
48
+ "@oh-my-pi/pi-utils": "18.18.2"
49
49
  },
50
50
  "peerDependencies": {
51
51
  "fastembed": "3.0.0",
@@ -715,37 +715,39 @@ export function getContext(beam: BeamMemoryState, limit = 10): Row[] {
715
715
 
716
716
  export function invalidate(beam: BeamMemoryState, memoryId: string, replacementId: string | null = null): boolean {
717
717
  const now = toUtcIso();
718
- const working = beam.db.run(
719
- `
720
- UPDATE working_memory
721
- SET valid_until = ?, superseded_by = ?
722
- WHERE id = ? AND (session_id = ? OR scope = 'global')
723
- `,
724
- [now, replacementId, memoryId, beam.sessionId],
725
- );
726
- if (working.changes > 0) {
727
- // Recall filters `valid_until`/`superseded_by` in SQL, but the enhanced path consults the
728
- // query cache BEFORE it reaches SQL. Without this the row a caller just retired keeps being
729
- // served to an identical query for the rest of the cache TTL -- the one thing an explicit
730
- // invalidation is supposed to guarantee against. Every other mutator here already does this;
731
- // this one was the omission. Gated on an actual row change, like `forgetWorking`, so a
732
- // no-op invalidation never discards a valid cache.
733
- invalidateCaches(beam);
734
- return true;
735
- }
736
- const episodic = beam.db.run(
737
- `
738
- UPDATE episodic_memory
739
- SET valid_until = ?, superseded_by = ?
740
- WHERE id = ? AND (session_id = ? OR scope = 'global')
741
- `,
742
- [now, replacementId, memoryId, beam.sessionId],
743
- );
744
- if (episodic.changes > 0) {
745
- invalidateCaches(beam);
746
- return true;
747
- }
748
- return false;
718
+ const changed = transaction(beam.db, () => {
719
+ const working = beam.db.run(
720
+ `
721
+ UPDATE working_memory
722
+ SET valid_until = ?, superseded_by = ?
723
+ WHERE id = ? AND (session_id = ? OR scope = 'global')
724
+ `,
725
+ [now, replacementId, memoryId, beam.sessionId],
726
+ );
727
+ if (working.changes > 0) {
728
+ // Retire episodic summaries built from this source: they still carry its text. Siblings
729
+ // covered by the same summary stay recallable via their (consolidated, never TTL-trimmed)
730
+ // working rows.
731
+ beam.db.run(
732
+ `UPDATE episodic_memory SET valid_until = ?, superseded_by = ?
733
+ WHERE (session_id = ? OR scope = 'global')
734
+ AND instr(',' || summary_of || ',', ',' || ? || ',') > 0`,
735
+ [now, replacementId, beam.sessionId, memoryId],
736
+ );
737
+ return true;
738
+ }
739
+ const episodic = beam.db.run(
740
+ `
741
+ UPDATE episodic_memory
742
+ SET valid_until = ?, superseded_by = ?
743
+ WHERE id = ? AND (session_id = ? OR scope = 'global')
744
+ `,
745
+ [now, replacementId, memoryId, beam.sessionId],
746
+ );
747
+ return episodic.changes > 0;
748
+ });
749
+ if (changed) invalidateCaches(beam);
750
+ return changed;
749
751
  }
750
752
 
751
753
  export function getWorkingStats(