refactor(hooks): consolidate duplicate JSONL file lists into shared constant

- Add jsonlFilePaths constant to eliminate duplicate file list definitions
- Update all usages in hook.go and hooks.go to use the shared constant
- Include beads.jsonl for backwards compatibility with older installations

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
beads/crew/elinor
2026-01-20 19:15:04 -08:00
committed by Steve Yegge
parent 2fe15e2328
commit 4b2d1791ee
2 changed files with 19 additions and 14 deletions

View File

@@ -20,6 +20,15 @@ import (
"github.com/steveyegge/beads/internal/storage/factory" "github.com/steveyegge/beads/internal/storage/factory"
) )
// jsonlFilePaths lists all JSONL files that should be staged/tracked.
// Includes beads.jsonl for backwards compatibility with older installations.
var jsonlFilePaths = []string{
".beads/issues.jsonl",
".beads/deletions.jsonl",
".beads/interactions.jsonl",
".beads/beads.jsonl", // Legacy filename, kept for backwards compatibility
}
// hookCmd is the main "bd hook" command that git hooks call into. // hookCmd is the main "bd hook" command that git hooks call into.
// This is distinct from "bd hooks" (plural) which manages hook installation. // This is distinct from "bd hooks" (plural) which manages hook installation.
var hookCmd = &cobra.Command{ var hookCmd = &cobra.Command{
@@ -368,17 +377,16 @@ func hookPreCommit() int {
} }
// Stage JSONL files // Stage JSONL files
jsonlFiles := []string{".beads/beads.jsonl", ".beads/issues.jsonl", ".beads/deletions.jsonl", ".beads/interactions.jsonl"}
if os.Getenv("BEADS_NO_AUTO_STAGE") == "" { if os.Getenv("BEADS_NO_AUTO_STAGE") == "" {
rc, rcErr := beads.GetRepoContext() rc, rcErr := beads.GetRepoContext()
ctx := context.Background() ctx := context.Background()
for _, f := range jsonlFiles { for _, f := range jsonlFilePaths {
if _, err := os.Stat(f); err == nil { if _, err := os.Stat(f); err == nil {
var gitAdd *exec.Cmd var gitAdd *exec.Cmd
if rcErr == nil { if rcErr == nil {
gitAdd = rc.GitCmdCWD(ctx, "add", f) gitAdd = rc.GitCmdCWD(ctx, "add", f)
} else { } else {
// #nosec G204 -- f comes from jsonlFiles (controlled, hardcoded paths) // #nosec G204 -- f comes from jsonlFilePaths (controlled, hardcoded paths)
gitAdd = exec.Command("git", "add", f) gitAdd = exec.Command("git", "add", f)
} }
_ = gitAdd.Run() _ = gitAdd.Run()
@@ -532,14 +540,13 @@ func stageJSONLFiles(ctx context.Context) {
} }
rc, rcErr := beads.GetRepoContext() rc, rcErr := beads.GetRepoContext()
jsonlFiles := []string{".beads/issues.jsonl", ".beads/deletions.jsonl", ".beads/interactions.jsonl"} for _, f := range jsonlFilePaths {
for _, f := range jsonlFiles {
if _, err := os.Stat(f); err == nil { if _, err := os.Stat(f); err == nil {
var gitAdd *exec.Cmd var gitAdd *exec.Cmd
if rcErr == nil { if rcErr == nil {
gitAdd = rc.GitCmdCWD(ctx, "add", f) gitAdd = rc.GitCmdCWD(ctx, "add", f)
} else { } else {
// #nosec G204 -- f comes from jsonlFiles (hardcoded) // #nosec G204 -- f comes from jsonlFilePaths (controlled, hardcoded paths)
gitAdd = exec.Command("git", "add", f) gitAdd = exec.Command("git", "add", f)
} }
_ = gitAdd.Run() _ = gitAdd.Run()

View File

@@ -575,12 +575,10 @@ func runPreCommitHook() int {
// By default, we auto-stage for convenience. Users with conflicting git hooks // By default, we auto-stage for convenience. Users with conflicting git hooks
// (e.g., hooks that read the staging area) can set BEADS_NO_AUTO_STAGE=1 to // (e.g., hooks that read the staging area) can set BEADS_NO_AUTO_STAGE=1 to
// disable this and stage manually. See: https://github.com/steveyegge/beads/issues/826 // disable this and stage manually. See: https://github.com/steveyegge/beads/issues/826
jsonlFiles := []string{".beads/beads.jsonl", ".beads/issues.jsonl", ".beads/deletions.jsonl", ".beads/interactions.jsonl"}
if os.Getenv("BEADS_NO_AUTO_STAGE") != "" { if os.Getenv("BEADS_NO_AUTO_STAGE") != "" {
// Safe mode: check for unstaged changes and block if found // Safe mode: check for unstaged changes and block if found
var unstaged []string var unstaged []string
for _, f := range jsonlFiles { for _, f := range jsonlFilePaths {
if _, err := os.Stat(f); err == nil { if _, err := os.Stat(f); err == nil {
if hasUnstagedChanges(f) { if hasUnstagedChanges(f) {
unstaged = append(unstaged, f) unstaged = append(unstaged, f)
@@ -601,14 +599,14 @@ func runPreCommitHook() int {
// Default: auto-stage JSONL files // Default: auto-stage JSONL files
rc, rcErr := beads.GetRepoContext() rc, rcErr := beads.GetRepoContext()
ctx := context.Background() ctx := context.Background()
for _, f := range jsonlFiles { for _, f := range jsonlFilePaths {
if _, err := os.Stat(f); err == nil { if _, err := os.Stat(f); err == nil {
var gitAdd *exec.Cmd var gitAdd *exec.Cmd
if rcErr == nil { if rcErr == nil {
gitAdd = rc.GitCmdCWD(ctx, "add", f) gitAdd = rc.GitCmdCWD(ctx, "add", f)
} else { } else {
// Fallback if RepoContext unavailable // Fallback if RepoContext unavailable
// #nosec G204 -- f comes from jsonlFiles (controlled, hardcoded paths) // #nosec G204 -- f comes from jsonlFilePaths (controlled, hardcoded paths)
gitAdd = exec.Command("git", "add", f) gitAdd = exec.Command("git", "add", f)
} }
_ = gitAdd.Run() // Ignore errors - file may not exist _ = gitAdd.Run() // Ignore errors - file may not exist
@@ -697,7 +695,7 @@ func runPrePushHook(args []string) int {
// Check for uncommitted JSONL changes // Check for uncommitted JSONL changes
files := []string{} files := []string{}
for _, f := range []string{".beads/beads.jsonl", ".beads/issues.jsonl", ".beads/deletions.jsonl", ".beads/interactions.jsonl"} { for _, f := range jsonlFilePaths {
// Check if file exists or is tracked // Check if file exists or is tracked
if _, err := os.Stat(f); err == nil { if _, err := os.Stat(f); err == nil {
files = append(files, f) files = append(files, f)
@@ -707,7 +705,7 @@ func runPrePushHook(args []string) int {
if rcErr == nil { if rcErr == nil {
checkCmd = rc.GitCmdCWD(ctx, "ls-files", "--error-unmatch", f) checkCmd = rc.GitCmdCWD(ctx, "ls-files", "--error-unmatch", f)
} else { } else {
// #nosec G204 - f is from hardcoded list above, not user input // #nosec G204 - f is from jsonlFilePaths (controlled, hardcoded paths)
checkCmd = exec.Command("git", "ls-files", "--error-unmatch", f) checkCmd = exec.Command("git", "ls-files", "--error-unmatch", f)
} }
if checkCmd.Run() == nil { if checkCmd.Run() == nil {
@@ -1127,7 +1125,7 @@ func isRebaseInProgress() bool {
// hasBeadsJSONL checks if any JSONL file exists in .beads/. // hasBeadsJSONL checks if any JSONL file exists in .beads/.
func hasBeadsJSONL() bool { func hasBeadsJSONL() bool {
for _, f := range []string{".beads/beads.jsonl", ".beads/issues.jsonl", ".beads/deletions.jsonl", ".beads/interactions.jsonl"} { for _, f := range jsonlFilePaths {
if _, err := os.Stat(f); err == nil { if _, err := os.Stat(f); err == nil {
return true return true
} }