Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Pipeline Plan 17

Seth Ford edited this page Feb 12, 2026 · 4 revisions

The plan file is in a sensitive directory. Let me present the plan directly instead.


Implementation Plan: SQLite Persistence Layer for Team State

Summary

Add a SQLite database at ~/.shipwright/shipwright.db to replace JSON file-based state management. The dashboard server (Bun/TypeScript) uses bun:sqlite as the primary interface, while bash scripts use the sqlite3 CLI. Dual-write to both SQLite and existing JSONL/JSON files ensures backward compatibility.


Files to Modify

New Files

File Purpose
scripts/lib/migrations/001_initial_schema.sql Initial table definitions (8 tables, 15 indexes)
scripts/lib/db.sh Bash SQLite helper library (query, insert, migrate)
scripts/sw-db.sh CLI subcommand: shipwright db migrate|status|import|export
scripts/sw-db-test.sh Test suite for SQLite persistence layer
dashboard/db.ts TypeScript SQLite module using bun:sqlite

Modified Files

File Change
scripts/lib/helpers.sh Add SQLite dual-write in emit_event()
scripts/sw-cost.sh Add SQLite insert in cost_record()
scripts/sw-daemon.sh Write pipeline_run lifecycle to SQLite
scripts/sw-memory.sh Write failures/decisions to SQLite
dashboard/server.ts Replace file-based reads with SQL queries, with fallback
scripts/sw Add db subcommand routing
package.json Add sw-db-test.sh to test chain

Implementation Steps

Step 1: Schema (scripts/lib/migrations/001_initial_schema.sql)

8 tables with proper indexes:

  • schema_version — migration tracking (version PK, applied_at, description)
  • events — mirrors events.jsonl (type, ts_epoch, issue, stage, result, duration_s, cost_usd, model, extra TEXT for JSON overflow). Indexes on type, ts_epoch, issue, compound (type+ts_epoch)
  • pipeline_runs — denormalized runs (issue, branch, template, status, started/completed epochs, duration_s, pr_url, worktree_path). Indexes on status, issue, started_epoch
  • pipeline_stages — stage completions (run_id FK, stage, status, duration_s, cost_usd)
  • sessions — developer/agent sessions (id TEXT PK, machine, heartbeat, daemon state, active_jobs JSON)
  • cost_entries — mirrors costs.json (tokens, model, stage, issue, cost_usd). Indexes on ts_epoch, model, issue
  • metrics — pre-computed snapshots (metric_name, value, period, period_start)
  • memory_entries — failures/decisions/patterns (repo_hash, entry_type, pattern, root_cause, frequency)

Step 2: Bash library (scripts/lib/db.sh)

Double-source-guarded library providing: sw_db_path(), sw_db_available(), sw_db_migrate(), sw_db_ensure(), sw_db_query(), sw_db_insert_event(), sw_db_insert_cost(), sw_db_insert_pipeline_run(), sw_db_update_pipeline_run(). WAL mode + 5s busy timeout. All Bash 3.2 compatible.

Step 3: CLI subcommand (scripts/sw-db.sh)

shipwright db migrate|status|import|export. The import command reads events.jsonl, costs.json, developer-registry.json, and memory files into SQLite for existing installations.

Step 4: TypeScript module (dashboard/db.ts)

ShipwrightDB class using bun:sqlite with: migration runner, event CRUD, pipeline queries, SQL-powered DORA metrics (calculateDoraGrades()), cost breakdowns/trends, paginated activity feed, stage performance, session management, memory queries.

Step 5–8: Wire dual-writes in bash scripts

  • helpers.sh emit_event() → SQLite write gated behind SW_SQLITE_ENABLED + command -v sqlite3, failures silently ignored
  • sw-cost.sh cost_record() → SQLite insert inside flock section
  • sw-daemon.sh → pipeline lifecycle (claim_job, update_stage, complete_job)
  • sw-memory.sh → failure/decision capture

Step 9: Dashboard integration

Replace 14+ file-scan functions in server.ts with SQL queries. Keep fallback to file-based reads when DB is missing. Key replacements: readEvents(), calculateDoraGrades(), getMetricsHistory(), getCostInfo(), getActivityFeed(), cost/stage endpoints.

Steps 10–12: CLI routing, tests, docs

Route db subcommand in scripts/sw. Comprehensive test suite. Update package.json and CLAUDE.md.


Task Checklist

  • Task 1: Create scripts/lib/migrations/001_initial_schema.sql — 8 tables, 15 indexes, schema_version
  • Task 2: Create scripts/lib/db.sh — bash SQLite library (Bash 3.2 compatible, WAL mode)
  • Task 3: Create scripts/sw-db.sh — CLI: shipwright db migrate|status|import|export
  • Task 4: Create dashboard/db.tsShipwrightDB class with bun:sqlite, all query methods
  • Task 5: Modify scripts/lib/helpers.sh — dual-write emit_event() to SQLite
  • Task 6: Modify scripts/sw-cost.sh — dual-write cost_record() to SQLite
  • Task 7: Modify scripts/sw-daemon.sh — pipeline lifecycle writes to SQLite
  • Task 8: Modify scripts/sw-memory.sh — memory entries to SQLite
  • Task 9: Modify dashboard/server.ts — SQL-backed queries with file fallback
  • Task 10: Modify scripts/sw — add db subcommand
  • Task 11: Create scripts/sw-db-test.sh — test suite (schema, CRUD, DORA, import, concurrency, degradation)
  • Task 12: Update package.json and CLAUDE.md

Testing Approach

Unit tests (sw-db-test.sh): Isolated temp $HOME, schema migration, CRUD operations, pipeline lifecycle, cost daily sums, DORA metric calculation with seeded data, JSON import, concurrent write safety (5 background writers), graceful degradation without sqlite3.

Integration: Dashboard /api/status from SQLite, dual-write verification (JSONL + SQLite), fallback when DB deleted.

Regression: All 22 existing test suites must still pass.


Definition of Done

  • SQLite at ~/.shipwright/shipwright.db created on first use
  • 8 tables with indexes, migration system tracking schema_version
  • Bash dual-write to JSONL + SQLite (JSONL authoritative, SQLite best-effort)
  • Dashboard reads from SQLite with file-based fallback
  • shipwright db import migrates existing JSON state
  • sw-db-test.sh all green + 22 existing suites pass
  • WAL mode + busy timeout for concurrent safety
  • Bash 3.2 compatible, no regressions

Architecture Decisions

  1. Dual-write, not replace — zero-risk migration; system works identically if SQLite has issues
  2. Dashboard is primary SQLite consumer — TypeScript/Bun gets the biggest wins (DORA, costs, pagination)
  3. WAL mode — concurrent readers + single writer
  4. Best-effort from bash|| true guards, gated behind command -v sqlite3
  5. Migration files — numbered .sql files for trackable schema evolution
  6. extra TEXT columns — JSON overflow avoids schema churn for uncommon fields
  7. Separate runtimes — bash uses sqlite3 CLI, dashboard uses bun:sqlite

Clone this wiki locally

AltStyle によって変換されたページ (->オリジナル) /