|
1 | 1 | package beads |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "encoding/json" |
4 | 5 | "fmt" |
5 | 6 | "os" |
6 | 7 | "path/filepath" |
@@ -346,3 +347,119 @@ func TestMergeAgentBeadSources(t *testing.T) { |
346 | 347 | } |
347 | 348 | }) |
348 | 349 | } |
| 350 | + |
| 351 | +func installMockBDCreateRecorder(t *testing.T, logPath string) { |
| 352 | + t.Helper() |
| 353 | + |
| 354 | + binDir := t.TempDir() |
| 355 | + if runtime.GOOS == "windows" { |
| 356 | + t.Skip("cross-rig create recorder test not implemented on Windows") |
| 357 | + } |
| 358 | + |
| 359 | + script := `#!/bin/sh |
| 360 | +printf 'pwd=%s\n' "$(pwd)" >> "$MOCK_BD_LOG" |
| 361 | +printf 'beads_dir=%s\n' "$BEADS_DIR" >> "$MOCK_BD_LOG" |
| 362 | +printf 'args=%s\n' "$*" >> "$MOCK_BD_LOG" |
| 363 | +
|
| 364 | +cmd="" |
| 365 | +for arg in "$@"; do |
| 366 | + case "$arg" in |
| 367 | + --*) ;; |
| 368 | + *) cmd="$arg"; break ;; |
| 369 | + esac |
| 370 | +done |
| 371 | +
|
| 372 | +case "$cmd" in |
| 373 | + create) |
| 374 | + printf '{"id":"pt-imported-polecat-shiny","title":"shiny","status":"open"}\n' |
| 375 | + exit 0 |
| 376 | + ;; |
| 377 | + slot|config|migrate|init|show|update) |
| 378 | + exit 0 |
| 379 | + ;; |
| 380 | + *) |
| 381 | + exit 0 |
| 382 | + ;; |
| 383 | +esac |
| 384 | +` |
| 385 | + scriptPath := filepath.Join(binDir, "bd") |
| 386 | + if err := os.WriteFile(scriptPath, []byte(script), 0755); err != nil { |
| 387 | + t.Fatalf("write mock bd: %v", err) |
| 388 | + } |
| 389 | + |
| 390 | + t.Setenv("PATH", binDir+string(os.PathListSeparator)+os.Getenv("PATH")) |
| 391 | + t.Setenv("MOCK_BD_LOG", logPath) |
| 392 | +} |
| 393 | + |
| 394 | +func TestCreateAgentBead_UsesTownRootForCrossRigRoutes(t *testing.T) { |
| 395 | + if runtime.GOOS == "windows" { |
| 396 | + t.Skip("path assertions are Unix-oriented") |
| 397 | + } |
| 398 | + |
| 399 | + // Resolve symlinks so path assertions match shell pwd output. |
| 400 | + // On macOS, t.TempDir() returns /var/... but pwd resolves to /private/var/... |
| 401 | + townRoot, _ := filepath.EvalSymlinks(t.TempDir()) |
| 402 | + for _, dir := range []string{ |
| 403 | + filepath.Join(townRoot, "mayor"), |
| 404 | + filepath.Join(townRoot, ".beads"), |
| 405 | + filepath.Join(townRoot, "imported", "mayor", "rig", ".beads"), |
| 406 | + } { |
| 407 | + if err := os.MkdirAll(dir, 0755); err != nil { |
| 408 | + t.Fatalf("mkdir %s: %v", dir, err) |
| 409 | + } |
| 410 | + } |
| 411 | + if err := os.WriteFile(filepath.Join(townRoot, "mayor", "town.json"), []byte(`{"name":"test"}`), 0644); err != nil { |
| 412 | + t.Fatal(err) |
| 413 | + } |
| 414 | + if err := os.WriteFile(filepath.Join(townRoot, ".beads", "routes.jsonl"), []byte("{\"prefix\":\"pt-\",\"path\":\"imported/mayor/rig\"}\n"), 0644); err != nil { |
| 415 | + t.Fatal(err) |
| 416 | + } |
| 417 | + |
| 418 | + logPath := filepath.Join(townRoot, "bd.log") |
| 419 | + installMockBDCreateRecorder(t, logPath) |
| 420 | + |
| 421 | + workerDir := filepath.Join(townRoot, "imported", "mayor", "rig") |
| 422 | + bd := NewWithBeadsDir(workerDir, filepath.Join(workerDir, ".beads")) |
| 423 | + |
| 424 | + issue, err := bd.CreateAgentBead("pt-imported-polecat-shiny", "shiny", &AgentFields{ |
| 425 | + RoleType: "polecat", |
| 426 | + Rig: "imported", |
| 427 | + AgentState: "spawning", |
| 428 | + HookBead: "pt-task-1", |
| 429 | + }) |
| 430 | + if err != nil { |
| 431 | + t.Fatalf("CreateAgentBead: %v", err) |
| 432 | + } |
| 433 | + if issue == nil { |
| 434 | + t.Fatal("CreateAgentBead returned nil issue") |
| 435 | + } |
| 436 | + |
| 437 | + logData, err := os.ReadFile(logPath) |
| 438 | + if err != nil { |
| 439 | + t.Fatalf("read mock bd log: %v", err) |
| 440 | + } |
| 441 | + logOutput := string(logData) |
| 442 | + if !strings.Contains(logOutput, "pwd="+townRoot) { |
| 443 | + t.Fatalf("mock bd log missing town root cwd:\n%s", logOutput) |
| 444 | + } |
| 445 | + if !strings.Contains(logOutput, "beads_dir="+filepath.Join(townRoot, ".beads")) { |
| 446 | + t.Fatalf("mock bd log missing town-root BEADS_DIR:\n%s", logOutput) |
| 447 | + } |
| 448 | + if !strings.Contains(logOutput, "create --json --id=pt-imported-polecat-shiny") { |
| 449 | + t.Fatalf("mock bd log missing create call:\n%s", logOutput) |
| 450 | + } |
| 451 | + if !strings.Contains(logOutput, "slot set pt-imported-polecat-shiny hook pt-task-1") { |
| 452 | + t.Fatalf("mock bd log missing slot set call:\n%s", logOutput) |
| 453 | + } |
| 454 | +} |
| 455 | + |
| 456 | +func TestCreateAgentBead_ParsesMockCreateOutput(t *testing.T) { |
| 457 | + raw := []byte(`{"id":"pt-imported-polecat-shiny","title":"shiny","status":"open"}`) |
| 458 | + var issue Issue |
| 459 | + if err := json.Unmarshal(raw, &issue); err != nil { |
| 460 | + t.Fatalf("json.Unmarshal: %v", err) |
| 461 | + } |
| 462 | + if issue.ID != "pt-imported-polecat-shiny" { |
| 463 | + t.Fatalf("issue.ID = %q", issue.ID) |
| 464 | + } |
| 465 | +} |
0 commit comments