fix(doctor): query metadata table instead of config for last_import_time (#916)

The sync_divergence check was querying the wrong table. The sync code
writes last_import_time to the metadata table, but doctor was looking
in config. This caused spurious "No last_import_time recorded" warnings
even when sync was working correctly.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
aaron-sangster
2026-01-06 03:11:17 +00:00
committed by GitHub
parent 7db052a48e
commit b86ce0a7e0
2 changed files with 48 additions and 7 deletions

View File

@@ -180,7 +180,7 @@ func checkSQLiteMtimeDivergence(path, beadsDir string) *SyncDivergenceIssue {
defer db.Close()
var lastImportTimeStr string
err = db.QueryRow("SELECT value FROM config WHERE key = 'last_import_time'").Scan(&lastImportTimeStr)
err = db.QueryRow("SELECT value FROM metadata WHERE key = 'last_import_time'").Scan(&lastImportTimeStr)
if err != nil {
// No last_import_time recorded - this is a potential issue
return &SyncDivergenceIssue{

View File

@@ -150,7 +150,7 @@ func TestCheckSQLiteMtimeDivergence(t *testing.T) {
t.Fatal(err)
}
_, _ = db.Exec("CREATE TABLE issues (id TEXT)")
_, _ = db.Exec("CREATE TABLE config (key TEXT, value TEXT)")
_, _ = db.Exec("CREATE TABLE metadata (key TEXT, value TEXT)")
db.Close()
issue := checkSQLiteMtimeDivergence(dir, beadsDir)
@@ -173,7 +173,7 @@ func TestCheckSQLiteMtimeDivergence(t *testing.T) {
t.Fatal(err)
}
_, _ = db.Exec("CREATE TABLE issues (id TEXT)")
_, _ = db.Exec("CREATE TABLE config (key TEXT, value TEXT)")
_, _ = db.Exec("CREATE TABLE metadata (key TEXT, value TEXT)")
db.Close()
// Create JSONL
@@ -214,8 +214,8 @@ func TestCheckSQLiteMtimeDivergence(t *testing.T) {
t.Fatal(err)
}
_, _ = db.Exec("CREATE TABLE issues (id TEXT)")
_, _ = db.Exec("CREATE TABLE config (key TEXT, value TEXT)")
_, _ = db.Exec("INSERT INTO config (key, value) VALUES (?, ?)",
_, _ = db.Exec("CREATE TABLE metadata (key TEXT, value TEXT)")
_, _ = db.Exec("INSERT INTO metadata (key, value) VALUES (?, ?)",
"last_import_time", importTime.Format(time.RFC3339))
db.Close()
@@ -239,9 +239,9 @@ func TestCheckSQLiteMtimeDivergence(t *testing.T) {
t.Fatal(err)
}
_, _ = db.Exec("CREATE TABLE issues (id TEXT)")
_, _ = db.Exec("CREATE TABLE config (key TEXT, value TEXT)")
_, _ = db.Exec("CREATE TABLE metadata (key TEXT, value TEXT)")
oldTime := time.Now().Add(-1 * time.Hour)
_, _ = db.Exec("INSERT INTO config (key, value) VALUES (?, ?)",
_, _ = db.Exec("INSERT INTO metadata (key, value) VALUES (?, ?)",
"last_import_time", oldTime.Format(time.RFC3339))
db.Close()
@@ -263,6 +263,47 @@ func TestCheckSQLiteMtimeDivergence(t *testing.T) {
}
}
})
// Regression test: verify we read from metadata table, not config table.
// The sync code writes to metadata, so doctor must read from there.
// This catches the bug where doctor queried 'config' instead of 'metadata'.
t.Run("reads from metadata table not config", func(t *testing.T) {
dir := mkTmpDirInTmp(t, "bd-mtime-table-*")
beadsDir := filepath.Join(dir, ".beads")
if err := os.MkdirAll(beadsDir, 0755); err != nil {
t.Fatal(err)
}
// Create JSONL first
jsonlPath := filepath.Join(beadsDir, "issues.jsonl")
if err := os.WriteFile(jsonlPath, []byte(`{"id":"test-1"}`+"\n"), 0644); err != nil {
t.Fatal(err)
}
// Get JSONL mtime
jsonlInfo, _ := os.Stat(jsonlPath)
importTime := jsonlInfo.ModTime()
// Create database with BOTH config and metadata tables (realistic schema)
// Put last_import_time ONLY in metadata (as real sync code does)
dbPath := filepath.Join(beadsDir, "beads.db")
db, err := sql.Open("sqlite3", dbPath)
if err != nil {
t.Fatal(err)
}
_, _ = db.Exec("CREATE TABLE issues (id TEXT)")
_, _ = db.Exec("CREATE TABLE config (key TEXT, value TEXT)")
_, _ = db.Exec("CREATE TABLE metadata (key TEXT, value TEXT)")
// Only insert into metadata, NOT config
_, _ = db.Exec("INSERT INTO metadata (key, value) VALUES (?, ?)",
"last_import_time", importTime.Format(time.RFC3339))
db.Close()
issue := checkSQLiteMtimeDivergence(dir, beadsDir)
if issue != nil {
t.Errorf("expected nil issue when last_import_time is in metadata table, got %+v", issue)
}
})
}
func TestCheckUncommittedBeadsChanges(t *testing.T) {