Memory: replay log poisoned by synthetic memory-trigger-<hash> turn_ids; all batches FK-fail since 18:48 #13
Closed
opened 2026-05-12 19:03:24 +00:00 by KofTwentyTwo
·
1 comment
No Branch/Tag Specified
develop
ci/secrets-historical-baseline
feature/security-findings-2026-10
dependabot/npm_and_yarn/webview/npm_and_yarn-3ac77625be
dependabot/npm_and_yarn/webview/packages/bus/npm_and_yarn-c86b58a346
dependabot/npm_and_yarn/webview/vitejs/plugin-react-6.0.2
dependabot/npm_and_yarn/webview/vite-8.0.13
dependabot/npm_and_yarn/webview/zustand-5.0.13
dependabot/npm_and_yarn/webview/types/node-25.9.1
dependabot/npm_and_yarn/webview/vitest-4.1.6
dependabot/github_actions/actions/setup-node-6
dependabot/github_actions/github/codeql-action-4
dependabot/github_actions/actions/checkout-6
dependabot/github_actions/actions/cache-5
dependabot/github_actions/pnpm/action-setup-6
feat/local-first-llm-routing
docs/local-first-llm-routing-spec
fix/v0.2-wave-1-code-fixes
docs/v0.2-wave-1-doc-drift
docs/handoff-2026-05-14
docs/multi-runner-inventory
docs/ollama-baseline-58
fix/ci-env-harness-sqlite-voice-warmup
fix/ci-xcode-26-and-batcher-timing
chore/typecheck-blocking
fix/hud-typecheck-strict-undefined
wip/voice-log-menu-stash4
v0.1.0-dev.71
v0.1.0-dev.68
v0.1.0-dev.64
v0.1.0-dev.50
Labels
Clear labels
area:agent
area:build
area:bus
area:devtool
area:hud
area:logging
area:mcp
area:memory
area:vision
area:voice
audit-finding
bug
carry-forward
comment-cleanup
dependencies
documentation
duplicate
enhancement
epic
good first issue
help wanted
invalid
javascript
migration
question
severity:critical
severity:high
severity:low
severity:medium
wontfix
Something isn't working
Comment / docstring cleanup per .planning/code-commenting-guide.md
Dependency updates
Improvements or additions to documentation
This issue or pull request already exists
New feature or request
Good for newcomers
Extra attention is needed
This doesn't seem right
Pull requests that update javascript code
Further information is requested
This will not be worked on
Milestone
No items
No Milestone
v0.1 — It actually works (basic capabilities)
Projects
Clear projects
No projects
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: KofTwentyTwo/Jarvis#13
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Replay log poisoned: synthetic
memory-trigger-<hash>turn_ids break ALL replay flushes since2026-05-12T18:48:47.211Z. Every replay batch fails withSQLITE_CONSTRAINT_FOREIGNKEY(code 19); ReplayLog re-buffers the poisoned batch and retries forever. At 3 consecutive failures it escalates to CRITICAL. Real turn events queued behind the poison are silently lost.Evidence
App/AppDelegate.swift:2783-2797(AppDelegateMemoryReplaySink.record(_:forTriggerTurnId:))packages/Replay/Sources/Replay/Schema.swift:15(PRAGMA foreign_keys=ON)packages/Replay/Sources/Replay/ReplayLog.swift:195-260(flushPendingbatch transaction)~/Library/Logs/Jarvis/replay.2026-05-12.logshows ~50+ chronic-failure entries withturn_ids=...,memory-trigger-7747877241524896942,batch_size=31growing,consecutive_failures=23+SELECT kind, COUNT(*) FROM events GROUP BY kindinreplay.sqliteshows zeromemory_mutationrows ever, despite 1 fact written todayRoot cause / hypothesis
MemoryStore.recordMemoryMutation(line 248-272) routes through the sink with a syntheticTurnID = "memory-trigger-7747877241524896942"(FNV hash formatted as string).replay.sqlite'sevents.turn_id REFERENCES turns(turn_id)is a real FK withforeign_keys=ON. No row inturnshas that synthetic id →SQLITE_CONSTRAINT_FOREIGNKEYon INSERT.flushPendingwraps the whole batch in one transaction, so the poisoned event takes every real event in the same batch down on rollback. Re-buffer logic doesn't filter; same poison gets retried forever.Recommended fix
Two layers, pick at least one:
Don't synthesize a fake turn_id. Thread the real triggering
TurnID(UUID) throughMemoryExtractionCoordinator→Orchestrator.process→applyOp→recordMemoryMutation. The orchestrator already hasjob.turnId— pass it through alongside the Int64 hash, use the real one when emitting to replay. OR add a sentinelturnsrow up-front for memory mutations (session_id = current,turn_id = "memory-system").Defensive batch-splitting in
ReplayLog.flushPending. When a batch fails, retry events individually so one poisoned row can't take 30 others with it. Bounds blast radius even if a new poisoned-id pathway sneaks in later.Layer 2 alone is the structural defense; layer 1 is the surgical fix.
Test
forTriggerTurnIdnot present inturns→ assert ReplayLog flush succeeds for the OTHER events in the batch and only the poisoned event is dropped/loggedReplayLogexposes consecutive-failure count toMemoryBootHealthProbeSource
.planning/audit-2026-05-12/memory-audit.md(2026-05-12) — finding M-2 CRITICALCross-references
MemoryReplaySink.recordis fire-and-forget; failures unobservable from MemoryStore (compounds visibility gap)facts.source_turn_idClosed by v0.1 cluster merges on 2026-05-13. Develop now at
a8c7f1a0.