Implements task 473f65aa (Feature 02, task 3 of 4).
Done-condition: migrations/0001_init.sql creates every table in the CTXD data model (25 tables) with foreign keys, CHECK constraints for every enum column (dinners.status and notification_prefs.event rotation_review named), unique constraints on the eight named keys; tests assert each table exists, each enum CHECK rejects an invalid value, each unique constraint rejects a duplicate, and deleting a parent with children is refused. Go quality floor passes.
Evidence (developer-run, to be re-verified at review): gofmt -l . empty; go vet ./... clean; go test -race -count=1 ./... ok (internal/store 83 tests/subtests); CGO_ENABLED=0 go build ./... ok; real boot against a temp data dir recorded 0000_bootstrap,0001_init and 25 tables.
Implements task 473f65aa (Feature 02, task 3 of 4).
Done-condition: migrations/0001_init.sql creates every table in the CTXD data model (25 tables) with foreign keys, CHECK constraints for every enum column (dinners.status and notification_prefs.event rotation_review named), unique constraints on the eight named keys; tests assert each table exists, each enum CHECK rejects an invalid value, each unique constraint rejects a duplicate, and deleting a parent with children is refused. Go quality floor passes.
Evidence (developer-run, to be re-verified at review): gofmt -l . empty; go vet ./... clean; go test -race -count=1 ./... ok (internal/store 83 tests/subtests); CGO_ENABLED=0 go build ./... ok; real boot against a temp data dir recorded 0000_bootstrap,0001_init and 25 tables.
Base: feature/b9c21d67-...-sqlite-data-layer-and-schema (b06d168).
migrations/0001_init.sql creates the 25 tables of the CTXD CONTEXT.MD data
model with foreign keys (default NO ACTION, so a parent with children cannot
be deleted; ai_run_id references are ON DELETE SET NULL for the 30-day
ai_runs purge), a CHECK on every enum and boolean column, and the unique
constraints the model names. Single-row settings tables are pinned to id 1.
internal/store/schema_test.go migrates a temp database with the embedded
migrations and asserts every table exists, every enum CHECK rejects an
invalid value, every named unique constraint rejects a duplicate, and
deleting a parent with children is refused.
TestMigrateEmbeddedMigrations now expects 0000_bootstrap,0001_init, and the
upgrade test migrates a bootstrap-only database to the real embedded set.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
{"verdict":"CHANGES_REQUIRED","reviewed_sha":"50b670e0a81da7c0954693def9ed86e7d7b325d7","summary":"All 25 tables and the named unique constraints are present. The migration applies to a fresh SQLite database; gofmt, go vet, and go test -race -count=1 ./... pass. Three schema behaviors violate the stated requirements.","findings":[{"id":"F1","severity":"high","location":"migrations/0001_init.sql:137,159","failure_case":"An ai_runs row can be deleted while suggestion_batches or week_plans still reference it, contrary to the required refusal of parent deletion.","evidence":"Both foreign keys use ON DELETE SET NULL. An in-memory SQLite check deleted a referenced ai_runs row successfully and left the child reference NULL; TestSchemaAIRunPurgeClearsReferences explicitly expects this behavior.","suggested_correction":"Use a refusing foreign-key action for both references. Handle retention by explicitly resolving references before a purge, and test that a direct parent delete is refused."},{"id":"F2","severity":"medium","location":"migrations/0001_init.sql:66,267","failure_case":"SQLite accepts rows without an ID or notification event, including multiple notification_prefs rows with NULL events.","evidence":"These TEXT PRIMARY KEY columns lack NOT NULL. An in-memory SQLite check inserted a recipe with a NULL id and two notification_prefs rows with NULL event; the event CHECK and primary-key uniqueness did not reject them.","suggested_correction":"Add NOT NULL to TEXT primary keys, including notification_prefs.event, and test NULL rejection."},{"id":"F3","severity":"medium","location":"migrations/0001_init.sql:35-39","failure_case":"A fractional day of the week is accepted despite the intended integer values 0 through 6.","evidence":"The three weekday columns use BETWEEN 0 AND 6. SQLite accepted plan_draft_dow = 5.5 and stored it as REAL; the tests exercise only out-of-range integers.","suggested_correction":"Use CHECK (column IN (0, 1, 2, 3, 4, 5, 6)) for each weekday column and test a fractional value."},{"id":"F4","severity":"low","location":"internal/store/schema_test.go:373-406","failure_case":"The composite-unique tests would pass with some incorrect, narrower constraints, such as UNIQUE(date) in place of UNIQUE(plan_id, date).","evidence":"Each test checks a distinct pair and a duplicate pair, but does not verify that one component may repeat when the other differs.","suggested_correction":"Add positive cases for the same date under different plans, the same plan_date for different dinners, and the same event_key on different channels."}]}
Posted unaltered by review_agent. This is transport, not a second review.
## Independent review — Codex `gpt-6-sol`, reasoning high
Verdict: **CHANGES_REQUIRED**
Reviewed SHA: `50b670e0a81da7c0954693def9ed86e7d7b325d7`
```json
{
"verdict": "CHANGES_REQUIRED",
"reviewed_sha": "50b670e0a81da7c0954693def9ed86e7d7b325d7",
"summary": "All 25 tables and the named unique constraints are present. The migration applies to a fresh SQLite database; gofmt, go vet, and go test -race -count=1 ./... pass. Three schema behaviors violate the stated requirements.",
"findings": [
{
"id": "F1",
"severity": "high",
"location": "migrations/0001_init.sql:137,159",
"failure_case": "An ai_runs row can be deleted while suggestion_batches or week_plans still reference it, contrary to the required refusal of parent deletion.",
"evidence": "Both foreign keys use ON DELETE SET NULL. An in-memory SQLite check deleted a referenced ai_runs row successfully and left the child reference NULL; TestSchemaAIRunPurgeClearsReferences explicitly expects this behavior.",
"suggested_correction": "Use a refusing foreign-key action for both references. Handle retention by explicitly resolving references before a purge, and test that a direct parent delete is refused."
},
{
"id": "F2",
"severity": "medium",
"location": "migrations/0001_init.sql:66,267",
"failure_case": "SQLite accepts rows without an ID or notification event, including multiple notification_prefs rows with NULL events.",
"evidence": "These TEXT PRIMARY KEY columns lack NOT NULL. An in-memory SQLite check inserted a recipe with a NULL id and two notification_prefs rows with NULL event; the event CHECK and primary-key uniqueness did not reject them.",
"suggested_correction": "Add NOT NULL to TEXT primary keys, including notification_prefs.event, and test NULL rejection."
},
{
"id": "F3",
"severity": "medium",
"location": "migrations/0001_init.sql:35-39",
"failure_case": "A fractional day of the week is accepted despite the intended integer values 0 through 6.",
"evidence": "The three weekday columns use BETWEEN 0 AND 6. SQLite accepted plan_draft_dow = 5.5 and stored it as REAL; the tests exercise only out-of-range integers.",
"suggested_correction": "Use CHECK (column IN (0, 1, 2, 3, 4, 5, 6)) for each weekday column and test a fractional value."
},
{
"id": "F4",
"severity": "low",
"location": "internal/store/schema_test.go:373-406",
"failure_case": "The composite-unique tests would pass with some incorrect, narrower constraints, such as UNIQUE(date) in place of UNIQUE(plan_id, date).",
"evidence": "Each test checks a distinct pair and a duplicate pair, but does not verify that one component may repeat when the other differs.",
"suggested_correction": "Add positive cases for the same date under different plans, the same plan_date for different dinners, and the same event_key on different channels."
}
]
}
```
---
Posted unaltered by `review_agent`. This is transport, not a second review.
- ai_run_id in suggestion_batches and week_plans now uses the default
refusing action instead of ON DELETE SET NULL; the ai_runs purge must
clear references explicitly. Tested as a refused parent delete.
- Every TEXT primary key (including notification_prefs.event and
sessions.id_hash) is NOT NULL; tested that NULL keys are rejected.
- Weekday columns use CHECK (col IN (0, 1, 2, 3, 4, 5, 6)) so fractional
values are refused; tested with 5.5, 0.5 and 3.5.
- Composite UNIQUE tests add positive partial-overlap cases (same date
under different plans, same plan_date for different dinners, same
event_key on different channels, same period_key for different
schedules).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
{"verdict":"APPROVED","reviewed_sha":"7b760e87b1d9905460ccae10969d68fd0d7c8e4b","summary":"The migration creates all 25 required tables with the specified enum checks, unique constraints, and foreign keys. The tests exercise invalid values, duplicates, and refused parent deletes. The bootstrap migration and dependencies are unchanged; no database or secret file was added. gofmt, go vet, and go test -race -count=1 ./... passed.","findings":[]}
Posted unaltered by review_agent. This is transport, not a second review.
## Independent review — Codex `gpt-6-sol`, reasoning high
Verdict: **APPROVED**
Reviewed SHA: `7b760e87b1d9905460ccae10969d68fd0d7c8e4b`
```json
{
"verdict": "APPROVED",
"reviewed_sha": "7b760e87b1d9905460ccae10969d68fd0d7c8e4b",
"summary": "The migration creates all 25 required tables with the specified enum checks, unique constraints, and foreign keys. The tests exercise invalid values, duplicates, and refused parent deletes. The bootstrap migration and dependencies are unchanged; no database or secret file was added. gofmt, go vet, and go test -race -count=1 ./... passed.",
"findings": []
}
```
---
Posted unaltered by `review_agent`. This is transport, not a second review.
approver_agent
merged commit fa7c6b7218 into feature/b9c21d67-bf72-411a-901d-77e57352d398-sqlite-data-layer-and-schema2026-10-03 09:06:21 -04:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Implements task 473f65aa (Feature 02, task 3 of 4).
Done-condition: migrations/0001_init.sql creates every table in the CTXD data model (25 tables) with foreign keys, CHECK constraints for every enum column (dinners.status and notification_prefs.event rotation_review named), unique constraints on the eight named keys; tests assert each table exists, each enum CHECK rejects an invalid value, each unique constraint rejects a duplicate, and deleting a parent with children is refused. Go quality floor passes.
Evidence (developer-run, to be re-verified at review): gofmt -l . empty; go vet ./... clean; go test -race -count=1 ./... ok (internal/store 83 tests/subtests); CGO_ENABLED=0 go build ./... ok; real boot against a temp data dir recorded 0000_bootstrap,0001_init and 25 tables.
Base: feature/b9c21d67-...-sqlite-data-layer-and-schema (
b06d168).Independent review — Codex
gpt-6-sol, reasoning highVerdict: CHANGES_REQUIRED
Reviewed SHA:
50b670e0a81da7c0954693def9ed86e7d7b325d7Posted unaltered by
review_agent. This is transport, not a second review.Independent review — Codex
gpt-6-sol, reasoning highVerdict: APPROVED
Reviewed SHA:
7b760e87b1d9905460ccae10969d68fd0d7c8e4bPosted unaltered by
review_agent. This is transport, not a second review.