package main import ( "os" "os/exec" "path/filepath" "testing" "ai-workflow-skill/packages/repo-memory-runtime/internal/store" ) func TestVerifyCandidateDetectsFileChange(t *testing.T) { t.Parallel() repo := t.TempDir() runCmd(t, repo, "git", "init") runCmd(t, repo, "git", "config", "user.email", "test@example.com") runCmd(t, repo, "git", "config", "user.name", "Tester") file := filepath.Join(repo, "foo.txt") if err := os.WriteFile(file, []byte("hello\n"), 0o644); err != nil { t.Fatal(err) } runCmd(t, repo, "git", "add", ".") runCmd(t, repo, "git", "commit", "-m", "init") commit := stringsTrim(runOut(t, repo, "git", "rev-parse", "HEAD")) if err := os.WriteFile(file, []byte("changed\n"), 0o644); err != nil { t.Fatal(err) } status, reason, err := verifyCandidate(repo, store.VerifyCandidate{ Status: "confirmed", VerifiedOnCommit: commit, Dependencies: []store.DependencyInput{ {Type: "file", Locator: "foo.txt", IsHard: true}, }, }) if err != nil { t.Fatal(err) } if status != "needs_review" { t.Fatalf("status = %q, want needs_review", status) } if reason == "" { t.Fatal("expected downgrade reason") } } func TestVerifyCandidateMarksMissingDependencyStale(t *testing.T) { t.Parallel() repo := t.TempDir() runCmd(t, repo, "git", "init") runCmd(t, repo, "git", "config", "user.email", "test@example.com") runCmd(t, repo, "git", "config", "user.name", "Tester") runCmd(t, repo, "git", "commit", "--allow-empty", "-m", "init") commit := stringsTrim(runOut(t, repo, "git", "rev-parse", "HEAD")) status, reason, err := verifyCandidate(repo, store.VerifyCandidate{ Status: "confirmed", VerifiedOnCommit: commit, Dependencies: []store.DependencyInput{ {Type: "file", Locator: "missing.txt", IsHard: true}, }, }) if err != nil { t.Fatal(err) } if status != "stale" { t.Fatalf("status = %q, want stale", status) } if reason == "" { t.Fatal("expected stale reason") } } func runCmd(t *testing.T, dir string, name string, args ...string) { t.Helper() cmd := exec.Command(name, args...) cmd.Dir = dir out, err := cmd.CombinedOutput() if err != nil { t.Fatalf("%s %v failed: %v\n%s", name, args, err, string(out)) } } func runOut(t *testing.T, dir string, name string, args ...string) string { t.Helper() cmd := exec.Command(name, args...) cmd.Dir = dir out, err := cmd.Output() if err != nil { t.Fatalf("%s %v failed: %v", name, args, err) } return string(out) } func stringsTrim(value string) string { for len(value) > 0 && (value[len(value)-1] == '\n' || value[len(value)-1] == '\r' || value[len(value)-1] == ' ') { value = value[:len(value)-1] } return value }