fix(lint): address gosec, misspell, and unparam warnings

- gate.go: fix "cancelled" → "canceled" misspelling, add #nosec for
  validated GitHub IDs in exec.Command, mark checkTimer escalated as
  intentionally false, rename unused ctx param
- sync_divergence.go: add #nosec for git commands with validated paths,
  mark unused path param
- sync_branch.go: add #nosec for .git/info/exclude permissions
- setup.go: add #nosec for config file permissions
- recipes.go: add #nosec for validated config file paths
- external_deps.go: add #nosec for SQL with generated placeholders

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
beads/crew/fang
2026-01-05 22:06:52 -08:00
committed by Steve Yegge
parent ee179f5b6d
commit 7b0f398f11
6 changed files with 19 additions and 17 deletions

View File

@@ -339,7 +339,7 @@ func addToGitExclude(path, pattern string) error {
}
// Append pattern
f, err := os.OpenFile(excludePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
f, err := os.OpenFile(excludePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) // #nosec G302 -- .git/info/exclude needs to be readable
if err != nil {
return fmt.Errorf("failed to open exclude file: %w", err)
}

View File

@@ -124,7 +124,7 @@ func checkJSONLGitDivergence(path, beadsDir string) *SyncDivergenceIssue {
}
// Check if file is tracked by git
cmd := exec.Command("git", "ls-files", "--error-unmatch", relPath)
cmd := exec.Command("git", "ls-files", "--error-unmatch", relPath) // #nosec G204 -- relPath is derived from validated file path
cmd.Dir = path
if err := cmd.Run(); err != nil {
// File not tracked by git
@@ -132,7 +132,7 @@ func checkJSONLGitDivergence(path, beadsDir string) *SyncDivergenceIssue {
}
// Compare current file with HEAD
cmd = exec.Command("git", "diff", "--quiet", "HEAD", "--", relPath)
cmd = exec.Command("git", "diff", "--quiet", "HEAD", "--", relPath) // #nosec G204 -- relPath is derived from validated file path
cmd.Dir = path
if err := cmd.Run(); err != nil {
// Exit code non-zero means there are differences
@@ -147,7 +147,7 @@ func checkJSONLGitDivergence(path, beadsDir string) *SyncDivergenceIssue {
}
// checkSQLiteMtimeDivergence checks if SQLite last_import_time matches JSONL mtime.
func checkSQLiteMtimeDivergence(path, beadsDir string) *SyncDivergenceIssue {
func checkSQLiteMtimeDivergence(_, beadsDir string) *SyncDivergenceIssue { //nolint:unparam // path reserved for future use
// Get database path
dbPath := filepath.Join(beadsDir, beads.CanonicalDatabaseName)
if cfg, err := configfile.Load(beadsDir); err == nil && cfg != nil && cfg.Database != "" {
@@ -235,7 +235,7 @@ func checkUncommittedBeadsChanges(path, beadsDir string) *SyncDivergenceIssue {
}
// Check for uncommitted changes in .beads/
cmd := exec.Command("git", "status", "--porcelain", "--", relBeadsDir)
cmd := exec.Command("git", "status", "--porcelain", "--", relBeadsDir) // #nosec G204 -- relBeadsDir is derived from validated path
cmd.Dir = path
out, err := cmd.Output()
if err != nil {

View File

@@ -442,7 +442,7 @@ A gate is resolved when:
- bead: target bead status=closed
A gate is escalated when:
- gh:run: status=completed AND conclusion in (failure, cancelled)
- gh:run: status=completed AND conclusion in (failure, canceled)
- gh:pr: state=CLOSED AND merged=false
Examples:
@@ -645,7 +645,7 @@ func checkGHRun(gate *types.Issue) (resolved, escalated bool, reason string, err
}
// Run: gh run view <id> --json status,conclusion,name
cmd := exec.Command("gh", "run", "view", gate.AwaitID, "--json", "status,conclusion,name")
cmd := exec.Command("gh", "run", "view", gate.AwaitID, "--json", "status,conclusion,name") // #nosec G204 -- gate.AwaitID is a validated GitHub run ID
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
@@ -676,8 +676,8 @@ func checkGHRun(gate *types.Issue) (resolved, escalated bool, reason string, err
return true, false, fmt.Sprintf("workflow '%s' succeeded", status.Name), nil
case "failure":
return false, true, fmt.Sprintf("workflow '%s' failed", status.Name), nil
case "cancelled":
return false, true, fmt.Sprintf("workflow '%s' was cancelled", status.Name), nil
case "cancelled", "canceled":
return false, true, fmt.Sprintf("workflow '%s' was canceled", status.Name), nil
case "skipped":
return true, false, fmt.Sprintf("workflow '%s' was skipped", status.Name), nil
default:
@@ -697,7 +697,7 @@ func checkGHPR(gate *types.Issue) (resolved, escalated bool, reason string, err
}
// Run: gh pr view <id> --json state,merged,title
cmd := exec.Command("gh", "pr", "view", gate.AwaitID, "--json", "state,merged,title")
cmd := exec.Command("gh", "pr", "view", gate.AwaitID, "--json", "state,merged,title") // #nosec G204 -- gate.AwaitID is a validated GitHub PR number
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
@@ -737,7 +737,8 @@ func checkGHPR(gate *types.Issue) (resolved, escalated bool, reason string, err
}
// checkTimer checks a timer gate for expiration
func checkTimer(gate *types.Issue, now time.Time) (resolved, escalated bool, reason string, err error) {
// Note: timers resolve but never escalate (escalated is always false by design)
func checkTimer(gate *types.Issue, now time.Time) (resolved, escalated bool, reason string, err error) { //nolint:unparam // escalated intentionally always false
if gate.Timeout == 0 {
return false, false, "timer gate without timeout configured", fmt.Errorf("no timeout set")
}
@@ -815,7 +816,7 @@ func checkBeadGate(ctx context.Context, awaitID string) (bool, string) {
}
// closeGate closes a gate issue with the given reason
func closeGate(ctx interface{}, gateID, reason string) error {
func closeGate(_ interface{}, gateID, reason string) error {
if daemonClient != nil {
closeArgs := &rpc.CloseArgs{
ID: gateID,

View File

@@ -131,7 +131,7 @@ func writeToPath(path string) error {
}
}
if err := os.WriteFile(path, []byte(recipes.Template), 0o644); err != nil {
if err := os.WriteFile(path, []byte(recipes.Template), 0o644); err != nil { // #nosec G306 -- config files need to be readable
return fmt.Errorf("write file: %w", err)
}
return nil
@@ -225,7 +225,7 @@ func runRecipe(name string) {
}
}
if err := os.WriteFile(recipe.Path, []byte(recipes.Template), 0o644); err != nil {
if err := os.WriteFile(recipe.Path, []byte(recipes.Template), 0o644); err != nil { // #nosec G306 -- config files need to be readable
fmt.Fprintf(os.Stderr, "Error: write file: %v\n", err)
os.Exit(1)
}