Skip to content

refactor: move baseline schema into migration v1#36

Merged
dean0x merged 1 commit intomainfrom
refactor/schema-migration-v1
Dec 5, 2025
Merged

refactor: move baseline schema into migration v1#36
dean0x merged 1 commit intomainfrom
refactor/schema-migration-v1

Conversation

@dean0x
Copy link
Owner

@dean0x dean0x commented Dec 5, 2025

User description

Summary

Fixes #21 - Makes migrations the single source of truth for database schema.

Problem

Schema was previously defined in two places:

  1. createTables() - Created all tables directly
  2. Migration v1 - Empty migration that just recorded baseline version

This violated database migration best practices and made schema evolution harder to track.

Solution

  • createTables() now only creates schema_migrations table
  • All table/index creation moved into migration v1's up() function
  • Fresh and existing databases now follow the same code path

Migration Safety

Scenario Behavior
Fresh database Migration v1 runs, creates all tables
Existing v0.3.x database Migration v1 skips (version already recorded)
Re-run migration Safe due to IF NOT EXISTS (idempotent)

Test plan

  • Build passes
  • Repository tests pass (66 tests)
  • Core tests pass (273 tests)
  • Migration logs confirm "Applying migration v1" on fresh DB

🤖 Generated with Claude Code


PR Type

Enhancement


Description

  • Move all table/index creation from createTables() into migration v1

  • Establish migrations as single source of truth for schema

  • Ensure fresh and existing databases follow same code path

  • Add architecture documentation explaining migration safety


Diagram Walkthrough

flowchart LR
  A["createTables()"] -->|"Previously: Created all tables"| B["Schema split across two places"]
  C["Migration v1"] -->|"Previously: Empty baseline"| B
  B -->|"Refactored to"| D["createTables() creates only schema_migrations"]
  D -->|"All schema now in"| E["Migration v1 up() function"]
  E -->|"Result: Single source of truth"| F["Unified schema management"]
Loading

File Walkthrough

Relevant files
Refactoring
database.ts
Consolidate schema definition into migration v1                   

src/implementations/database.ts

  • Removed 87 lines of table/index creation from createTables() method
  • Moved all table definitions (tasks, task_output, task_dependencies)
    and indexes into migration v1's up() function
  • Updated createTables() to only create schema_migrations table and
    apply pending migrations
  • Enhanced getMigrations() documentation with architecture notes on
    migration safety and idempotency
+79/-77 

Fixes #21 - Schema definition was split between createTables() and migrations.

Changes:
- createTables() now only creates schema_migrations table
- All table/index creation moved into migration v1's up() function
- Migrations are now the single source of truth for schema
- Added architecture documentation in getMigrations()

Migration safety:
- Uses IF NOT EXISTS for idempotency
- Existing databases already have v1 recorded (migration skips)
- Fresh databases run migration v1 to create all tables

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@qodo-free-for-open-source-projects

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
🟢
No security concerns identified No security vulnerabilities detected by AI analysis. Human verification advised for critical code.
Ticket Compliance
🟡
🎫 #21
🟢 Move all CREATE TABLE statements from createTables() into migration v1's up() function
Move all CREATE INDEX statements from createTables() into migration v1's up() function
Update createTables() to only create schema_migrations table
Ensure migrations become single source of truth for schema
Maintain idempotency using CREATE TABLE IF NOT EXISTS
Update documentation to reflect new pattern
Ensure existing databases skip v1 migration (currentVersion >= 1)
Test with fresh database to ensure identical behavior
Test with existing v0.3.0 database to ensure smooth upgrade
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@qodo-free-for-open-source-projects

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Ensure migration atomicity with one call

To ensure the database migration is atomic, combine all SQL statements within
the up function into a single db.exec() call instead of using multiple separate
calls.

src/implementations/database.ts [201-271]

-// Tasks table - core task data
+// Tasks table, output, dependencies, and indexes
 db.exec(`
   CREATE TABLE IF NOT EXISTS tasks (
     id TEXT PRIMARY KEY,
     prompt TEXT NOT NULL,
     status TEXT NOT NULL,
     priority TEXT NOT NULL,
     working_directory TEXT,
     use_worktree INTEGER DEFAULT 0,
     worktree_cleanup TEXT DEFAULT 'auto',
     merge_strategy TEXT DEFAULT 'pr',
     branch_name TEXT,
     base_branch TEXT,
     auto_commit INTEGER DEFAULT 1,
     push_to_remote INTEGER DEFAULT 1,
     pr_title TEXT,
     pr_body TEXT,
     timeout INTEGER,
     max_output_buffer INTEGER,
     parent_task_id TEXT,
     retry_count INTEGER,
     retry_of TEXT,
     created_at INTEGER NOT NULL,
     started_at INTEGER,
     completed_at INTEGER,
     worker_id TEXT,
     exit_code INTEGER,
     dependencies TEXT
-  )
-`);
+  );
 
-// Task output table - stdout/stderr capture
-db.exec(`
   CREATE TABLE IF NOT EXISTS task_output (
     task_id TEXT PRIMARY KEY,
     stdout TEXT,
     stderr TEXT,
     total_size INTEGER,
     file_path TEXT,
     FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE
-  )
-`);
+  );
 
-// Task dependencies table - DAG for dependency tracking
-// Pattern: Normalized dependency tracking with resolution states
-// Rationale: Enables efficient cycle detection, dependency queries, and state tracking
-db.exec(`
   CREATE TABLE IF NOT EXISTS task_dependencies (
     id INTEGER PRIMARY KEY AUTOINCREMENT,
     task_id TEXT NOT NULL,
     depends_on_task_id TEXT NOT NULL,
     created_at INTEGER NOT NULL,
     resolved_at INTEGER,
     resolution TEXT NOT NULL DEFAULT 'pending',
     FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE,
     FOREIGN KEY (depends_on_task_id) REFERENCES tasks(id) ON DELETE CASCADE,
     UNIQUE(task_id, depends_on_task_id)
-  )
-`);
+  );
 
-// Performance indexes
-db.exec(`
   CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status);
   CREATE INDEX IF NOT EXISTS idx_tasks_priority ON tasks(priority);
   CREATE INDEX IF NOT EXISTS idx_tasks_created_at ON tasks(created_at);
   CREATE INDEX IF NOT EXISTS idx_task_dependencies_task_id ON task_dependencies(task_id);
   CREATE INDEX IF NOT EXISTS idx_task_dependencies_depends_on ON task_dependencies(depends_on_task_id);
   CREATE INDEX IF NOT EXISTS idx_task_dependencies_resolution ON task_dependencies(resolution);
   CREATE INDEX IF NOT EXISTS idx_task_dependencies_blocked ON task_dependencies(task_id, resolution);
   CREATE INDEX IF NOT EXISTS idx_task_dependencies_depends_on_resolution ON task_dependencies(depends_on_task_id, resolution);
 `);
  • Apply / Chat
Suggestion importance[1-10]: 6

__

Why: The suggestion correctly identifies that multiple db.exec() calls are not atomic and proposes a valid improvement to ensure the entire migration succeeds or fails as a single unit, enhancing robustness.

Low
  • More

@dean0x dean0x mentioned this pull request Dec 5, 2025
10 tasks
@dean0x dean0x merged commit d22c89e into main Dec 5, 2025
2 checks passed
@dean0x dean0x deleted the refactor/schema-migration-v1 branch December 5, 2025 20:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor: Move baseline schema into migration v1 for single source of truth

1 participant