Add migration inspection tools for AI agents (bd-627d Phase 2)
Implemented: - bd migrate --inspect --json: Shows migration plan, db state, warnings - bd info --schema --json: Returns schema details for agents - Migration invariants: Validates migrations post-execution - Added ListMigrations() for introspection Phase 1 (invariants) and Phase 2 (inspection) complete. Next: Wire up MCP tools in beads-mcp server. Amp-Thread-ID: https://ampcode.com/threads/T-c4674660-d640-405f-a929-b664e8699a48 Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
@@ -29,13 +29,66 @@ var migrations = []Migration{
|
||||
{"content_hash_column", migrateContentHashColumn},
|
||||
}
|
||||
|
||||
// RunMigrations executes all registered migrations in order
|
||||
// MigrationInfo contains metadata about a migration for inspection
|
||||
type MigrationInfo struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
// ListMigrations returns list of all registered migrations with descriptions
|
||||
// Note: This returns ALL registered migrations, not just pending ones (all are idempotent)
|
||||
func ListMigrations() []MigrationInfo {
|
||||
result := make([]MigrationInfo, len(migrations))
|
||||
for i, m := range migrations {
|
||||
result[i] = MigrationInfo{
|
||||
Name: m.Name,
|
||||
Description: getMigrationDescription(m.Name),
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// getMigrationDescription returns a human-readable description for a migration
|
||||
func getMigrationDescription(name string) string {
|
||||
descriptions := map[string]string{
|
||||
"dirty_issues_table": "Adds dirty_issues table for auto-export tracking",
|
||||
"external_ref_column": "Adds external_ref column to issues table",
|
||||
"composite_indexes": "Adds composite indexes for better query performance",
|
||||
"closed_at_constraint": "Adds constraint ensuring closed issues have closed_at timestamp",
|
||||
"compaction_columns": "Adds compaction tracking columns (compacted_at, compacted_at_commit)",
|
||||
"snapshots_table": "Adds snapshots table for issue history",
|
||||
"compaction_config": "Adds config entries for compaction",
|
||||
"compacted_at_commit_column": "Adds compacted_at_commit to snapshots table",
|
||||
"export_hashes_table": "Adds export_hashes table for idempotent exports",
|
||||
"content_hash_column": "Adds content_hash column for collision resolution",
|
||||
}
|
||||
|
||||
if desc, ok := descriptions[name]; ok {
|
||||
return desc
|
||||
}
|
||||
return "Unknown migration"
|
||||
}
|
||||
|
||||
// RunMigrations executes all registered migrations in order with invariant checking
|
||||
func RunMigrations(db *sql.DB) error {
|
||||
// Capture pre-migration snapshot for validation
|
||||
snapshot, err := captureSnapshot(db)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to capture pre-migration snapshot: %w", err)
|
||||
}
|
||||
|
||||
// Run migrations (they are already idempotent)
|
||||
for _, migration := range migrations {
|
||||
if err := migration.Func(db); err != nil {
|
||||
return fmt.Errorf("migration %s failed: %w", migration.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Verify invariants after migrations complete
|
||||
if err := verifyInvariants(db, snapshot); err != nil {
|
||||
return fmt.Errorf("post-migration validation failed: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user