Files
yellowjacket/.planning/milestones/v1.0-phases/03-test-infrastructure/03-01-PLAN.md
T
yonlu 6ce0661fca chore: complete v1.0 Consolidation milestone
Archive milestone artifacts:
- milestones/v1.0-ROADMAP.md (full roadmap archive)
- milestones/v1.0-REQUIREMENTS.md (26/26 requirements complete)
- milestones/v1.0-phases/ (8 phase directories with plans, summaries, verifications)

Updated:
- PROJECT.md: full evolution review, all consolidation requirements validated
- ROADMAP.md: collapsed to milestone summary with archive link
- STATE.md: reset for next milestone
- MILESTONES.md: created with stats and accomplishments
- RETROSPECTIVE.md: created with lessons learned

Deleted:
- REQUIREMENTS.md (archived, fresh for next milestone)

8 phases, 17 plans, 34 tasks, 84 tests added, 6 days
2026-03-05 09:34:43 -05:00

8.9 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
phase plan type wave depends_on files_modified autonomous requirements must_haves
03-test-infrastructure 01 execute 1
backend/database/database.go
backend/database/testhelper.go
true
TEST-01
PERF-04
truths artifacts key_links
Production SQLite connection applies synchronous=NORMAL, cache_size=-8000, and mmap_size=67108864 PRAGMAs at database open
NewTestDB(t) returns a clean in-memory SQLite DB with the same migrations and PRAGMAs as production NewDB()
Each test gets an isolated database instance — no shared state between test functions
Tests using NewTestDB pass with -race flag enabled
path provides contains
backend/database/database.go Shared applyPRAGMAs function + production PRAGMA application in NewDB applyPRAGMAs
path provides exports
backend/database/testhelper.go NewTestDB test helper for in-memory SQLite with production-mirror setup
NewTestDB
from to via pattern
backend/database/testhelper.go backend/database/database.go shared applyPRAGMAs function applyPRAGMAs(
from to via pattern
backend/database/testhelper.go backend/database/database.go shared schema application (schemas embed + runMigrations) schemas.ReadDir|runMigrations
Create a production-mirroring SQLite test helper and apply performance PRAGMAs to the production database connection.

Purpose: Establish the test foundation that all subsequent test phases (4-5) depend on. Tests need real database instances with identical configuration to production — same PRAGMAs, same migrations, same constraints — so test results are trustworthy.

Output: Modified database.go with shared PRAGMA function + production PRAGMAs applied, and new testhelper.go with NewTestDB(t).

<execution_context> @/home/caleb/.config/opencode/get-shit-done/workflows/execute-plan.md @/home/caleb/.config/opencode/get-shit-done/templates/summary.md </execution_context>

@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md

@backend/database/database.go

From backend/database/database.go:

// DB wraps the SQLite database connection and queries.
type DB struct {
    db      *sql.DB
    Ctx     context.Context
    Queries *sqlcgen.Queries
    logger  *slog.Logger
}

// NewDB opens the database and applies schema migrations.
func NewDB(logger *slog.Logger) (*DB, error)

// BeginTx starts a new database transaction.
func (d *DB) BeginTx() (*sql.Tx, error)

// ExecContext executes a query without returning any rows.
func (d *DB) ExecContext(query string, args ...any) (sql.Result, error)

// QueryContext executes a query that returns rows.
func (d *DB) QueryContext(query string, args ...any) (*sql.Rows, error)

From backend/database/database.go (internal):

//go:embed sql/schemas/*.sql
var schemas embed.FS

func runMigrations(ctx context.Context, db *sql.DB, logger *slog.Logger) error
func isDuplicateColumnErr(err error) bool
Task 1: Extract shared applyPRAGMAs and add production PRAGMAs to NewDB backend/database/database.go In `backend/database/database.go`:
  1. Create an unexported applyPRAGMAs(ctx context.Context, db *sql.DB) error function that executes these PRAGMAs in order:

    • PRAGMA foreign_keys = ON (already exists in NewDB — extract it)
    • PRAGMA synchronous = NORMAL
    • PRAGMA cache_size = -8000
    • PRAGMA mmap_size = 67108864

    Use a slice of PRAGMA strings and loop over them with db.ExecContext. Wrap errors with fmt.Errorf("could not apply PRAGMA %q: %w", pragma, err).

  2. Modify NewDB() to call applyPRAGMAs(dbCtx, db) instead of the inline PRAGMA foreign_keys = ON exec. Insert the call right after db.SetMaxOpenConns(1) — PRAGMAs before schema creation, per CONTEXT.md decision.

  3. Remove the standalone foreign_keys PRAGMA block that currently exists in NewDB() (lines 58-65) since it's now handled by applyPRAGMAs.

  4. Add a doc comment on applyPRAGMAs: // applyPRAGMAs configures SQLite connection settings. Called by both NewDB and NewTestDB to ensure identical behavior.

Follow existing conventions: error wrapping with fmt.Errorf, blank line after early returns (nlreturn), keep lines under 100 chars (golines). cd /mnt/vault/dev/golang/yellowjacket && go build -tags webkit2_41 ./backend/database/ && go vet -tags webkit2_41 ./backend/database/

  • applyPRAGMAs function exists in database.go with all 4 PRAGMAs (foreign_keys, synchronous, cache_size, mmap_size)
  • NewDB() calls applyPRAGMAs instead of inline foreign_keys PRAGMA
  • Package compiles and passes vet
Task 2: Create NewTestDB helper in testhelper.go backend/database/testhelper.go Create `backend/database/testhelper.go` with:
  1. Package declaration: package database

  2. Imports: context, database/sql, fmt, io/fs, log/slog, path, testing, modernc.org/sqlite (blank import for driver), and yellowjacket/backend/database/sql/sqlcgen.

  3. Exported function NewTestDB(t *testing.T) *DB:

    • Call t.Helper() at the start
    • Open in-memory SQLite: sql.Open("sqlite", ":memory:?_busy_timeout=5000&_journal_mode=WAL")
    • If open fails, t.Fatalf("could not open test database: %v", err)
    • db.SetMaxOpenConns(1) — same as production
    • Create context: ctx := t.Context() (use t.Context() per usetesting linter)
    • Call applyPRAGMAs(ctx, db) — if error, t.Fatalf("could not apply PRAGMAs: %v", err)
    • Apply schemas: iterate schemas.ReadDir("sql/schemas"), read each .sql file, db.ExecContext(ctx, string(sqlContent)) — mirror the exact loop from NewDB(). If error, t.Fatalf.
    • Call runMigrations(ctx, db, slog.Default()) — if error, t.Fatalf("could not run migrations: %v", err)
    • Do NOT run orphan cleanup query (CONTEXT.md decision: "test DBs start empty, no orphans to clean")
    • Create queries: queries := sqlcgen.New(db)
    • Register cleanup: t.Cleanup(func() { db.Close() })
    • Return &DB{db: db, Ctx: ctx, Queries: queries, logger: slog.Default()}
  4. Add doc comment: // NewTestDB returns an in-memory SQLite database that mirrors the production setup (PRAGMAs + all migrations). The database is automatically closed when the test completes via t.Cleanup.

Note: Do NOT expose raw *sql.DB — tests use DB.ExecContext() / DB.Queries like production code (per CONTEXT.md decision). No functional options. No error return — failures are fatal via t.Fatalf.

Follow conventions: t.Helper(), t.Context(), blank import comment, doc comments ending with period, nlreturn spacing. cd /mnt/vault/dev/golang/yellowjacket && go build -tags webkit2_41 ./backend/database/ && go vet -tags webkit2_41 ./backend/database/ && go test -tags webkit2_41 -race -count=1 -run TestNewTestDB ./backend/database/ 2>&1 || echo "No test yet — build+vet passed"

  • backend/database/testhelper.go exists with exported NewTestDB(t *testing.T) *DB
  • Function opens :memory: DB, applies PRAGMAs via shared applyPRAGMAs, applies schemas, runs migrations
  • No orphan cleanup, no health check, no error return, no functional options
  • Cleanup registered via t.Cleanup()
  • Package compiles, passes vet, and passes -race flag
After both tasks complete, run the full verification:
# 1. Build the database package
go build -tags webkit2_41 ./backend/database/

# 2. Vet the database package
go vet -tags webkit2_41 ./backend/database/

# 3. Run all existing tests with race detector to confirm no regressions
make test

# 4. Verify applyPRAGMAs is called from both NewDB and NewTestDB
grep -n "applyPRAGMAs" backend/database/database.go backend/database/testhelper.go

# 5. Verify production PRAGMAs are all present
grep -c "PRAGMA" backend/database/database.go

<success_criteria>

  1. backend/database/database.go has a shared applyPRAGMAs function with all 4 PRAGMAs
  2. NewDB() calls applyPRAGMAs (no more inline foreign_keys PRAGMA)
  3. backend/database/testhelper.go exports NewTestDB(t *testing.T) *DB
  4. NewTestDB uses :memory: with same connection params, calls applyPRAGMAs + schema loop + runMigrations
  5. NewTestDB registers t.Cleanup(func() { db.Close() })
  6. make test passes (all existing tests green, race detector clean)
  7. No orphan cleanup in NewTestDB, no health check, no functional options </success_criteria>
After completion, create `.planning/phases/03-test-infrastructure/03-01-SUMMARY.md`