fix(storage): keep kernel state when SQLite disappears
Repeat the database check after confirmation. A missing database now stops cleanup before any state file is removed.
143 unmodified linesExpand all14414514614714814915015115215315418 unmodified lines143 unmodified linesExpand all return result, ctx.Err() } return result, err } if options.OldKernels && fresh.Database == 0 { return result, errors.New("database disappeared after the preview; no Python state files have been removed; restore the database and retry cleanup") } if options.OldKernels && !slices.Equal(preview.OldKernels, fresh.OldKernels) { return result, errors.New("unused Python state files changed after the preview; no files have been removed; run cleanup again to review the new list") } if options.Backups && !slices.Equal(preview.OldBackups, fresh.OldBackups) {18 unmodified lines5 unmodified lines67891011121314186 unmodified linesExpand all2012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462475 unmodified lines "context" "os" "os/exec" "path/filepath" "strings" "testing" "time")
186 unmodified linesExpand all } }) }}
func TestKernelCleanupRefusesDatabaseLostAfterPreview(t *testing.T) { home := t.TempDir() database := filepath.Join(home, "albedo.sqlite") setup := `import sqlite3,syswith sqlite3.connect(sys.argv[1]) as db: db.executescript("CREATE TABLE sessions(id TEXT, pinned_context TEXT); CREATE TABLE transcript(session TEXT,payload BLOB);")` if out, err := exec.Command("python3", "-c", setup, database).CombinedOutput(); err != nil { t.Fatalf("setup database: %v %s", err, out) } kernels := filepath.Join(home, "kernels") if err := os.Mkdir(kernels, 0700); err != nil { t.Fatal(err) } candidate := filepath.Join(kernels, "orphan.state") if err := os.WriteFile(candidate, []byte("retain"), 0600); err != nil { t.Fatal(err) } old := time.Now().Add(-31 * 24 * time.Hour) if err := os.Chtimes(candidate, old, old); err != nil { t.Fatal(err) } service := testService(home) plan, planErr := service.PlanCleanup(t.Context(), CleanupOptions{OldKernels: true}) if planErr != nil { t.Fatal(planErr) } if err := os.Remove(database); err != nil { t.Fatal(err) } if _, err := service.ApplyCleanup(t.Context(), plan); err == nil || !strings.Contains(err.Error(), "database disappeared") { t.Fatalf("missing database authorized kernel deletion: %v", err) } if content, err := os.ReadFile(candidate); err != nil || string(content) != "retain" { t.Fatalf("kernel changed: %q, %v", content, err) } helper, err := startMaintenance(t.Context(), home, nil) if err != nil { t.Fatalf("refused cleanup retained ownership: %v", err) } helper.close()}