package workflow import ( "os" "path/filepath" "testing" ) func TestLeakGuard_CleanTrackedTree(t *testing.T) { cfg := newCfg(t) writeRepoFile(t, cfg.RepoRoot, "main.go", "package main\nfunc main(){}\n") writeRepoFile(t, cfg.RepoRoot, ".gitignore", "/.eeco/\n") gitInit(t, cfg.RepoRoot) res, err := leakGuard{}.Run(Env{Config: cfg}) if err != nil { t.Fatal(err) } if res.Code != CodeClean { t.Fatalf("clean repo -> %d (%s) %+v", res.Code, res.Summary, res.Findings) } } func TestLeakGuard_FlagsTrailerInTrackedFile(t *testing.T) { cfg := newCfg(t) trailer := fragCoAB + ": A " writeRepoFile(t, cfg.RepoRoot, "CHANGELOG.md", "release notes\n"+trailer+"\n") gitInit(t, cfg.RepoRoot) res, err := leakGuard{}.Run(Env{Config: cfg}) if err != nil { t.Fatal(err) } if res.Code != CodeFinding { t.Fatalf("tracked trailer -> %d, want %d (%+v)", res.Code, CodeFinding, res.Findings) } } func TestLeakGuard_FlagsWorkspacePathLeak(t *testing.T) { cfg := newCfg(t) // Build the engine path from fragments so this tracked test source // never carries a contiguous workspace-engine path for the gate to // (correctly) flag against eeco itself. eng := cfg.WorkspaceName + "/state/" writeRepoFile(t, cfg.RepoRoot, "notes.txt", "debug dump from "+eng+"queue.md here\n") gitInit(t, cfg.RepoRoot) res, err := leakGuard{}.Run(Env{Config: cfg}) if err != nil { t.Fatal(err) } if res.Code != CodeFinding { t.Fatalf("workspace path leak -> %d, want %d", res.Code, CodeFinding) } } func TestLeakGuard_GitignoreEntryExempt(t *testing.T) { cfg := newCfg(t) // The .gitignore workspace line is the documented intended change; // it must never be reported as a leak — even an engine-path-shaped // line here is exempt. Fragment-built for the reason above. ws := cfg.WorkspaceName writeRepoFile(t, cfg.RepoRoot, ".gitignore", "/"+ws+"/\n"+ws+"/state/\n") gitInit(t, cfg.RepoRoot) res, err := leakGuard{}.Run(Env{Config: cfg}) if err != nil { t.Fatal(err) } if res.Code != CodeClean { t.Fatalf(".gitignore flagged: %+v", res.Findings) } } func TestLeakGuard_IgnoresUntrackedFile(t *testing.T) { cfg := newCfg(t) writeRepoFile(t, cfg.RepoRoot, "tracked.txt", "fine\n") gitInit(t, cfg.RepoRoot) // Written after `git add`: untracked, so it cannot enter history. writeRepoFile(t, cfg.RepoRoot, "untracked.txt", fragCoAB+": X \n") res, err := leakGuard{}.Run(Env{Config: cfg}) if err != nil { t.Fatal(err) } if res.Code != CodeClean { t.Fatalf("untracked file gated the commit: %+v", res.Findings) } } func TestLeakGuard_ScansCommitMessage(t *testing.T) { cfg := newCfg(t) writeRepoFile(t, cfg.RepoRoot, "f.txt", "ok\n") gitInit(t, cfg.RepoRoot) msg := "feat: a change\n\n" + fragCoAB + ": Tool \n" if err := os.WriteFile(filepath.Join(cfg.RepoRoot, ".git", "COMMIT_EDITMSG"), []byte(msg), 0o644); err != nil { t.Fatal(err) } res, err := leakGuard{}.Run(Env{Config: cfg}) if err != nil { t.Fatal(err) } if res.Code != CodeFinding { t.Fatalf("commit-message trailer -> %d, want %d", res.Code, CodeFinding) } var sawMsg bool for _, f := range res.Findings { if f.Path == "COMMIT_EDITMSG" { sawMsg = true } } if !sawMsg { t.Errorf("commit message not attributed in findings: %+v", res.Findings) } }