Repository navigation
feat(sqlite): store procedural skills on the default backend (#596) - #598
Conversation
procedural_skills existed only on PostgreSQL, so on SQLite the session-end writer mined its skills and lost every one to an AttributeError its caller swallows, leaving recall_skills permanently empty on the backend plugin installs, .mcpb and Cowork use. Checked at runtime before the fix: SqliteMemoryStore had neither upsert_procedural_skill nor get_procedural_skills. sqlite_schema_procedural.py mirrors the PostgreSQL columns with SQLite's spellings and joins get_all_ddl, so an existing database picks the table up on its next open through CREATE TABLE IF NOT EXISTS. sqlite_store_procedural.SqliteProceduralMixin implements the two operations with the same shapes the handlers read, the row id back from the upsert and is_habitual as a bool (ADR-1075). The I2 invariant's allow-list moves three sqlite_store.py line numbers by four: the new import shifted them, the writers themselves are untouched. Five new tests, all failing on the previous code, including the end-to-end writer path. Full suite: 8741 passed, 8 skipped. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01Cz7A6goxVzfKL9NT7k4zDH
|
ZETETIC-REVIEW: APPROVE SummaryPR #598 (commit 73383d0) adds Stakes calibration
1. Column-level and behavioural parity
Upsert return type: both return
Non-blocking: 2. Upgrade path, proved empiricallyBuilt a store with origin/main's code (10b98d0, same commit as the Reopened the same file with this branch's code (no schema wipe):
3. Upsert commit/read-back safety
Two-process race: since 4. I2 allow-list shiftRead 5. Test strength, mutation testing (all three caught, tree restored clean)Applied and reverted individually against
All three fired as expected; 6. Gates
File sizes: 7. Accuracy of PR body / ADR-1075 / CHANGELOG claims
Layer check (Move 1)
No handler/core file imports infrastructure directly in this diff; wiring is entirely inside the infrastructure layer, consistent with SOLID audit (Move 2)
Wiring & contract drift (Move 3)
Complexity & structure (Move 5)Both new files (38, 79 lines) are well under the 50-line/function, 300-line-smell, 500-line-cap thresholds. No smells. Security & hygiene (Move 6)
Move 0, Ledger reconciliation and seen-defect check
IssuesBlockingNone. Non-blocking
Hand-offsNone, no root-cause rework, no structural decomposition question, no threat-model surface, no unverified perf claim. Commands run |
|
Follow-up: the full local Matches the PR body's claim exactly. No failures. This does not change the verdict, APPROVE stands. |
The Protocol's docstring still said "(PG-only)", which this branch makes false. It now states that both backends implement the capability since ADR-1075 and why the Protocol remains: the handler is written against the capability, not against a store. ADR-0433 keeps the original line as preserved evidence and is left untouched, like every other historical quotation under docs/adr. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01Cz7A6goxVzfKL9NT7k4zDH
|
ZETETIC-REVIEW: APPROVE Re-verification at head 291c1edRe-reviewed after the prior APPROVE (73383d0). Verdict is unchanged: APPROVE. What changed
Verified independently
Carried forward from the 73383d0 reviewEverything verified at 73383d0 still holds: column/behavioural parity with PostgreSQL, the empirically-proved upgrade path for an existing SQLite database, upsert commit/read-back safety, the I2 allow-list shift matching the same three writers, three mutation-testing kills (DDL omission, missing bool cast, missing ON CONFLICT), and a full local IssuesBlockingNone. Non-blockingNone remaining; the one nit from the prior review is resolved by this commit. VerdictAPPROVE. |
Summary
procedural_skillsexisted only on PostgreSQL:pg_schema.pydeclares the table (ADR-0558) andpg_store_procedural.PgProceduralMixinimplements its two operations, with nothing of the kind on the SQLite side. Checked at runtime against a store built through the real composition root,SqliteMemoryStorehad neitherupsert_procedural_skillnorget_procedural_skills.procedural_skill_writer.maybe_mine_skillscalls the upsert for every mined skill inside atrywhoseexcept Exceptionreturns{"status": "error"}. So on SQLite the mining ran, produced its skills, and lost each one to anAttributeErrornobody reads. SQLite is the default backend for plugin installs,.mcpband Cowork (PRIVACY.md lines 26-38), and the README advertises all 54 tools as working on both backends, which made that claim false forrecall_skills.The fix mirrors the PostgreSQL columns with SQLite's spellings in
sqlite_schema_procedural.py, joined intoget_all_ddlso an existing database picks the table up on its next open, and implements the two operations insqlite_store_procedural.SqliteProceduralMixinwith the shapes the handlers read: the row id back from the upsert,is_habitualas a bool (ADR-1075).Closes #596
Type of change
Test plan
tests_py/infrastructure/test_sqlite_procedural.py: the two operations present on the default store, a round trip including the boolean and the timestamp, the upsert updating in place rather than duplicating, the proficiency floor filtering, and the end-to-endmaybe_mine_skillspath persisting what mining produced. All five fail on the previous code.ruff check,ruff format --check: clean.pyright mcp_server/: 0 errors.scripts/check_craftsmanship.py --base origin/main: OK.scripts/check_doc_claims.py: OK.Audit notes
sqlite_store.pyline numbers by four. The new import shifted them; the heat writers themselves are untouched, which the test's own failure message asks the author to confirm.MIGRATIONSadds columns to existing tables, and this is a new table created byCREATE TABLE IF NOT EXISTSon open.Coding-standards compliance
Breaking changes
None. The table is new on SQLite and unchanged on PostgreSQL.
Reviewer checklist
🤖 Generated with Claude Code
https://claude.ai/code/session_01Cz7A6goxVzfKL9NT7k4zDH