Merge upstream/main into subtle-ux-improvements

Resolves conflicts and converts new defer/undefer commands from
fatih/color to the lipgloss semantic color system.

Key changes:
- Added StatusDeferred case in graph.go with ui.RenderAccent
- Converted status.go to use ui package for colorized output
- Converted defer.go/undefer.go to use ui package
- Merged GroupID and Aliases for status command
- Updated pre-commit hook version to 0.31.0
- Ran go mod tidy to remove fatih/color dependency
This commit is contained in:
Ryan Snodgrass
2025-12-20 17:22:43 -08:00
45 changed files with 850 additions and 316 deletions

View File

@@ -409,7 +409,7 @@ func uninstallHooks() error {
// runPreCommitHook flushes pending changes to JSONL before commit.
// Returns 0 on success (or if not applicable), non-zero on error.
//
//nolint:unparam // Always returns 0 by design - warns but doesn't block commits
//nolint:unparam // Always returns 0 by design - warnings don't block commits
func runPreCommitHook() int {
// Check if we're in a bd workspace
if _, err := os.Stat(".beads"); os.IsNotExist(err) {
@@ -433,7 +433,7 @@ func runPreCommitHook() int {
// Stage all tracked JSONL files
for _, f := range []string{".beads/beads.jsonl", ".beads/issues.jsonl", ".beads/deletions.jsonl", ".beads/interactions.jsonl"} {
if _, err := os.Stat(f); err == nil {
// #nosec G204 -- f is a fixed string from the hardcoded slice above
// #nosec G204 - f is from hardcoded list above, not user input
gitAdd := exec.Command("git", "add", f)
_ = gitAdd.Run() // Ignore errors - file may not exist
}
@@ -445,7 +445,7 @@ func runPreCommitHook() int {
// runPostMergeHook imports JSONL after pull/merge.
// Returns 0 on success (or if not applicable), non-zero on error.
//
//nolint:unparam // Always returns 0 by design - warns but doesn't block merges
//nolint:unparam // Always returns 0 by design - warnings don't block merges
func runPostMergeHook() int {
// Skip during rebase
if isRebaseInProgress() {
@@ -510,7 +510,7 @@ func runPrePushHook() int {
files = append(files, f)
} else {
// Check if tracked by git
// #nosec G204 -- f is a fixed string from the hardcoded slice above
// #nosec G204 - f is from hardcoded list above, not user input
checkCmd := exec.Command("git", "ls-files", "--error-unmatch", f)
if checkCmd.Run() == nil {
files = append(files, f)
@@ -524,7 +524,7 @@ func runPrePushHook() int {
// Check for uncommitted changes using git status
args := append([]string{"status", "--porcelain", "--"}, files...)
// #nosec G204 -- args contains only fixed strings from hardcoded slice
// #nosec G204 - args built from hardcoded list and git subcommands
statusCmd := exec.Command("git", args...)
output, _ := statusCmd.Output()
if len(output) > 0 {
@@ -548,7 +548,7 @@ func runPrePushHook() int {
// args: [previous-HEAD, new-HEAD, flag] where flag=1 for branch checkout
// Returns 0 on success (or if not applicable), non-zero on error.
//
//nolint:unparam // Always returns 0 by design - warns but doesn't block checkouts
//nolint:unparam // Always returns 0 by design - warnings don't block checkouts
func runPostCheckoutHook(args []string) int {
// Only run on branch checkouts (flag=1)
if len(args) >= 3 && args[2] != "1" {