@@ -194,15 +194,9 @@ and this assessment both get updated as each slice lands.
194194
195195---
196196
197- ## What was actually changed in this pass (Phase 0, minimal slice)
197+ ## What was actually changed
198198
199- Per the brief's own closing instruction — "implement only Phase 0 and the
200- smallest vertical slice of Phase 1 unless the evidence shows another first
201- slice is safer" — the evidence above (no profiled bottleneck on any P0
202- non-persistence item, and persistence's own Phase 1 being a multi-day,
203- high-risk, schema-migrating undertaking that cannot be safely finished and
204- verified in one pass) points to * not* starting Phase 1 at all yet. What
205- shipped alongside this document:
199+ ### Phase 0
206200
2072011 . ** ` docs/ARCHITECTURE.md ` reconciled** — its native-addon section
208202 described download-only; corrected to include the datastore/audit
@@ -214,21 +208,68 @@ shipped alongside this document:
214208 into a single "unavailable, fall back" boolean. ` getNativeCapabilityReport() `
215209 now inspects the thrown error and reports which of those it actually
216210 was, purely for diagnostics/logging — every existing fallback behavior
217- is unchanged.
211+ is unchanged. New shared module: ` app/src/native-capability.ts ` .
212+ 3 . ** CI's ` rust ` job now builds and load-verifies the addon on Windows and
213+ macOS, not just Linux** — previously flagged here as a real, unverified
214+ gap. ` .github/workflows/ci.yml ` 's ` rust ` job gained a 3-OS matrix; fmt
215+ and clippy still run once (Rust source is OS-independent), but `cargo
216+ build` , ` cargo test` , a real ` napi build` , and a ` require()` + exports
217+ check now run on every platform. Verified locally on Linux (the one
218+ platform this sandbox can run); Windows/macOS are verified for real by
219+ GitHub's own runners on the next push, which is the actual point — this
220+ sandbox was never going to be able to confirm those two itself.
221+
222+ ### Phase 1 — smallest vertical slice
223+
224+ An inert SQLite scaffold for audit events: ` lib/src/store/audit.rs `
225+ (` rusqlite ` , bundled SQLite, WAL mode, a ` schema_version ` table, an
226+ ` audit_events ` table, and ` open ` /` migrate-from-JSON ` /` count ` /` verify `
227+ functions), exposed via N-API, with a TypeScript bridge
228+ (` app/src/native-sqlite-store.ts ` ). ** Deliberately not wired into
229+ ` audit-log-store.ts ` 's live read/write path** — nothing in the running app
230+ calls this yet; it exists to prove the pattern (schema versioning,
231+ idempotent migration-from-JSON safe to rerun, transactional batch inserts,
232+ ` PRAGMA integrity_check ` -based corruption detection) works end-to-end
233+ through the real built addon before committing to an actual cutover, per
234+ the brief's own rollback requirement (ship behind a flag, default off).
235+
236+ 9 new Rust tests (idempotent open, schema-version-recorded-once, WAL-mode
237+ active, migration correctness/idempotency/partial-rerun/no-duplicate-rows,
238+ a rejected malformed batch leaving zero rows behind — one bad event fails
239+ the whole transaction rather than partially migrating), 5 new TypeScript
240+ tests (full round trip through the actual built ` .node ` addon, rejected
241+ malformed batch, and the addon-unavailable throw path), all verified via
242+ the real built binary (` npm run build:debug ` + a ` require() ` smoke test),
243+ not just ` cargo test ` .
244+
245+ ** A real build-infrastructure finding surfaced by adding this:** `cargo
246+ test` started failing to link at all (not just for the new module — for
247+ the * entire* crate, including previously-passing tests) once ` rusqlite `
248+ was added, with undefined references to ` napi_reference_unref ` /
249+ ` napi_delete_reference ` / ` napi_call_threadsafe_function ` . These are napi's
250+ own C-ABI symbols, normally supplied by the Node process that loads a
251+ ` .node ` addon at runtime — a standalone ` cargo test ` binary has no Node
252+ process to supply them, and this crate's ` napi ` dependency had
253+ ` default-features = false ` without napi's own ` dyn-symbols ` feature (which
254+ resolves those symbols dynamically instead of requiring them at static
255+ link time, and is part of napi's * default* feature set — this crate had
256+ just never turned it on, and the existing code path apparently never
257+ triggered the linker into demanding those symbols before). Fix: added
258+ ` dyn-symbols ` to the ` napi ` dependency's feature list in ` lib/Cargo.toml ` .
259+ Re-verified after the fix that the real built addon still loads correctly
260+ under Node (it does — see the smoke test above); this is a supported,
261+ recommended napi-rs configuration, not a workaround.
218262
219263** Explicitly not done, with reasons, per "stop and document the blocker"
220264rather than half-finish:**
221265
222- - Multi-platform CI build/load jobs — this sandbox has no Windows/macOS
223- runner access; the CI YAML change itself would be easy, but "add a job"
224- without being able to verify it actually builds and loads the addon
225- there is exactly the kind of unverified change this brief says not to
226- ship.
227- - Any Phase 1+ code (SQLite store, crypto vault, RAG index, filesystem
228- capability layer, process supervisor, system-inspection rewrite,
229- ingestion, safety-scanning engine, recommender inference) — none of it
230- was started. Each is a substantial, independently-scoped project per the
231- brief's own phase breakdown; starting one without the characterization
232- tests, benchmarks, and migration/rollback machinery the brief itself
233- requires first would produce exactly the "half-migrated" state the brief
234- says to avoid.
266+ - Actually cutting ` audit-log-store.ts ` over to the SQLite store, or
267+ migrating any other store (patient cases, sessions, evidence, model
268+ registry). The scaffold above is the foundation that cutover would use,
269+ not the cutover itself — flipping the live read/write path needs the
270+ three-way native/fallback/new-store comparison and feature-flag rollout
271+ described in §6, which is real, separately-scoped work.
272+ - Crypto vault, RAG index, filesystem capability layer, process supervisor,
273+ system-inspection rewrite, ingestion, safety-scanning engine, recommender
274+ inference — none started. Each is a substantial, independently-scoped
275+ project per the brief's own phase breakdown.
0 commit comments