Repository navigation
test: static schema-drift gate against the v1.8.0 setup.sql (GIT-109 step 2) - #46
Merged
1 commit merged intoSep 22, 2026
Merged
1 commit merged into
1 commit merged into
Conversation
…step 2) Customers never run SQL after initial setup, so every table and column gitmem touches must exist in the v1.8.0 schema or be deliberately guarded. - tests/helpers/schema-drift.ts parses setup.sql into table -> columns (CREATE TABLE, ALTER ... ADD COLUMN, views) and walks src/ with the TypeScript compiler API. It collects table + payload keys reaching directUpsert / directPatch / upsertRecord / storage.upsert, and select / filter / order keys reaching directQuery / directQueryAll / listRecords / getRecord. It follows getTableName(), const indirection, spreads, conditional spreads, later x.prop = assignments, local functions' returns and .map/.filter element shapes. Free-tier-only code is set aside; anything it cannot resolve is reported, never assumed fine. - tests/fixtures/schema/setup-v1.8.0.sql is the floor, byte-identical to `git show v1.8.0:schema/setup.sql`. - schema-drift.test.ts fails on a finding not allowlisted by ticket, a stale allowlist entry, an entry without a GIT-### ticket, a new unresolved call site, or a SESSION_COLUMNS entry v1.8.0 lacks that is not production-only. A synthetic source tree with planted drift proves the analyzer still catches it. First run: 74 call sites, 362 column accesses, 11 findings — 3 probe-guarded production-only columns (GIT-109) and 8 variant tables/columns reachable only on the dev tier (GIT-106). No other drift. +9 tests. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
A static gate: nothing
src/reads or writes may be missing from the v1.8.0setup.sqlunless it's allowlisted against the ticket that owns it (GIT-109 step 2).tests/helpers/schema-drift.tsdoes two things.setup.sqlinto table → columns, coveringCREATE TABLE,ALTER … ADD COLUMNand views.src/with the TypeScript compiler API, collecting:directUpsert,directPatch,upsertRecord,storage.upsert;select/ filter /orderkeys reachingdirectQuery,directQueryAll,listRecords,getRecord.It follows
getTableName("x"),constindirection, spreads and conditional spreads (...(ok && {col})), laterrow.col = …assignments, local functions'return {…}, and.map/.filterelement shapes. Code underif (!hasSupabase()), theelseofif (hasSupabase()), or a…Freefunction writes local JSON and is set aside. Anything it can't resolve is reported as unresolved, never assumed fine.tests/fixtures/schema/setup-v1.8.0.sql: the floor, byte-identical togit show v1.8.0:schema/setup.sql. Findings are labelled "added after 1.8.0" or "in no setup.sql" by comparing with the currentschema/setup.sql.tests/unit/schema-drift.test.tsfails on:GIT-###ticket;SESSION_COLUMNSentry that v1.8.0 lacks and that isn't production-only. That coverssession_close's payload, which is built dynamically.It also plants drift in a synthetic source tree every run, to prove the analyzer still catches each kind.
First run: everything it found
74 call sites, 362 column accesses; 7 free-tier-only sites set aside; 6 pass-through helpers (the table is a parameter:
storage.ts×3,store-columns.ts,supabase-client.ts×2; their callers are checked).11 findings, all in no
setup.sqlat all (none were added after 1.8.0):gitmem_learnings.archived_atarchive-learning.ts:132supportedColumns()finds itgitmem_sessions.claude_code_session_idsession-close.ts:1470filterToStoreSessionColumns()gitmem_sessions.task_observationsabsorb-observations.ts:75variant_assignments(table)variant-assignment.ts:100, 139hasVariants())variant_performance_metrics(table)recall.ts:607scar_enforcement_variants.activevariant-assignment.ts:69,variant-generation.ts:322scar_enforcement_variants.description,.enforcement_config,.variant_name,.variant_versionvariant-generation.ts:322Worth knowing:
setup.sqlcreatesscar_enforcement_variants, but with a different shape (variant_type, variant_config, metadata) from the one the code reads and writes. It's unreachable on pro and free (GIT-106), but if variants ever leave the dev tier, the table setup.sql provisions won't work with them.No other drift. Every other table and column reached from
src/exists in v1.8.0.Unresolved (5 sites; the test pins them, so a new one fails):
thread-supabase.ts:393, 433, 821: filters come frombuildScopedThreadQuery()in another file (thread-scope tests pin them);write-health.ts:72: loops overgetTableName("learnings" | "decisions")and selectsidonly;session-close.ts:1470:sessionDatais narrowed toSESSION_COLUMNS, which the last check compares with v1.8.0.All Release C branches scanned too (#37–#45): each has exactly the same 11 findings and no new unresolved sites. None of this release's fixes reaches a column a v1.8.0 store lacks.
How to test
npx vitest run tests/unit/schema-drift.test.ts: 9/9. Full suite 1283/1283 (+9).Negative control on real code: adding
drift_probe_column: 1tocreate_decision's payload fails the gate withgitmem_decisions.drift_probe_column [write] (in no setup.sql) at src/tools/create-decision.ts:87. Reverted.Venue: not applicable. This is a static test; nothing runs against a store.
Checklist
npm run test:unitpasses (1283)Breaking changes
None. Test only.
🤖 Generated with Claude Code