mirror of
https://github.com/thedotmack/claude-mem.git
synced 2026-09-20 04:23:02 +08:00
0b8288bf7c
* test(sqlite): pin the #3378 background-init FK abort to the v7/v9 rebuild copies (red)
Pin-down proof on unfixed code: a legacy v4-era DB seeded (with
PRAGMA foreign_keys = OFF, mimicking historical data) with a child row
whose memory_session_id has no sdk_sessions parent aborts the
SessionStore constructor migration chain:
- orphaned observation -> SQLiteError: FOREIGN KEY constraint failed
at makeObservationsTextNullable (SessionStore.ts:1167), the
INSERT INTO observations_new SELECT copy; committed schema_versions
stop at [4,5,6,7,8], v9 absent.
- orphaned session_summary -> same error at
removeSessionSummariesUniqueConstraint (SessionStore.ts:1074), the
INSERT INTO session_summaries_new SELECT copy; committed
schema_versions stop at [4,5,6], v7 absent.
These two child-table rebuilds run with foreign_keys = ON (set per
connection in connection.ts:45) and, unlike the v21/v33/v34 rebuilds,
never disable it - so each orphaned row makes the copy INSERT violate
the freshly created FK, dbManager.initialize() rejects, and the worker
never reports ready. runOneTimeV12_4_3Cleanup cannot be the aborting
step: it swallows its own errors (CleanupV12_4_3.ts:70-76).
This test asserts the desired post-fix behavior (constructor completes,
orphans survive, stub parents created) and currently fails 4/4 with the
FK error above.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RSNZmfi4vSYjTeEWtwqKrW
* fix(worker): repair orphaned FK parents before migration rebuilds; adoption after db init (#3378)
Three root-cause fixes for the background-init half of #3378 (the
recycle-loop half shipped in 13.12.3 as 906ffe37b):
1. FK abort (pinned by the red test in the previous commit): the v7 and
v9 child-table rebuilds (removeSessionSummariesUniqueConstraint,
makeObservationsTextNullable) copy rows via INSERT ... SELECT with
foreign_keys = ON, so one legacy orphaned child row (a
memory_session_id with no sdk_sessions parent) threw 'FOREIGN KEY
constraint failed', aborted the constructor migration chain, and the
worker never reported ready. Orphaned rows are live user data served
by context injection - the missing side is the parent. New
repairOrphanedSessionParents() creates a minimal completed stub
session per orphaned memory_session_id immediately before each copy,
mirroring SyncApply.ensureSessionForMemoryId
(INSERT ... ON CONFLICT DO NOTHING). No child rows are deleted.
2. 'errors=[object Object]': adoption.errors
(Array<{worktree, error}>) was passed as a logger CONTEXT value,
which logger.ts renders with a template literal. New
formatAdoptionErrors() serializes it to
'<worktree>: <error>; ...' at the log site.
3. 'database is locked' at boot: the fire-and-forget adoption kick
started before dbManager.initialize(), racing the boot migration
writer for the single WAL writer slot through its own connection.
The kick now starts after dbManager.initialize() and the one-time
v12.4.3 cleanup; it stays fire-and-forget, only its start moved.
The ready-flag fail-fast gating in initializeBackground is unchanged;
no retry loops or busy_timeout changes - the lock fix is ordering.
Closes the FK-abort half of #3378.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RSNZmfi4vSYjTeEWtwqKrW
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>