package agent import ( "bytes" "os" "path/filepath" "testing" "time" ) func testSpool(t *testing.T) *Spool { t.Helper() now := time.Date(2026, 9, 18, 0, 0, 0, 0, time.UTC) s, err := NewSpool(t.TempDir(), func() time.Time { return now }) if err != nil { t.Fatal(err) } return s } func TestSpoolAtomicStateAndBootUnknown(t *testing.T) { s := testSpool(t) if _, err := s.Start("exec-1", 1, "session-1"); err != nil { t.Fatal(err) } if _, err := s.Update("exec-1", "running", ""); err != nil { t.Fatal(err) } report, err := s.MarkUnknownOnBoot() if err != nil { t.Fatal(err) } if len(report.Unknown) != 1 || report.Unknown[0] != "exec-1" { t.Fatalf("recovery report = %+v", report) } state, err := s.Load("exec-1") if err != nil { t.Fatal(err) } if state.Status != "unknown" || !state.Unknown { t.Fatalf("state = %+v", state) } } func TestSpoolQuarantinesCorruptStateAndNeverDeletesIt(t *testing.T) { s := testSpool(t) if err := os.MkdirAll(filepath.Join(s.Root(), "broken"), 0o700); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(s.Root(), "broken", "state.json"), []byte("{"), 0o600); err != nil { t.Fatal(err) } report, err := s.MarkUnknownOnBoot() if err != nil { t.Fatal(err) } if len(report.Quarantined) != 1 || len(report.Unknown) != 0 { t.Fatalf("recovery report = %+v", report) } matches, err := filepath.Glob(filepath.Join(s.Root(), "broken", "state.json.corrupt-*")) if err != nil || len(matches) != 1 { t.Fatalf("quarantine files = %v, err=%v", matches, err) } } func TestSpoolTranscriptAndAssetAreDurableFiles(t *testing.T) { s := testSpool(t) if _, err := s.Start("exec-2", 1, "session-2"); err != nil { t.Fatal(err) } if err := s.AppendTranscript("exec-2", []byte(`{"text":"hello","final":true}`)); err != nil { t.Fatal(err) } path, n, hash, err := s.WriteAsset("exec-2", "recording.pcm", bytes.NewReader([]byte("pcm"))) if err != nil { t.Fatal(err) } if n != 3 || hash == "" || path == "" { t.Fatalf("asset result path=%q bytes=%d hash=%q", path, n, hash) } if _, err := os.Stat(filepath.Join(s.Root(), "exec-2", "assets", "recording.pcm.part")); !os.IsNotExist(err) { t.Fatalf("temporary asset still exists: %v", err) } }