Releases: jsflax/Engram
Releases · jsflax/Engram
Release list
v0.13.3
Performance release: kills the sync-daemon busy-spin, the unbounded WAL
growth, and the recall slowdown they compounded into (Claude Code's
UserPromptSubmit hook timing out — recall observed at 228s on a churned
database; now sub-second).
Fixed
- Sync daemon busy-spin — upload passes were re-invoked with zero delay
from four sites and each pass re-scanned the entire audit log (the daemon
burned ~46 CPU-hours in 2 days against a slow server). Upload ticks are
now paced (leading-edge immediate + coalescing window; WSS 750ms, IPC
relay 50ms), each pass is bounded to one send window by a new per-slot
upload_floorcursor, and a stalled server backs the resend cadence off
exponentially instead of being re-hammered every 10s. - Unbounded WAL growth — nothing at runtime ever checkpointed the WAL
while the daemon's long-lived connections pinned the passive autocheckpoint
(memory.sqlite-walobserved at 1.1GB; every SQL statement then pays an
O(WAL) page-lookup penalty). The sync engine now runs PASSIVE checkpoints
every 60s — including while disconnected — and TRUNCATE every 5 minutes
when idle. - Reconnect storms — the exponential backoff reset itself on every
successful open, so a flapping endpoint reconnected at ~1s forever. The
counter now resets only after a connection proves stable (≥60s). - Recall N×K statement explosion — every property read on a recalled
memory issued its ownSELECT(~300 statements per depth-1 recall).
Recall now materializes each hit from the row its query already fetched
(zero further SQL), reads embeddings once per traversal candidate, and
batches access-stat bumps into one transaction of atomic increments on
the correct database handle (they silently autocommitted individually on
synced projects before). - Sync progress counters —
pendingaccumulated the whole backlog on
every pass and never returned to zero; it now mirrors exactly the
sent-but-unACKed set, so the daemon health surface is trustworthy.
v0.13.2
First field-report fix (thanks to the first external install).
Fixed
- CLI binaries broken after app auto-update — the installer copied
binaries out of a Sparkle-updated bundle without stripping
com.apple.quarantine, so Gatekeeper blocked the memory MCP server when
Claude Code spawned it; a partial copy could also stamp the version and
wedge the install until the next release. The installer now strips
quarantine after each copy, treats missing bundled binaries as an error,
verifies every binary (executable + unquarantined) before stamping the
version, and logs failures to~/.claude/cli-install-error.loginstead of
dying silently.
v0.13.1
Same-day follow-up to 0.13.0 focused on onboarding and first-run polish.
Fixed
- Stale dev endpoints purged at launch — a persisted ngrok/localhost
sync_endpointfrom an old dev session survived app updates and silently
pointed both the app and the sync daemon at a dead tunnel ("authentication
failed" with no hint why). Ephemeral dev endpoints are now discarded;
genuine custom endpoints still persist. - Daemon endpoint follows the app — the sync daemon's launchd plist
snapshots its--endpointat install time; endpoint changes (and the
migration above) now rewrite the plist and restart the daemon immediately
instead of waiting for the next app version bump. - Proximity audio audible from anywhere — the manual distance gain never
fully silenced (floored at −30 dB) and the quantile LOD near-tier is
relative, so the nearest tones hummed at any camera distance. Voices now
hard-mute beyond an absolute audibility range.
Added
- Live subscription unlock — while signed in without an active
subscription, the app polls status once a minute; an admin-granted (or
newly purchased) subscription connects sync immediately, no restart. - Subscribe button in the Account tab for signed-in users without a
subscription — opens the web checkout.
Notes
- Email registration works end-to-end as of the 0.13.0 server deploy (the
server now returns a session token on register; previously registration
failed silently in all app versions).
v0.13.0
The revival release: three months of accumulated breakage fixed across the
full stack — visualizer, IPC/cloud sync, hooks, and the production relay.
Cloud sync is live end-to-end for the first time since April 5.
Fixed — sync (15 production bugs)
- Cloud sync outage root causes: expired auth token silently rejected every 60s
for 3 months (the UI's green "Synced" showed pending-count, not connection state —
now a real health surface); relay dropped each connection's first frames
(handler-registration race); no at-least-once redelivery (unACKed entries now
resend on a 10s timeout); IPC wedged at 0/365 by sync-state collapse against a
stale config snapshot (live slot registry + startup heal). - The relay killer: Swift C++-interop on aarch64 Linux crashes (null protocol
witness) on Collection ops over imported std::vector — the production relay
segfaulted on every received frame. macOS unaffected, so every local gate stayed
green. Index loops now (lattice 0.10.6); reproduced + validated in a Linux container. - Unshare destroyed peers' data: narrowing a sync filter fleet-deleted rows on
every device (the February data-loss bug). Filter removals now stop at the
device's own synced DB; peers retain their copies (E2E-pinned). - URLSession 401 poisoning: one 401 during server boot made CFNetwork silently
drop the Authorization header on all later connects in that session — fresh
ephemeral session per attempt + stale-session delegate guard. - Upload flow control: full-backlog bursts (25×1MB frames) overran the relay;
sends are now windowed per ack round-trip. Transport errors without close events
left the synchronizer "connected" and unable to reconnect — fixed. - April recall crash: Results live-fetch subscript TOCTOU under Collection.map —
KNN results materialized via Array(). - Hooks crash: session state mutated after its backing lattice deallocated
(weak instance cache) — all access now scoped via withSessionState.
Fixed — visualizer
- Traversal color flash: MeshInstancesComponent slots are now stable across
topology changes (color texture and transforms aren't versioned together by
RealityKit); departed slots collapse to zero scale. - Mascot "camo" texture: the scene sets no IBL, so RealityKit's default studio
environment mirrored in glossy regions — reflections damped (roughness floor,
specular cut, clearcoat off). The asset itself was never broken. - Sign-out crash during galaxy load (Galaxy.startObservers fatalErrors → graceful).
- New-memory relayout: a settled simulation absorbs small topology deltas (≤24)
without a full re-layout jolt. - MeshInstancesComponent UAF crash on near-camera orbit (create-once components).
- Sidebar lag: per-project counts cached (was 77 synchronous SQL COUNTs per
SwiftUI body evaluation against a 1.1GB database).
Performance
- Visualizer at 42k nodes / 232k edges: orbit worst-case 434ms → 12.4ms p50
(preview, full 8k-instance render budget + 30k edges). Idle LOD is ~free
(cached visible-set); GPU force pass confirmed 0.4–1.0ms (Barnes-Hut). - Production adapter now maintains indexed position arrays + per-tick caches
(glow/centroid/topic), quantile-tier LOD replaces fixed cutoffs (fixed
5000-unit cull blanked the whole graph at 42k scale). - Label propagation rewritten: async in-place, sticky ties, closed-neighborhood
seeding — deterministic communities.
Added
- CrashReporter: async-signal-safe crash reports for the MCP server (ring
buffer + signal handlers, no allocation in the handler). - Statusline: remember-events render in the Claude Code statusline
(engram-statusline.sh + installer). - Sync health surface: daemon status JSON (state/pending/lastSync) + red/yellow
problem rows in the sync UI. - vacuum / train_vectors MCP tools; nuclear-compact escape hatch for full
re-upload; fresh-peer replay handshake for IPC catch-up.
Changed
- Package now depends on tagged releases (lattice 0.10.6) instead of a local
path — remote-resolved builds are the release gate. - Maintenance trigger: 10 → 50 CRUD ops + 15-minute cooldown (self-retrigger fix).
- Lattice logging env-gated (default error) + session-log cleanup covers all
binaries; memory-logs no longer grow unbounded.
Known debt
- EngramVisualizerTests' GPU-internal suites (BH roundtrip internals, hybrid
CPU-integration path, pipelining-count asserts) predate the April Metal refactor
and were dead-on-arrival with it (a deleted-kernel crash blocked the whole target
until this release); their timing budgets are idle-machine calibrated. The public
ForceEngine path is green. Reconciliation tracked for a follow-up.
v0.12.4
Fixed
- Label atlas crash on large graphs —
renderLabelAtlascreated textures exceeding Metal's 16384px max dimension when users had many memories with long labels (e.g. height 22774). Atlas now falls back to 1x scale when 2x would overflow, with a hard cap at 16384. - Label truncation overflow —
extractLabeltopic-prefix path could produce 50+ character labels (e.g."visualizer-3d-rendering-core: ...") when topic names were long, wasting atlas row space. Labels now intelligently budget between topic and content, capped at 30 chars total. - Atlas texture storage mode — changed from
.managedto.shared(correct for Apple Silicon unified memory)
Changed
- Sparkle signing — replaced
--deepcodesign with explicit bottom-up signing of XPC services, fixing App Management TCC prompt on macOS Ventura+
v0.12.3
Fixed
- Metal crash on minimize — MTKView continued rendering at 60fps when the window was minimized, producing zero-dimension drawables that triggered a Metal validation SIGABRT. Added dimension guards and pause/resume on minimize/deminiaturize.
- Empty embedding SIGTRAP —
remember,merge, andconsolidatesilently storedVector<Float>([])when the CoreML embedding model failed to load. Laterrecallwith a valid query vector hit a dimension mismatch in sqlite-vec, causing an uncatchable SIGTRAP in LatticeCore. These operations now fail with a clear error instead of storing empty vectors.
Improved
- Recall quality — NLTagger POS-based content-word extraction for FTS queries (drops determiners, pronouns, prepositions), staleness penalty for never-accessed memories older than 14 days, weak-recall warning when average distance > 0.07, and graph traversal now filters connected memories by semantic relevance to the query
- GPU compute edge stamping — edge cylinder geometry now stamped via Metal compute kernel, matching the existing node sphere pipeline
- Log rotation — hooks, session-learner, and maintenance logs rotate at 256KB with one
.1backup
Added
- Sidebar view — new left-side panel for graph controls and navigation
v0.12.2
Fixed
- Sparkle auto-update broken —
sparkle:version(build number) was hardcoded to1for every release, so Sparkle never offered updates. Build number now auto-increments from the previous appcast entry.
v0.12.1
Changed
- Raw Metal renderer — replaced RealityKit with a custom MTKView pipeline, eliminating 67.5% main thread blocking in
re::DrawingManager::commitFrameInternal()and 13.5% VFX lock contention fromParticleEmitterComponent - GPU procedural nebulae — fBm noise billboards rendered entirely in Metal fragment shaders, replacing RealityKit particle emitters
- Blinn-Phong lighting — sphere impostor nodes use analytical normal reconstruction with Blinn-Phong shading tuned for dark-background aesthetic
- Opaque rendering — fog baked into
base_colorin shaders instead of.transparentblending, avoiding GPU depth sorting of 55K+ triangles - Search spotlight — suppressed recall glow on non-matching nodes for cleaner visual contrast
- EngramModels library extraction — core model types (Memory, Edge, Checkpoint, HookState) moved into a separate SPM target; EngramKit re-exports via
@_exported import EngramModels - Account UI — Apple and Google Sign-In via
AuthenticationServicesandGoogleSignIn-iOS, posting identity tokens to cloud sync backend - Streaming graph load — batched node loading off main actor for faster initial render
- GraphRenderStore — bypass SwiftUI observation for 3D render data, reducing unnecessary view recomputation
- Project labels in 3D view — project name labels rendered in the 3D scene with tighter clustering
- Lattice dependency switched from local path to remote URL (
0.4.0)
Fixed
- Node flicker during force simulation convergence
- FTS5 full-text search query handling
- GPU compute label batch sizing and edge buffer synchronization
- Drive-to-project camera animation