Files
james.maes f59f5d12e3 fix(memory): v0.1 CRIT cluster — facts_vec / replay correlation / FTS5 sanitize / search_memory preamble (#12, #13, #14, #15, #16, #153)
#14 (CRIT): ContextBuilder.selfAwarePreamble names search_memory + forget_fact with explicit cue 'call search_memory FIRST. Never claim to remember without searching.'

#16 (HIGH): MemoryQueries.sanitizeFTS5Query strips non-alphanumeric, quotes tokens; HybridSearch.searchFacts calls it before binding to MATCH ?. Embedding still runs on raw query.

#12 (CRIT): MemoryStore.init accepts optional embedder; insertNewFact writes facts_vec after the facts commit. Vec failures log + leave FTS row (no rollback). installMemory shares one embedder between writer + reader.

#15 (HIGH): drop stableHash; pass sentinel 0 as sourceTurnId (option 1 per audit — smaller change surface than threading real rowid through 5 files). Schema comment updated.

#13 (CRIT): two-layer fix. Layer 1: AppDelegate owns a per-process sentinel TurnID; installAgent writes the matching turns row after beginSession; AppDelegateMemoryReplaySink attributes events to it. Layer 2: ReplayLog.flushPending retries failed batches event-by-event so one poisoned row only drops itself.

Memory 98 + Replay 34 + AgentCore 243 tests pass; all 18 boundary gates green.
2026-05-13 06:30:35 -05:00
..

Replay

Per-turn NDJSON log under ~/Library/Application Support/Jarvis/replay/. Every turn writes a full transcript of LLM events, tool calls (pre- and post-sanitize bytes both, per SEC-07), memory mutations, and stop reason. The replayer is a developer tool, not user-facing.

Key public types

Type Purpose
ReplayLog (actor) The single writer; rotated per session
ReplayEvent NDJSON event union — turnStart, userInput, tokenDelta, toolCallRequested, toolResult, memoryRetrieval, memoryFactAdded, memoryFactUpdated, memoryFactForgotten, turnEnd
ReplaySession Session-level rollup (multiple turns)
ReplayPaths Path resolver

Depends on

AgentCore, Config, Logging. External: swift-log.

Used by

App/AppDelegate, packages/AgentCore (AgentOrchestrator is the primary writer), packages/Memory (writes mutation + retrieval events), App/MCP/ReplayingToolResultObserver.swift (writes pre/post sanitize bytes).

Key invariants / contracts

  • ReplayLog is the single writer per session file. Multi-writer is undefined.
  • turnNonce is persisted in replay rows but never on the bus (SEC-06).
  • Pre- and post-sanitize bytes both go to replay (SEC-07). The model only sees post-sanitize.
  • replayLog.beginSession is called before any turn. Pre-audit BLOCKER fixed (audit-2026-05-04).
  • NDJSON format. Each line is one event, JSON-encoded. Newline-delimited; no leading/trailing whitespace within events.

Tests

XCTest. Round-trip serialization tests, session rollover, file-handle leak detection (packages/Harness/FDLeakDetector SEC-08).

Notable files

  • Sources/Replay/ReplayLog.swift — the writer actor
  • Sources/Replay/ReplayEvent.swift — event union
  • Sources/Replay/ReplaySession.swift — session rollup