feat(migration): Add gt migrate-agents command for two-level architecture (gt-nnub1)
Implements Phase 4 of the two-level beads architecture migration: - Add hq- prefix helper functions for town-level agent beads - Add CreateWithID method for deterministic bead creation - Create gt migrate-agents command with dry-run/execute modes - Migrate gt-mayor/gt-deacon to hq-mayor/hq-deacon in town beads - Migrate role beads (gt-*-role) to town beads (hq-*-role) - Add migration labels to old beads for tracking - Idempotent: skips already-migrated beads 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
95
internal/cmd/migrate_agents_test.go
Normal file
95
internal/cmd/migrate_agents_test.go
Normal file
@@ -0,0 +1,95 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/steveyegge/gastown/internal/beads"
|
||||
)
|
||||
|
||||
func TestMigrationResultStatus(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
result migrationResult
|
||||
wantIcon string
|
||||
}{
|
||||
{
|
||||
name: "migrated shows checkmark",
|
||||
result: migrationResult{
|
||||
OldID: "gt-mayor",
|
||||
NewID: "hq-mayor",
|
||||
Status: "migrated",
|
||||
Message: "successfully migrated",
|
||||
},
|
||||
wantIcon: "✓",
|
||||
},
|
||||
{
|
||||
name: "would migrate shows checkmark",
|
||||
result: migrationResult{
|
||||
OldID: "gt-mayor",
|
||||
NewID: "hq-mayor",
|
||||
Status: "would migrate",
|
||||
Message: "would copy state from gt-mayor",
|
||||
},
|
||||
wantIcon: "✓",
|
||||
},
|
||||
{
|
||||
name: "skipped shows empty circle",
|
||||
result: migrationResult{
|
||||
OldID: "gt-mayor",
|
||||
NewID: "hq-mayor",
|
||||
Status: "skipped",
|
||||
Message: "already exists",
|
||||
},
|
||||
wantIcon: "⊘",
|
||||
},
|
||||
{
|
||||
name: "error shows X",
|
||||
result: migrationResult{
|
||||
OldID: "gt-mayor",
|
||||
NewID: "hq-mayor",
|
||||
Status: "error",
|
||||
Message: "failed to create",
|
||||
},
|
||||
wantIcon: "✗",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var icon string
|
||||
switch tt.result.Status {
|
||||
case "migrated", "would migrate":
|
||||
icon = "✓"
|
||||
case "skipped":
|
||||
icon = "⊘"
|
||||
case "error":
|
||||
icon = "✗"
|
||||
}
|
||||
if icon != tt.wantIcon {
|
||||
t.Errorf("icon for status %q = %q, want %q", tt.result.Status, icon, tt.wantIcon)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestTownBeadIDHelpers(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
got string
|
||||
want string
|
||||
}{
|
||||
{"MayorBeadIDTown", beads.MayorBeadIDTown(), "hq-mayor"},
|
||||
{"DeaconBeadIDTown", beads.DeaconBeadIDTown(), "hq-deacon"},
|
||||
{"DogBeadIDTown", beads.DogBeadIDTown("fido"), "hq-dog-fido"},
|
||||
{"RoleBeadIDTown mayor", beads.RoleBeadIDTown("mayor"), "hq-mayor-role"},
|
||||
{"RoleBeadIDTown witness", beads.RoleBeadIDTown("witness"), "hq-witness-role"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.got != tt.want {
|
||||
t.Errorf("%s = %q, want %q", tt.name, tt.got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user