Files
Jarvis/packages/Replay/Package.swift
james.maesandClaude Opus 4.7 cb584a2ac8 feat(d5d6): real memory database — vec0 statically linked, hard-fail boot, stats tool
Closes D-5 / D-6 (sqlite-vec dylib bundling) carry-forwards from the
2026-05-04 audit by adopting jkrukowski/SQLiteVec as a SPM dependency.
The package's CSQLiteVec target compiles sqlite3.c + sqlite-vec.c into
one statically-linked C target with `core_vec_init()` registering vec0
as an auto-extension. All sqlite3_* calls in Replay's SQLiteConnection
and Memory's MemoryStore resolve to this bundled SQLite (vec0 always
available) instead of Apple's stripped /usr/lib/libsqlite3.dylib.

The retired hand-rolled approach (dlsym pathway + JARVIS_VEC0_STUB_PATH
env-flag + Bundle.module placeholder text file) never worked on macOS
because Apple stripped sqlite3_load_extension from the system libsqlite3.
Memory init has been silently dormant since Phase 7 (2026-04 onward),
which is what made B-02 (history threading) appear permanently broken
to the user during dogfooding even after the 48ad8d6 tactical patch
landed.

Live verification 2026-05-11: fresh launch with empty jarvis.db creates
schema, persists turn rows across submits, B-02 multi-turn context
resolves correctly ("what breed is Toby?" → "Golden Retriever" after
prior turn established Toby is a Golden Retriever), and the new
get_memory_stats tool reports `turnsCount=6, vecVersion=v0.1.6,
sqliteVersion=3.51.0`.

Changes:

- packages/Replay/Package.swift
    + SQLiteVec SPM dependency (from: "0.0.14")
    + CSQLiteVec product wired into Replay target
- packages/Replay/Sources/Replay/SQLiteConnection.swift
    - import SQLite3
    + @_exported import CSQLiteVec
    All sqlite3_* call sites unchanged — linker now resolves to our
    bundled sqlite3 with vec0 statically linked in.
- packages/Memory/Package.swift
    + SQLiteVec SPM dependency (named product so MemoryStore can import
      CSQLiteVec directly for the core_vec_init() one-shot call)
    - resources: PLACEHOLDER.txt copy (defunct vec0.dylib stub slot)
- packages/Memory/Sources/Memory/MemoryStore.swift
    - import SQLite3 → import CSQLiteVec
    + _vecAutoExtensionRegistered static-let one-shot: calls
      CSQLiteVec.core_vec_init() which registers vec0 via
      sqlite3_auto_extension on the first MemoryStore construction.
      Idempotent (static-let initializer fires exactly once).
    - loadVecExtension(on:) dlsym/JARVIS_VEC0_STUB_PATH/Bundle.module
      pathway (retired; ~70 lines removed)
    Updated docstring to reflect the new hard-fail boot policy.
- packages/Memory/Sources/Memory/Resources/PLACEHOLDER.txt — deleted
- App/AppDelegate.swift installMemory()
    Reverses Track-D D-1 (75a10be, 2026-05-04): MemoryStore.init failures
    are now FATAL via Logger.critical + TCCAlertService.presentHardBlock
    + NSApp.terminate. The graceful-degradation path that kept the app
    booting with memoryStore=nil hid the entire B-02/B-04/B-05 silent-
    failure bug class. Aligns with the 2026-05-07 API-first pivot
    thesis: "no silent failures".
    `store` is now non-optional throughout installMemory; downstream
    callers no longer need `if let store = store`.
- packages/MCP/Sources/MCP/InProcess/GetMemoryStatsTool.swift (new)
    + MemoryStatsDispatching protocol
    + MemoryStats Codable struct (turnsCount, factsTotal, factsActive,
      sessionsCount, dbFileBytes, vecVersion, sqliteVersion,
      lastTurnAtUnixMs, lastFactAtUnixMs)
    + GetMemoryStatsTool conforming to InProcessTool
- App/MCP/InProcessMemoryAdapters.swift
    + MemoryStatsStoreAdapter — bridges the protocol to MemoryStore's
      public queryRowCount / querySingleString seams and FileManager
      for the on-disk file size. Read-only, no confirmation.
- App/AppDelegate.swift installSelfKnowledgeTools()
    + Registers GetMemoryStatsTool with MemoryStatsStoreAdapter.
- packages/Memory/Tests/MemoryTests/*
    Retired the JARVIS_VEC0_STUB_PATH XCTSkipUnless guards from 9 tests
    (vec0 is always available now — no need to env-gate). Rewrote
    MemoryStoreTests to drop the now-impossible "init throws when vec
    missing" case and assert facts_vec virtual table creation +
    vec_version() readback. Added seedTurnRow helper to
    MemoryStoreApplyOpTests so the now-enforced
    `facts.source_turn_id REFERENCES turns(id)` foreign key is honored
    in tests that previously passed when FK enforcement was dormant.

Test summary: Memory full suite 91 tests, 10 skipped (env-gated real-
Ollama tests), 0 failures. App target builds clean. Substrate verified
end-to-end via live launch (vec_version: v0.1.6 logged at boot;
get_memory_stats returns actual schema row counts).

Pending D-7 carry-forward: ollama pull nomic-embed-text (~270MB) for
embedder; user already has qwen2.5-coder:32b-instruct-q8_0 which is
a higher-quality variant of the project's hardcoded
qwen2.5-coder:32b — small ModelID config delta to follow.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-11 10:25:56 -05:00

58 lines
2.7 KiB
Swift

// swift-tools-version:6.0
import PackageDescription
let package = Package(
name: "Replay",
// Plan 09-02 cascade — bumped from v13 to v14 because Replay's AgentCore
// dependency now transitively pulls JarvisVision (macOS 14). Project
// deployment target has always been macOS 14; v13 here was stale.
platforms: [.macOS(.v14)],
products: [
.library(name: "Replay", targets: ["Replay"]),
],
dependencies: [
.package(path: "../AgentCore"),
.package(path: "../Logging"),
.package(path: "../Config"),
// Plan 05-05 deviation (Rule 3, blocking): Replay sources `import
// Logging` (swift-log Logger) directly but the package never
// declared swift-log as an explicit dep. SPM tolerated this via
// transitive visibility through JarvisLogging; the Xcode
// framework linker is stricter. Adding the explicit dep so
// Replay.framework links cleanly when consumed by App target.
.package(url: "https://github.com/apple/swift-log.git", from: "1.5.0"),
// D-5/D-6 closure (2026-05-11): retire the hand-rolled extension-
// loading dlsym pathway. jkrukowski/SQLiteVec ships `CSQLiteVec`
// which compiles sqlite3.c + sqlite-vec.c + an `extinit.c` glue
// (`core_vec_init` → `sqlite3_auto_extension(sqlite3_vec_init)`)
// into one static-linked C target. SQLiteConnection imports
// CSQLiteVec instead of the SDK's `SQLite3.tbd`, so all our
// `sqlite3_*` calls resolve to a SQLite that has vec0 built in.
// Apple's stripping of `sqlite3_load_extension` is irrelevant —
// no runtime extension loading is needed. License: MIT.
.package(url: "https://github.com/jkrukowski/SQLiteVec.git", from: "0.0.14"),
],
targets: [
.target(
name: "Replay",
dependencies: [
.product(name: "AgentCore", package: "AgentCore"),
.product(name: "JarvisLogging", package: "Logging"),
.product(name: "Config", package: "Config"),
.product(name: "Logging", package: "swift-log"),
// D-5/D-6: SQLite + vec0 statically linked together.
// Replay's SQLiteConnection.swift imports CSQLiteVec instead of
// SQLite3, so every consumer of Replay (Memory, App target)
// automatically uses the vec0-bundled sqlite3 build.
.product(name: "CSQLiteVec", package: "SQLiteVec"),
],
swiftSettings: [.swiftLanguageMode(.v6)]
),
.testTarget(
name: "ReplayTests",
dependencies: ["Replay"],
swiftSettings: [.swiftLanguageMode(.v6)]
),
]
)