@@ -101,44 +101,47 @@ func setupTestTown(t *testing.T) string {
101101
102102// mockBdCommand creates a fake bd binary that simulates bd behavior.
103103// This avoids needing bd installed for tests.
104- func mockBdCommand (t * testing.T ) {
104+ func mockBdCommand (t * testing.T ) string {
105105 t .Helper ()
106106
107107 binDir := t .TempDir ()
108108 bdPath := filepath .Join (binDir , "bd" )
109+ logPath := filepath .Join (binDir , "bd.log" )
109110
110111 // Create a script that simulates bd init and other commands
112+ // Also logs all create commands for verification.
113+ // Note: beads.run() prepends --no-daemon --allow-stale to all commands,
114+ // so we need to find the actual command in the argument list.
111115 script := `#!/bin/sh
112116# Mock bd for testing
113-
114- case "$1" in
117+ LOG_FILE="` + logPath + `"
118+
119+ # Find the actual command (skip global flags like --no-daemon, --allow-stale)
120+ cmd=""
121+ for arg in "$@"; do
122+ case "$arg" in
123+ --*) ;; # skip flags
124+ *) cmd="$arg"; break ;;
125+ esac
126+ done
127+
128+ case "$cmd" in
115129 init)
116130 # Create .beads directory and config.yaml
117131 mkdir -p .beads
118132 prefix="gt"
133+ # Handle both --prefix=value and --prefix value forms
134+ next_is_prefix=false
119135 for arg in "$@"; do
120- case "$arg" in
121- --prefix=*) prefix="${arg#--prefix=}" ;;
122- --prefix)
123- # Next arg is the prefix
124- shift
125- if [ -n "$1" ] && [ "$1" != "--"* ]; then
126- prefix="$1"
127- fi
128- ;;
129- esac
130- shift
131- done
132- # Handle positional --prefix VALUE
133- shift # skip 'init'
134- while [ $# -gt 0 ]; do
135- case "$1" in
136- --prefix)
137- shift
138- prefix="$1"
139- ;;
140- esac
141- shift
136+ if [ "$next_is_prefix" = true ]; then
137+ prefix="$arg"
138+ next_is_prefix=false
139+ else
140+ case "$arg" in
141+ --prefix=*) prefix="${arg#--prefix=}" ;;
142+ --prefix) next_is_prefix=true ;;
143+ esac
144+ fi
142145 done
143146 echo "prefix: $prefix" > .beads/config.yaml
144147 exit 0
@@ -151,8 +154,17 @@ case "$1" in
151154 exit 1
152155 ;;
153156 create)
154- # Return minimal JSON for agent bead creation
155- echo '{}'
157+ # Log all create commands for verification
158+ echo "$@" >> "$LOG_FILE"
159+ # Extract the ID from --id=xxx argument
160+ bead_id=""
161+ for arg in "$@"; do
162+ case "$arg" in
163+ --id=*) bead_id="${arg#--id=}" ;;
164+ esac
165+ done
166+ # Return valid JSON for bead creation
167+ echo "{\"id\":\"$bead_id\",\"status\":\"open\",\"created_at\":\"2025-01-01T00:00:00Z\"}"
156168 exit 0
157169 ;;
158170 mol|list)
@@ -169,12 +181,14 @@ esac
169181
170182 // Prepend to PATH
171183 t .Setenv ("PATH" , binDir + string (os .PathListSeparator )+ os .Getenv ("PATH" ))
184+
185+ return logPath
172186}
173187
174188// TestRigAddCreatesCorrectStructure verifies that gt rig add creates
175189// the expected directory structure.
176190func TestRigAddCreatesCorrectStructure (t * testing.T ) {
177- mockBdCommand (t )
191+ _ = mockBdCommand (t )
178192 townRoot := setupTestTown (t )
179193 gitURL := createTestGitRepo (t , "testproject" )
180194
@@ -293,7 +307,7 @@ func TestRigAddCreatesCorrectStructure(t *testing.T) {
293307// TestRigAddInitializesBeads verifies that beads is initialized with
294308// the correct prefix.
295309func TestRigAddInitializesBeads (t * testing.T ) {
296- mockBdCommand (t )
310+ _ = mockBdCommand (t )
297311 townRoot := setupTestTown (t )
298312 gitURL := createTestGitRepo (t , "beadstest" )
299313
@@ -389,7 +403,7 @@ func TestRigAddInitializesBeads(t *testing.T) {
389403// TestRigAddUpdatesRoutes verifies that routes.jsonl is updated
390404// with the new rig's route.
391405func TestRigAddUpdatesRoutes (t * testing.T ) {
392- mockBdCommand (t )
406+ _ = mockBdCommand (t )
393407 townRoot := setupTestTown (t )
394408 gitURL := createTestGitRepo (t , "routetest" )
395409
@@ -458,7 +472,7 @@ func TestRigAddUpdatesRoutes(t *testing.T) {
458472// TestRigAddUpdatesRigsJson verifies that rigs.json is updated
459473// with the new rig entry.
460474func TestRigAddUpdatesRigsJson (t * testing.T ) {
461- mockBdCommand (t )
475+ _ = mockBdCommand (t )
462476 townRoot := setupTestTown (t )
463477 gitURL := createTestGitRepo (t , "jsontest" )
464478
@@ -510,7 +524,7 @@ func TestRigAddUpdatesRigsJson(t *testing.T) {
510524// TestRigAddDerivesPrefix verifies that when no prefix is specified,
511525// one is derived from the rig name.
512526func TestRigAddDerivesPrefix (t * testing.T ) {
513- mockBdCommand (t )
527+ _ = mockBdCommand (t )
514528 townRoot := setupTestTown (t )
515529 gitURL := createTestGitRepo (t , "myproject" )
516530
@@ -541,7 +555,7 @@ func TestRigAddDerivesPrefix(t *testing.T) {
541555// TestRigAddCreatesRigConfig verifies that config.json contains
542556// the correct rig configuration.
543557func TestRigAddCreatesRigConfig (t * testing.T ) {
544- mockBdCommand (t )
558+ _ = mockBdCommand (t )
545559 townRoot := setupTestTown (t )
546560 gitURL := createTestGitRepo (t , "configtest" )
547561
@@ -596,7 +610,7 @@ func TestRigAddCreatesRigConfig(t *testing.T) {
596610
597611// TestRigAddCreatesAgentDirs verifies that agent state files are created.
598612func TestRigAddCreatesAgentDirs (t * testing.T ) {
599- mockBdCommand (t )
613+ _ = mockBdCommand (t )
600614 townRoot := setupTestTown (t )
601615 gitURL := createTestGitRepo (t , "agenttest" )
602616
@@ -641,7 +655,7 @@ func TestRigAddCreatesAgentDirs(t *testing.T) {
641655// TestRigAddRejectsInvalidNames verifies that rig names with invalid
642656// characters are rejected.
643657func TestRigAddRejectsInvalidNames (t * testing.T ) {
644- mockBdCommand (t )
658+ _ = mockBdCommand (t )
645659 townRoot := setupTestTown (t )
646660 gitURL := createTestGitRepo (t , "validname" )
647661
@@ -677,3 +691,94 @@ func TestRigAddRejectsInvalidNames(t *testing.T) {
677691 })
678692 }
679693}
694+
695+ // TestRigAddCreatesAgentBeads verifies that gt rig add creates
696+ // witness and refinery agent beads via the manager's initAgentBeads.
697+ func TestRigAddCreatesAgentBeads (t * testing.T ) {
698+ bdLogPath := mockBdCommand (t )
699+ townRoot := setupTestTown (t )
700+ gitURL := createTestGitRepo (t , "agentbeadtest" )
701+
702+ rigsPath := filepath .Join (townRoot , "mayor" , "rigs.json" )
703+ rigsConfig , err := config .LoadRigsConfig (rigsPath )
704+ if err != nil {
705+ t .Fatalf ("load rigs.json: %v" , err )
706+ }
707+
708+ g := git .NewGit (townRoot )
709+ mgr := rig .NewManager (townRoot , rigsConfig , g )
710+
711+ // AddRig internally calls initAgentBeads which creates witness and refinery beads
712+ newRig , err := mgr .AddRig (rig.AddRigOptions {
713+ Name : "agentbeadtest" ,
714+ GitURL : gitURL ,
715+ BeadsPrefix : "ab" ,
716+ })
717+ if err != nil {
718+ t .Fatalf ("AddRig: %v" , err )
719+ }
720+
721+ // Verify the mock bd was called with correct create commands
722+ logContent , err := os .ReadFile (bdLogPath )
723+ if err != nil {
724+ t .Fatalf ("reading bd log: %v" , err )
725+ }
726+ logStr := string (logContent )
727+
728+ // Expected bead IDs that initAgentBeads should create
729+ witnessID := beads .WitnessBeadIDWithPrefix (newRig .Config .Prefix , "agentbeadtest" )
730+ refineryID := beads .RefineryBeadIDWithPrefix (newRig .Config .Prefix , "agentbeadtest" )
731+
732+ expectedIDs := []struct {
733+ id string
734+ desc string
735+ }{
736+ {witnessID , "witness agent bead" },
737+ {refineryID , "refinery agent bead" },
738+ }
739+
740+ for _ , expected := range expectedIDs {
741+ if ! strings .Contains (logStr , expected .id ) {
742+ t .Errorf ("bd create log should contain %s (%s), got:\n %s" , expected .id , expected .desc , logStr )
743+ }
744+ }
745+
746+ // Verify correct prefix is used (ab-)
747+ if ! strings .Contains (logStr , "ab-" ) {
748+ t .Errorf ("bd create log should contain prefix 'ab-', got:\n %s" , logStr )
749+ }
750+ }
751+
752+ // TestAgentBeadIDs verifies the agent bead ID generation functions.
753+ func TestAgentBeadIDs (t * testing.T ) {
754+ tests := []struct {
755+ name string
756+ fn func () string
757+ expected string
758+ }{
759+ {
760+ "WitnessBeadIDWithPrefix" ,
761+ func () string { return beads .WitnessBeadIDWithPrefix ("ab" , "myrig" ) },
762+ "ab-myrig-witness" ,
763+ },
764+ {
765+ "RefineryBeadIDWithPrefix" ,
766+ func () string { return beads .RefineryBeadIDWithPrefix ("ab" , "myrig" ) },
767+ "ab-myrig-refinery" ,
768+ },
769+ {
770+ "RigBeadIDWithPrefix" ,
771+ func () string { return beads .RigBeadIDWithPrefix ("ab" , "myrig" ) },
772+ "ab-rig-myrig" ,
773+ },
774+ }
775+
776+ for _ , tc := range tests {
777+ t .Run (tc .name , func (t * testing.T ) {
778+ result := tc .fn ()
779+ if result != tc .expected {
780+ t .Errorf ("got %q, want %q" , result , tc .expected )
781+ }
782+ })
783+ }
784+ }
0 commit comments