diff --git a/.github/actions/setup-deps/action.yml b/.github/actions/setup-deps/action.yml index b91abce1..777735ef 100644 --- a/.github/actions/setup-deps/action.yml +++ b/.github/actions/setup-deps/action.yml @@ -18,7 +18,7 @@ runs: GH_TOKEN: ${{ inputs.token }} run: | clone_with_retry() { - local repo=$1 dest=$2 branch=${3:-dev} + local repo=$1 dest=$2 branch=${3:-main} for i in 1 2 3; do git clone --depth=1 --branch "$branch" "https://x-access-token:${GH_TOKEN}@github.com/GrayCodeAI/${repo}.git" "$dest" && return 0 echo "Retry $i for $repo..." && sleep $((i * 5)) @@ -26,15 +26,15 @@ runs: echo "Failed to clone $repo after 3 attempts" && return 1 } mkdir -p external - clone_with_retry eyrie external/eyrie dev - clone_with_retry tok external/tok dev - clone_with_retry yaad external/yaad dev - clone_with_retry inspect external/inspect dev - clone_with_retry sight external/sight dev - clone_with_retry trace external/trace dev + clone_with_retry eyrie external/eyrie main + clone_with_retry tok external/tok main + clone_with_retry yaad external/yaad main + clone_with_retry inspect external/inspect main + clone_with_retry sight external/sight main + clone_with_retry trace external/trace main - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 with: go-version: ${{ inputs.go-version }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d62c2932..43e70b15 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -159,7 +159,7 @@ jobs: coverage=$(go tool cover -func=coverage.out | grep total | awk '{print $3}' | tr -d '%' | tail -1) echo "Coverage: ${coverage}%" echo "COVERAGE=${coverage}" >> "$GITHUB_ENV" - - name: Coverage threshold (minimum 50%) + - name: Coverage threshold (minimum 60%) run: | if (( $(echo "${COVERAGE} < 60" | bc -l) )); then echo "::error::Coverage ${COVERAGE}% is below minimum 60%" @@ -253,7 +253,6 @@ jobs: - name: Run markdownlint-cli2 run: | npm install -g markdownlint-cli2 - printf '%s\n' '{"config":{"default":true,"line-length":false,"no-inline-html":false,"first-line-h1":false,"no-duplicate-heading":false,"no-emphasis-as-heading":false,"blanks-around-headings":false,"blanks-around-lists":false,"blanks-around-fences":false,"fenced-code-language":false,"table-column-style":false,"no-space-in-emphasis":false,"ol-prefix":false,"link-fragments":false,"blanks-around-tables":false,"table-column-count":false,"single-trailing-newline":false}}' > .markdownlint-cli2.jsonc markdownlint-cli2 '**/*.md' # ------------------------------------------------------------------------- diff --git a/.golangci.yml b/.golangci.yml index cf12174d..f652489e 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -21,9 +21,7 @@ linters: enable-all: true disable: - fieldalignment - - shadow - unusedwrite - - nilness staticcheck: checks: - all @@ -32,14 +30,11 @@ linters: - -ST1020 - -ST1021 - -ST1018 - - -SA4006 - -SA5011 - -SA1012 - -SA2001 - -SA4011 - -S1039 - - -S1011 - - -S1034 - -QF1003 - -QF1011 - -S1008 diff --git a/.markdownlint-cli2.jsonc b/.markdownlint-cli2.jsonc new file mode 100644 index 00000000..d62067db --- /dev/null +++ b/.markdownlint-cli2.jsonc @@ -0,0 +1,21 @@ +{ + "config": { + "default": true, + "line-length": false, + "no-inline-html": false, + "first-line-h1": false, + "no-duplicate-heading": false, + "no-emphasis-as-heading": false, + "blanks-around-headings": false, + "blanks-around-lists": false, + "blanks-around-fences": false, + "fenced-code-language": false, + "table-column-style": false, + "no-space-in-emphasis": false, + "ol-prefix": false, + "link-fragments": false, + "blanks-around-tables": false, + "table-column-count": false, + "single-trailing-newline": false + } +} diff --git a/cmd/autoinit_test.go b/cmd/autoinit_test.go index 0ab53a43..efcbd50c 100644 --- a/cmd/autoinit_test.go +++ b/cmd/autoinit_test.go @@ -37,7 +37,7 @@ func TestAutoInitRunner_WritesContextFileOnce(t *testing.T) { } ctxFile := filepath.Join(root, autoInitContextFile) - if _, err := os.Stat(ctxFile); err != nil { + if _, statErr := os.Stat(ctxFile); statErr != nil { t.Fatalf("expected context file %s to be written: %v", autoInitContextFile, err) } diff --git a/cmd/chat.go b/cmd/chat.go index b4c0ee86..6966a440 100644 --- a/cmd/chat.go +++ b/cmd/chat.go @@ -273,8 +273,8 @@ func newChatModel(ref *progRef, systemPrompt string, settings hawkconfig.Setting startup.MarkPhase("newChatModel:configureSession") syncSessionFromPersistedSelection(sess, settings) sess.SetLogger(logger.New(io.Discard, logger.Error)) - if err := configureSession(sess, settings); err != nil { - return chatModel{}, err + if cfgErr := configureSession(sess, settings); cfgErr != nil { + return chatModel{}, cfgErr } startup.EndPhase("newChatModel:configureSession") @@ -399,15 +399,15 @@ func newChatModel(ref *progRef, systemPrompt string, settings hawkconfig.Setting // Prefetch live models for the active provider so footer ctx/pricing stay current. go func() { - provider := effectiveProvider - entries, _ := runtime.ListModels(context.Background(), runtime.ListModelsOpts{ProviderID: provider, Source: runtime.ListSourceAuto}) + providerName := effectiveProvider + entries, _ := runtime.ListModels(context.Background(), runtime.ListModelsOpts{ProviderID: providerName, Source: runtime.ListSourceAuto}) opts := configModelOptionsFromEyrie(entries) if len(opts) > 0 { modelCacheMu.Lock() - modelCache[provider] = opts + modelCache[providerName] = opts modelCacheMu.Unlock() if ref != nil { - ref.Send(modelsFetchedMsg{options: opts, provider: provider}) + ref.Send(modelsFetchedMsg{options: opts, provider: providerName}) } } }() @@ -1068,11 +1068,11 @@ func (m chatModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } m.viewDirty = true m.updateViewportContent() - cmds := []tea.Cmd{compactTickCmd()} + localCmds := []tea.Cmd{compactTickCmd()} if !m.input.Focused() { - cmds = append(cmds, m.input.Focus()) + localCmds = append(localCmds, m.input.Focus()) } - return m, tea.Batch(cmds...) + return m, tea.Batch(localCmds...) } return m, nil @@ -1306,7 +1306,7 @@ func autoIndexCodegraph() { } dbPath := filepath.Join(cwd, ".codegraph", "codegraph.db") - if _, err := os.Stat(dbPath); os.IsNotExist(err) { + if _, statErr := os.Stat(dbPath); os.IsNotExist(statErr) { return // Not initialized, skip } @@ -1367,9 +1367,9 @@ func runChat() error { ctx, cancel := context.WithCancel(context.Background()) _ = cancel // will be cancelled when program exits go func() { - ch, err := sess.Stream(ctx) - if err != nil { - p.Send(streamErrMsg{err: err}) + ch, streamErr := sess.Stream(ctx) + if streamErr != nil { + p.Send(streamErrMsg{err: streamErr}) return } pumpStreamEvents(ref, ch) diff --git a/cmd/chat_commands.go b/cmd/chat_commands.go index 1e2184cc..d558ff2b 100644 --- a/cmd/chat_commands.go +++ b/cmd/chat_commands.go @@ -802,9 +802,9 @@ Generate the recap:`, summary.String()) case "/check": return m.startPromptCommand("/check", buildCheckPrompt()) case "/design": - parts := strings.Fields(text) - if len(parts) >= 2 { - switch parts[1] { + fields := strings.Fields(text) + if len(fields) >= 2 { + switch fields[1] { case "screenshot": path := strings.TrimSpace(strings.TrimPrefix(text, "/design screenshot")) if path == "" { @@ -922,11 +922,11 @@ Generate the recap:`, summary.String()) m.messages = append(m.messages, displayMsg{role: "error", content: err.Error()}) return m, nil } - model, provider := effectiveModelAndProvider(settings) - if provider == "" { - provider = "auto" + modelName, providerName := effectiveModelAndProvider(settings) + if providerName == "" { + providerName = "auto" } - m.messages = append(m.messages, displayMsg{role: "system", content: hawkconfig.FormatEcosystemPanel(context.Background(), provider, model)}) + m.messages = append(m.messages, displayMsg{role: "system", content: hawkconfig.FormatEcosystemPanel(context.Background(), providerName, modelName)}) return m, nil case "/path": m.messages = append(m.messages, displayMsg{role: "system", content: hawkconfig.FormatDeveloperPathReport(context.Background())}) @@ -1294,11 +1294,11 @@ Generate the recap:`, summary.String()) return } - text := strings.TrimSpace(string(transcription)) - if text != "" { - m.input.SetValue(text) + transcript := strings.TrimSpace(string(transcription)) + if transcript != "" { + m.input.SetValue(transcript) m.input.CursorEnd() - m.messages = append(m.messages, displayMsg{role: "system", content: fmt.Sprintf("Voice input: %s", text)}) + m.messages = append(m.messages, displayMsg{role: "system", content: fmt.Sprintf("Voice input: %s", transcript)}) } }() } diff --git a/cmd/chat_config_keys.go b/cmd/chat_config_keys.go index d5c6d849..a02d3250 100644 --- a/cmd/chat_config_keys.go +++ b/cmd/chat_config_keys.go @@ -37,16 +37,16 @@ func (m chatModel) configKeyDetailView() string { mutedStyle := configMutedStyle() accentStyle := configAccentStyle() activeStyle := configActiveStyle() - provider := strings.TrimSpace(m.configProvider) - displayName := hawkconfig.GatewayDisplayName(provider) - masked := hawkconfig.MaskCredentialForProvider(context.Background(), provider) + providerName := strings.TrimSpace(m.configProvider) + displayName := hawkconfig.GatewayDisplayName(providerName) + masked := hawkconfig.MaskCredentialForProvider(context.Background(), providerName) var b strings.Builder b.WriteString(renderConfigBreadcrumb(displayName+" key") + "\n\n") b.WriteString(mutedStyle.Render(" Gateway: ") + accentStyle.Render(displayName) + "\n") b.WriteString(mutedStyle.Render(" Key: ") + activeStyle.Render(masked) + "\n") b.WriteString(mutedStyle.Render(" Stored in: "+credentialsStoreLabel()) + "\n") - if provider == hawkconfig.ProviderXiaomiTokenPlan { + if providerName == hawkconfig.ProviderXiaomiTokenPlan { reg := hawkconfig.XiaomiTokenPlanRegionLabel() if reg == "" { reg = "(not set — press g)" @@ -111,13 +111,13 @@ func (m chatModel) clearConfigGatewayKeyRemove() chatModel { } func (m chatModel) advanceConfigGatewayKeyRemove() (chatModel, tea.Cmd) { - provider := strings.TrimSpace(m.configKeysPendingRemove) - if provider == "" { + trimmedProvider := strings.TrimSpace(m.configKeysPendingRemove) + if trimmedProvider == "" { return m, nil } if m.configKeysRemoveStep < 2 { m.configKeysRemoveStep = 2 - name := hawkconfig.GatewayDisplayName(provider) + name := hawkconfig.GatewayDisplayName(trimmedProvider) m.configNotice = configGatewayRemoveNotice(2, name) return m, nil } @@ -125,47 +125,47 @@ func (m chatModel) advanceConfigGatewayKeyRemove() (chatModel, tea.Cmd) { } func (m chatModel) confirmConfigGatewayKeyRemove() (chatModel, tea.Cmd) { - provider := strings.TrimSpace(m.configKeysPendingRemove) - if provider == "" { + trimmedProvider := strings.TrimSpace(m.configKeysPendingRemove) + if trimmedProvider == "" { return m, nil } m.configKeysPendingRemove = "" m.configKeysRemoveStep = 0 m.configSaving = true - m.configNotice = fmt.Sprintf("Removing key for %s…", hawkconfig.GatewayDisplayName(provider)) + m.configNotice = fmt.Sprintf("Removing key for %s…", hawkconfig.GatewayDisplayName(trimmedProvider)) if m.configEntry == configEntryKeyView { m.configEntry = configEntryNone m.configProvider = "" } - return m, removeCredentialAsync(provider) + return m, removeCredentialAsync(trimmedProvider) } func (m chatModel) handleConfigKeyViewKey(msg tea.KeyMsg) (chatModel, tea.Cmd) { - provider := strings.TrimSpace(m.configProvider) + trimmedProvider := strings.TrimSpace(m.configProvider) switch msg.Type { case tea.KeyEsc: m.configEntry = configEntryNone m.configProvider = "" m = m.clearConfigGatewayKeyRemove() - if idx := m.configGatewayRowIndex(provider); idx >= 0 { + if idx := m.configGatewayRowIndex(trimmedProvider); idx >= 0 { m.configSel = idx } return m, nil case tea.KeyDelete, tea.KeyBackspace: - if provider == "" { + if trimmedProvider == "" { return m, nil } - return m.beginConfigGatewayKeyRemove(provider), nil + return m.beginConfigGatewayKeyRemove(trimmedProvider), nil case tea.KeyEnter: if m.configKeysPendingRemove != "" { return m.advanceConfigGatewayKeyRemove() } - if provider == "" { + if trimmedProvider == "" { return m, nil } - return m.startConfigKeyReplace(provider) + return m.startConfigKeyReplace(trimmedProvider) case tea.KeyRunes: - if provider == hawkconfig.ProviderXiaomiTokenPlan && strings.EqualFold(string(msg.Runes), "g") { + if trimmedProvider == hawkconfig.ProviderXiaomiTokenPlan && strings.EqualFold(string(msg.Runes), "g") { return m.startConfigXiaomiTokenPlanRegion(), nil } default: diff --git a/cmd/chat_config_panel.go b/cmd/chat_config_panel.go index b092da54..718e7bae 100644 --- a/cmd/chat_config_panel.go +++ b/cmd/chat_config_panel.go @@ -77,14 +77,14 @@ func (m chatModel) configPanelView() string { func (m chatModel) configProviderKeyView() string { titleStyle := configTitleStyle() mutedStyle := configMutedStyle() - provider := strings.TrimSpace(m.configProvider) + providerName := strings.TrimSpace(m.configProvider) title := "🔑 Paste API key" hint := "validates with provider API · stored in " + credentialsStoreLabel() - if provider != "" { - title = "🔑 " + hawkconfig.GatewayDisplayName(provider) + if providerName != "" { + title = "🔑 " + hawkconfig.GatewayDisplayName(providerName) hint = "paste key for this gateway only · " + hint } - if provider == hawkconfig.ProviderXiaomiTokenPlan { + if providerName == hawkconfig.ProviderXiaomiTokenPlan { reg := hawkconfig.XiaomiTokenPlanRegionLabel() if reg == "" { reg = "not set — esc and pick region with g or enter on gateway row" @@ -243,8 +243,8 @@ func (m chatModel) configPanelViewWidth() int { func (m chatModel) configActiveModelID() string { if m.session != nil { - if model := strings.TrimSpace(m.session.Model()); model != "" { - return model + if modelName := strings.TrimSpace(m.session.Model()); modelName != "" { + return modelName } } return strings.TrimSpace(hawkconfig.ActiveModel(context.Background())) @@ -448,37 +448,37 @@ func (m chatModel) finishConfigEntry() (chatModel, tea.Cmd) { return m, saveOllamaAsync(value) case configEntryAPIKeyPaste: if value == "" { - provider := strings.TrimSpace(m.configProvider) + providerName := strings.TrimSpace(m.configProvider) m.configEntry = configEntryNone m.configProvider = "" m.wipeConfigKeyInput() m.restoreChatInput() m.configTab = configTabGateways m.configNotice = "No API key entered — paste your key, then press enter" - if provider != "" { - if idx := m.configGatewayRowIndex(provider); idx >= 0 { + if providerName != "" { + if idx := m.configGatewayRowIndex(providerName); idx >= 0 { m.configSel = idx } } return m, nil } - provider := strings.TrimSpace(m.configReplaceProvider) - if provider == "" { - provider = strings.TrimSpace(m.configProvider) + providerName := strings.TrimSpace(m.configReplaceProvider) + if providerName == "" { + providerName = strings.TrimSpace(m.configProvider) } m.configReplaceProvider = "" - if provider == "" { + if providerName == "" { m.configNotice = "Select a gateway on the Gateways tab first" m.configEntry = configEntryNone m.wipeConfigKeyInput() m.restoreChatInput() return m, nil } - if provider == hawkconfig.ProviderXiaomiTokenPlan && hawkconfig.NeedsXiaomiTokenPlanRegion(provider) { + if providerName == hawkconfig.ProviderXiaomiTokenPlan && hawkconfig.NeedsXiaomiTokenPlanRegion(providerName) { m.configEntry = configEntryNone m.wipeConfigKeyInput() m.restoreChatInput() - m.configPostSaveKeysProvider = provider + m.configPostSaveKeysProvider = providerName m.configNotice = "Pick Token Plan region before pasting key" return m.startConfigXiaomiTokenPlanRegion(), nil } @@ -486,21 +486,21 @@ func (m chatModel) finishConfigEntry() (chatModel, tea.Cmd) { m.configProvider = "" m.wipeConfigKeyInput() m.restoreChatInput() - inference, err := hawkconfig.CredentialInferenceForProvider(provider) + inference, err := hawkconfig.CredentialInferenceForProvider(providerName) if err != nil { m.configTab = configTabGateways m.configNotice = "Could not save key: " + sanitizeConfigNotice(err.Error()) - if idx := m.configGatewayRowIndex(provider); idx >= 0 { + if idx := m.configGatewayRowIndex(providerName); idx >= 0 { m.configSel = idx } return m, nil } - m.configPostSaveKeysProvider = provider + m.configPostSaveKeysProvider = providerName m.configSaving = true notice := fmt.Sprintf("Validating key for %s…", inference.DisplayName) - if hint := xiaomi.KeyMismatchHint(xiaomi.BillingTokenPlan, value); provider == hawkconfig.ProviderXiaomiTokenPlan && hint != "" { + if hint := xiaomi.KeyMismatchHint(xiaomi.BillingTokenPlan, value); providerName == hawkconfig.ProviderXiaomiTokenPlan && hint != "" { notice = hint + " · " + notice - } else if hint := xiaomi.KeyMismatchHint(xiaomi.BillingPayAsYouGo, value); provider == xiaomi.ProviderPayAsYouGo && hint != "" { + } else if hint := xiaomi.KeyMismatchHint(xiaomi.BillingPayAsYouGo, value); providerName == xiaomi.ProviderPayAsYouGo && hint != "" { notice = hint + " · " + notice } m.configNotice = notice @@ -528,17 +528,17 @@ func (m chatModel) handleConfigEntryKey(msg tea.KeyMsg) (chatModel, tea.Cmd) { m.restoreChatInput() return m, nil case configEntryAPIKeyPaste: - provider := strings.TrimSpace(m.configReplaceProvider) - if provider == "" { - provider = strings.TrimSpace(m.configProvider) + providerName := strings.TrimSpace(m.configReplaceProvider) + if providerName == "" { + providerName = strings.TrimSpace(m.configProvider) } m.configReplaceProvider = "" m.configEntry = configEntryNone m.configProvider = "" m.wipeConfigKeyInput() m.restoreChatInput() - if provider != "" { - if idx := m.configGatewayRowIndex(provider); idx >= 0 { + if providerName != "" { + if idx := m.configGatewayRowIndex(providerName); idx >= 0 { m.configSel = idx } } diff --git a/cmd/chat_config_save_flow_test.go b/cmd/chat_config_save_flow_test.go index 917c7366..d91b3fce 100644 --- a/cmd/chat_config_save_flow_test.go +++ b/cmd/chat_config_save_flow_test.go @@ -109,7 +109,7 @@ func TestConfigGatewaysSelect_AddKeyOpensPaste(t *testing.T) { } } if sel < 0 { - t.Skip("all gateways already have keys in this environment") + t.Skip("all gateways already have keys in this environment") // TODO: https://github.com/GrayCodeAI/hawk/issues/28 } m.configSel = sel next, _ := m.handleConfigGatewaysSelect() diff --git a/cmd/chat_config_ui.go b/cmd/chat_config_ui.go index 7778d17c..5a965635 100644 --- a/cmd/chat_config_ui.go +++ b/cmd/chat_config_ui.go @@ -47,7 +47,7 @@ func renderConfigGatewayLine(displayName string) string { } func renderConfigStatusLine(m chatModel) string { - gateway, model, configured := m.configStatus() + gateway, modelName, configured := m.configStatus() muted := configMutedStyle().Inline(true) accent := configAccentStyle().Inline(true) active := configActiveStyle().Inline(true) @@ -70,10 +70,10 @@ func renderConfigStatusLine(m chatModel) string { muted.Render("Gateway: "), gatewayStyle.Render(gateway), } - if model == "" { + if modelName == "" { parts = append(parts, muted.Render(" · no model selected")) } else { - parts = append(parts, muted.Render(" · Model: "), active.Render(model)) + parts = append(parts, muted.Render(" · Model: "), active.Render(modelName)) } return lipgloss.JoinHorizontal(lipgloss.Left, parts...) } diff --git a/cmd/chat_model_test.go b/cmd/chat_model_test.go index 1c4fff13..62a781b0 100644 --- a/cmd/chat_model_test.go +++ b/cmd/chat_model_test.go @@ -150,7 +150,7 @@ func TestChatModel_SlashUnknown(t *testing.T) { } func TestChatModel_ManyCommands(t *testing.T) { - t.Skip("flaky: race condition with global state access") + t.Skip("flaky: race condition with global state access") // TODO: https://github.com/GrayCodeAI/hawk/issues/26 commands := []string{ "/context", "/env", "/hooks", "/stats", "/compact", "/diff", "/branch", "/vim", @@ -224,7 +224,7 @@ func TestChatModel_SlashExport(t *testing.T) { } func TestChatModel_StreamingCommands(t *testing.T) { - t.Skip("flaky: race condition with startStream goroutines") + t.Skip("flaky: race condition with startStream goroutines") // TODO: https://github.com/GrayCodeAI/hawk/issues/27 // These trigger startStream but progRef is nil-safe so they won't panic commands := []string{ "/doctor", "/commit", "/review", diff --git a/cmd/chat_print.go b/cmd/chat_print.go index a20b07b3..5e552f12 100644 --- a/cmd/chat_print.go +++ b/cmd/chat_print.go @@ -39,8 +39,8 @@ func runPrint(text string) error { sess := newHawkSession(settings, effectiveProvider, effectiveModel, systemPrompt, registry) sess.SetLogger(logger.New(io.Discard, logger.Error)) - if err := configureSession(sess, settings); err != nil { - return err + if cfgErr := configureSession(sess, settings); cfgErr != nil { + return cfgErr } reader := bufio.NewReader(os.Stdin) @@ -261,8 +261,8 @@ func runRepl() error { sess := newHawkSession(settings, effectiveProvider, effectiveModel, systemPrompt, registry) sess.SetLogger(logger.New(io.Discard, logger.Error)) - if err := configureSession(sess, settings); err != nil { - return err + if cfgErr := configureSession(sess, settings); cfgErr != nil { + return cfgErr } reader := bufio.NewReader(os.Stdin) diff --git a/cmd/chat_status.go b/cmd/chat_status.go index b3353384..8a312eeb 100644 --- a/cmd/chat_status.go +++ b/cmd/chat_status.go @@ -59,14 +59,14 @@ func (m *chatModel) invalidateConnStatus() { } func (m chatModel) connStatusFingerprint() string { - gw, model := m.sessionGatewayModel() + gw, modelName := m.sessionGatewayModel() creds := strings.Join(hawkconfig.ConfiguredCredentialProviders(), ",") api := 0 if m.session != nil { api = m.session.LastPromptTokens() } used := sessionContextUsedTokens(m.session) - return gw + "\x00" + model + "\x00" + creds + "\x00" + fmt.Sprintf("%d", used) + "\x00" + fmt.Sprintf("%d", api) + return gw + "\x00" + modelName + "\x00" + creds + "\x00" + fmt.Sprintf("%d", used) + "\x00" + fmt.Sprintf("%d", api) } func (m chatModel) sessionGatewayModel() (gateway, model string) { @@ -103,11 +103,11 @@ func (m *chatModel) chatConnectionStatus() string { } func (m chatModel) buildConnectionStatusPlain() string { - gw, model, ctxLabel := m.connectionStatusParts() - if gw == "" && model == "" { + gw, modelName, ctxLabel := m.connectionStatusParts() + if gw == "" && modelName == "" { return "pick model" } - if model == "" { + if modelName == "" { if gw == "" { return "pick model" } @@ -116,13 +116,13 @@ func (m chatModel) buildConnectionStatusPlain() string { if ctxLabel != "" && ctxLabel != "—" { ctxText := formatConnectionContextLabel(m, ctxLabel) if ctxText != "" { - return fmt.Sprintf("%s · %s · %s", gw, model, ctxText) + return fmt.Sprintf("%s · %s · %s", gw, modelName, ctxText) } } if gw == "" { - return model + return modelName } - return gw + " · " + model + return gw + " · " + modelName } func (m chatModel) connectionStatusParts() (gateway, model, contextLabel string) { @@ -167,9 +167,9 @@ func (m chatModel) renderConnectionStatusSplit() (modelRendered string, modelVis return "", 0, "", 0 } - gw, model, ctxLabel := m.connectionStatusParts() + gw, modelName, ctxLabel := m.connectionStatusParts() ctxText := formatConnectionContextLabel(m, ctxLabel) - modelRendered, modelVis = renderChatConnectionModel(gw, model) + modelRendered, modelVis = renderChatConnectionModel(gw, modelName) if ctxText != "" { ctxRendered, ctxVis = renderChatConnectionContext(ctxText, contextUsagePercent(m, ctxLabel)) } diff --git a/cmd/chat_welcome.go b/cmd/chat_welcome.go index 2883a55b..82501ce4 100644 --- a/cmd/chat_welcome.go +++ b/cmd/chat_welcome.go @@ -157,13 +157,13 @@ func buildWelcomeMessage(sess *engine.Session, sessionID string, registry *tool. } if forGate { - if model, provider := effectiveModelAndProvider(settings); model != "" { + if modelName, providerName := effectiveModelAndProvider(settings); modelName != "" { var plainParts, styledParts []string - if provider != "" { - plainParts = append(plainParts, provider) - styledParts = append(styledParts, mutedC+provider+rst) + if providerName != "" { + plainParts = append(plainParts, providerName) + styledParts = append(styledParts, mutedC+providerName+rst) } - short := normalizeModelDisplayName(model, model) + short := normalizeModelDisplayName(modelName, modelName) plainParts = append(plainParts, short) styledParts = append(styledParts, bodyC+short+rst) mode := permissionModeLabel(sess) @@ -313,8 +313,8 @@ func envSummaryWithSelection(provider, model string, includeSelection bool) stri func configCommandSummary(settings hawkconfig.Settings) string { _ = settings - provider := displayConfigValue(hawkconfig.ActiveProvider(context.TODO())) - model := displayConfigValue(hawkconfig.ActiveModel(context.TODO())) + providerName := displayConfigValue(hawkconfig.ActiveProvider(context.Background())) + modelName := displayConfigValue(hawkconfig.ActiveModel(context.Background())) return fmt.Sprintf(`Setup (eyrie) /config → paste API key (OS keychain) + pick model @@ -326,7 +326,7 @@ Current: model: %s keys: %s -Model catalog and routing live in eyrie — hawk is the UI only.`, provider, model, configuredKeyList()) +Model catalog and routing live in eyrie — hawk is the UI only.`, providerName, modelName, configuredKeyList()) } func apiKeyConfigSummary() string { diff --git a/cmd/cmdhistory_cmd.go b/cmd/cmdhistory_cmd.go index ffccf9fc..a7416fd6 100644 --- a/cmd/cmdhistory_cmd.go +++ b/cmd/cmdhistory_cmd.go @@ -83,8 +83,8 @@ var cmdHistoryRecentCmd = &cobra.Command{ n := 20 if len(args) > 0 { - parsed, err := strconv.Atoi(args[0]) - if err != nil { + parsed, parseErr := strconv.Atoi(args[0]) + if parseErr != nil { return fmt.Errorf("invalid number: %s", args[0]) } n = parsed @@ -165,8 +165,8 @@ func openCmdHistoryStore() (*cmdhistory.Store, error) { dbPath := filepath.Join(home, ".hawk", "cmd-history.db") // Ensure the directory exists. - if err := os.MkdirAll(filepath.Dir(dbPath), 0o755); err != nil { - return nil, fmt.Errorf("cannot create history directory: %w", err) + if mkErr := os.MkdirAll(filepath.Dir(dbPath), 0o755); mkErr != nil { + return nil, fmt.Errorf("cannot create history directory: %w", mkErr) } store, err := cmdhistory.New(dbPath) diff --git a/cmd/daemon.go b/cmd/daemon.go index 1da9fac2..c93f4a58 100644 --- a/cmd/daemon.go +++ b/cmd/daemon.go @@ -213,8 +213,8 @@ func runDaemonStop(_ *cobra.Command, _ []string) error { PID int `json:"pid"` Addr string `json:"addr"` } - if err := json.Unmarshal(data, &info); err != nil { - return fmt.Errorf("invalid PID file: %w", err) + if unmarshalErr := json.Unmarshal(data, &info); unmarshalErr != nil { + return fmt.Errorf("invalid PID file: %w", unmarshalErr) } proc, err := os.FindProcess(info.PID) @@ -246,7 +246,7 @@ func runDaemonStatus(_ *cobra.Command, _ []string) error { Addr string `json:"addr"` StartedAt string `json:"started_at"` } - if err := json.Unmarshal(data, &info); err != nil { + if unmarshalErr := json.Unmarshal(data, &info); unmarshalErr != nil { fmt.Println("Status: unknown (invalid PID file)") return nil } diff --git a/cmd/daemon_ready_test.go b/cmd/daemon_ready_test.go index 778bd67c..fb1feddf 100644 --- a/cmd/daemon_ready_test.go +++ b/cmd/daemon_ready_test.go @@ -55,7 +55,7 @@ func TestDaemonReadyProbe_AffectsReadyEndpoint(t *testing.T) { // Wait for the listener. deadline := time.Now().Add(2 * time.Second) for time.Now().Before(deadline) { - if c, err := net.DialTimeout("tcp", addr, 50*time.Millisecond); err == nil { + if c, dialErr := net.DialTimeout("tcp", addr, 50*time.Millisecond); dialErr == nil { c.Close() break } diff --git a/cmd/diagnostics.go b/cmd/diagnostics.go index 7766a57b..c94f7b69 100644 --- a/cmd/diagnostics.go +++ b/cmd/diagnostics.go @@ -23,9 +23,9 @@ import ( ) func doctorReport(settings hawkconfig.Settings) string { - modelName, provider := effectiveModelAndProvider(settings) - if provider == "" { - provider = "auto" + modelName, providerName := effectiveModelAndProvider(settings) + if providerName == "" { + providerName = "auto" } if modelName == "" { modelName = "default" @@ -37,7 +37,7 @@ func doctorReport(settings hawkconfig.Settings) string { b.WriteString(fmt.Sprintf("Version: %s\n", version)) b.WriteString(fmt.Sprintf("Go version: %s\n", runtime.Version())) b.WriteString(fmt.Sprintf("Directory: %s\n", cwd)) - b.WriteString(fmt.Sprintf("Provider: %s\n", provider)) + b.WriteString(fmt.Sprintf("Provider: %s\n", providerName)) b.WriteString(fmt.Sprintf("Model: %s\n", modelName)) // Binary size diff --git a/cmd/dx.go b/cmd/dx.go index 29eaf055..0c640d9b 100644 --- a/cmd/dx.go +++ b/cmd/dx.go @@ -67,10 +67,10 @@ func doctorOutput(settings hawkconfig.Settings) string { } b.WriteString("\nProvider:\n") b.WriteString(fmt.Sprintf(" Provider: %s\n", effectiveProvider)) - b.WriteString(fmt.Sprintf(" API key: %s\n", maskedKeyStatus(hawkconfig.ActiveProvider(context.TODO())))) + b.WriteString(fmt.Sprintf(" API key: %s\n", maskedKeyStatus(hawkconfig.ActiveProvider(context.Background())))) // Model configured (eyrie provider.json) - effectiveModel := strings.TrimSpace(hawkconfig.ActiveModel(context.TODO())) + effectiveModel := strings.TrimSpace(hawkconfig.ActiveModel(context.Background())) if effectiveModel == "" { effectiveModel = "(not configured)" } diff --git a/cmd/ecosystem.go b/cmd/ecosystem.go index 21cb32f1..168e63f0 100644 --- a/cmd/ecosystem.go +++ b/cmd/ecosystem.go @@ -16,11 +16,11 @@ var ecosystemCmd = &cobra.Command{ if err != nil { return err } - model, provider := effectiveModelAndProvider(settings) - if provider == "" { - provider = "auto" + modelName, providerName := effectiveModelAndProvider(settings) + if providerName == "" { + providerName = "auto" } - cmd.Println(hawkconfig.FormatEcosystemPanel(context.Background(), provider, model)) + cmd.Println(hawkconfig.FormatEcosystemPanel(context.Background(), providerName, modelName)) return nil }, } diff --git a/cmd/errors.go b/cmd/errors.go index 7cafb9e4..83a5c42e 100644 --- a/cmd/errors.go +++ b/cmd/errors.go @@ -377,20 +377,20 @@ func validateStartup(settings hawkconfig.Settings) []StartupWarning { var warnings []StartupWarning // 1. Check API key for configured provider - provider := hawkconfig.NormalizeProviderForEngine(settings.Provider) - if provider != "" && provider != "ollama" { - envKey := hawkconfig.ProviderAPIKeyEnv(provider) + providerName := hawkconfig.NormalizeProviderForEngine(settings.Provider) + if providerName != "" && providerName != "ollama" { + envKey := hawkconfig.ProviderAPIKeyEnv(providerName) if envKey != "" && os.Getenv(envKey) == "" { warnings = append(warnings, StartupWarning{ Check: "api_key", - Message: fmt.Sprintf("No API key found for %s. Set %s in your environment or run /config.", provider, envKey), + Message: fmt.Sprintf("No API key found for %s. Set %s in your environment or run /config.", providerName, envKey), }) } } // 2. Quick network reachability check (DNS lookup, no full HTTP request) - if provider != "" && provider != "ollama" { - host := providerDNSHost(provider) + if providerName != "" && providerName != "ollama" { + host := providerDNSHost(providerName) if host != "" { if _, err := net.LookupHost(host); err != nil { warnings = append(warnings, StartupWarning{ diff --git a/cmd/eval.go b/cmd/eval.go index ddd981a8..ea358595 100644 --- a/cmd/eval.go +++ b/cmd/eval.go @@ -124,15 +124,15 @@ func runEval(_ *cobra.Command, _ []string) error { return fmt.Errorf("no tasks matched the given filters") } - model := evalModel - if model == "" { - model = "default" + modelName := evalModel + if modelName == "" { + modelName = "default" } - fmt.Printf("Running %d tasks with model %s...\n", len(tasks), model) + fmt.Printf("Running %d tasks with model %s...\n", len(tasks), modelName) suite := &eval.BenchmarkSuite{Name: "hawk-eval", Tasks: tasks} - runner := eval.NewRunner(model, "") + runner := eval.NewRunner(modelName, "") runner.NoCache = evalNoCache if !evalNoCache { runner.Cache = eval.DefaultCache() diff --git a/cmd/eval_tools.go b/cmd/eval_tools.go index 9a207816..98e6b12c 100644 --- a/cmd/eval_tools.go +++ b/cmd/eval_tools.go @@ -78,8 +78,8 @@ func runEvalTools(cmd *cobra.Command, _ []string) error { if err != nil { return err } - model, provider := effectiveModelAndProvider(settings) - sess := newHawkSession(settings, provider, model, systemPrompt, registry) + modelName, providerName := effectiveModelAndProvider(settings) + sess := newHawkSession(settings, providerName, modelName, systemPrompt, registry) if err := configureSession(sess, settings); err != nil { return err } diff --git a/cmd/exec.go b/cmd/exec.go index 5a080963..ed869112 100644 --- a/cmd/exec.go +++ b/cmd/exec.go @@ -145,8 +145,8 @@ func runExec(_ *cobra.Command, args []string) error { } if execCWD != "" { - if err := os.Chdir(execCWD); err != nil { - return fmt.Errorf("chdir %s: %w", execCWD, err) + if chdirErr := os.Chdir(execCWD); chdirErr != nil { + return fmt.Errorf("chdir %s: %w", execCWD, chdirErr) } } @@ -166,8 +166,8 @@ func runExec(_ *cobra.Command, args []string) error { } wtBranch = branch defer cleanupExecWorktree(cwd, wtPath) - if err := os.Chdir(wtPath); err != nil { - return fmt.Errorf("chdir worktree: %w", err) + if chdirErr := os.Chdir(wtPath); chdirErr != nil { + return fmt.Errorf("chdir worktree: %w", chdirErr) } } @@ -183,9 +183,9 @@ func runExec(_ *cobra.Command, args []string) error { // If --agent is specified, prepend the agent persona var agentModel string if execAgent != "" { - agentDef, err := agents.Get(execAgent) - if err != nil { - return fmt.Errorf("agent %q: %w", execAgent, err) + agentDef, lookupErr := agents.Get(execAgent) + if lookupErr != nil { + return fmt.Errorf("agent %q: %w", execAgent, lookupErr) } systemPrompt = agentDef.Prompt + "\n\n" + systemPrompt agentModel = agentDef.Model @@ -211,8 +211,8 @@ func runExec(_ *cobra.Command, args []string) error { sess := newHawkSession(settings, effectiveProvider, effectiveModel, systemPrompt, registry) sess.SetLogger(logger.New(io.Discard, logger.Error)) - if err := configureSession(sess, settings, execMaxTurns); err != nil { - return err + if cfgErr := configureSession(sess, settings, execMaxTurns); cfgErr != nil { + return cfgErr } // Apply autonomy level @@ -231,9 +231,9 @@ func runExec(_ *cobra.Command, args []string) error { // Resume existing session if --session-id provided if execSessionID != "" { - saved, err := session.Load(execSessionID) - if err != nil { - return fmt.Errorf("resume session %s: %w", execSessionID, err) + saved, lookupErr := session.Load(execSessionID) + if lookupErr != nil { + return fmt.Errorf("resume session %s: %w", execSessionID, lookupErr) } sess.LoadMessages(toEyrieMessages(saved.Messages)) } diff --git a/cmd/feedback.go b/cmd/feedback.go index 73db104f..82819b72 100644 --- a/cmd/feedback.go +++ b/cmd/feedback.go @@ -95,8 +95,8 @@ func saveFeedbackLocal(report FeedbackReport) error { } dir := filepath.Join(home, ".hawk", "feedback") - if err := os.MkdirAll(dir, 0o755); err != nil { - return fmt.Errorf("create feedback directory: %w", err) + if mkErr := os.MkdirAll(dir, 0o755); mkErr != nil { + return fmt.Errorf("create feedback directory: %w", mkErr) } filename := fmt.Sprintf("feedback-%s.json", time.Now().Format("20060102-150405")) diff --git a/cmd/models.go b/cmd/models.go index 7235f712..234c9548 100644 --- a/cmd/models.go +++ b/cmd/models.go @@ -55,11 +55,11 @@ var modelsStatusCmd = &cobra.Command{ if err != nil { return err } - model, _ := effectiveModelAndProvider(settings) + modelName, _ := effectiveModelAndProvider(settings) if len(args) > 0 { - model = args[0] + modelName = args[0] } - report, err := hawkconfig.DeploymentStatusReport(ctx, model) + report, err := hawkconfig.DeploymentStatusReport(ctx, modelName) if err != nil { return err } @@ -73,8 +73,8 @@ var modelsRoutingPreviewCmd = &cobra.Command{ Short: "Print effective deployment routing JSON for a model", Args: cobra.MinimumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - model := args[0] - out, err := hawkconfig.RoutingPreviewJSON(context.Background(), model) + modelName := args[0] + out, err := hawkconfig.RoutingPreviewJSON(context.Background(), modelName) if err != nil { return err } @@ -87,20 +87,20 @@ var modelsListCmd = &cobra.Command{ Use: "list [provider]", Short: "List models from the eyrie catalog cache (or live provider API)", RunE: func(cmd *cobra.Command, args []string) error { - provider := "" + providerName := "" if len(args) > 0 { - provider = args[0] + providerName = args[0] } ctx := context.Background() var models []catalog.ModelCatalogEntry var err error if modelsListLive { - if provider == "" { + if providerName == "" { return fmt.Errorf("provider required with --live (e.g. hawk models list canopywave --live --json)") } - models, err = catalog.FetchLiveModelEntriesForProvider(eyriecfg.DiscoveryEnvMap(ctx), hawkconfig.NormalizeProviderForEngine(provider)) + models, err = catalog.FetchLiveModelEntriesForProvider(eyriecfg.DiscoveryEnvMap(ctx), hawkconfig.NormalizeProviderForEngine(providerName)) } else { - models, err = hawkconfig.FetchModelsForProvider(provider) + models, err = hawkconfig.FetchModelsForProvider(providerName) } if err != nil { return err @@ -137,8 +137,8 @@ var modelsListCmd = &cobra.Command{ return nil } cmd.Printf("%d models", len(models)) - if provider != "" { - cmd.Printf(" for provider %q", provider) + if providerName != "" { + cmd.Printf(" for provider %q", providerName) } cmd.Println() rows := make([]modelTableRow, len(models)) diff --git a/cmd/ocg_live_test.go b/cmd/ocg_live_test.go index 245825a0..96548190 100644 --- a/cmd/ocg_live_test.go +++ b/cmd/ocg_live_test.go @@ -14,7 +14,7 @@ import ( func TestLiveOpenCodeGoMiniMaxM3FullHawkPath(t *testing.T) { if credentials.LookupSecret(context.Background(), "OPENCODEGO_API_KEY") == "" { - t.Skip("OPENCODEGO_API_KEY not configured") + t.Skip("OPENCODEGO_API_KEY not configured") // TODO: https://github.com/GrayCodeAI/hawk/issues/29 } settings, err := loadEffectiveSettings() if err != nil { @@ -36,8 +36,8 @@ func TestLiveOpenCodeGoMiniMaxM3FullHawkPath(t *testing.T) { sess := newHawkSession(settings, effectiveProvider, effectiveModel, systemPrompt, registry) sess.SetLogger(logger.New(ioDiscard{}, logger.Info)) - if err := configureSession(sess, settings); err != nil { - t.Fatal(err) + if cfgErr := configureSession(sess, settings); cfgErr != nil { + t.Fatal(cfgErr) } sess.AddUser("Hi") diff --git a/cmd/path_test.go b/cmd/path_test.go index 63591e4a..7ee853d2 100644 --- a/cmd/path_test.go +++ b/cmd/path_test.go @@ -10,7 +10,7 @@ import ( func TestPathCmdRuns(t *testing.T) { if err := pathCmd.RunE(pathCmd, nil); err == nil { - t.Skip("machine has full developer path setup") + t.Skip("machine has full developer path setup") // TODO: https://github.com/GrayCodeAI/hawk/issues/30 } } diff --git a/cmd/review_fix.go b/cmd/review_fix.go index 898f9a70..7ad72684 100644 --- a/cmd/review_fix.go +++ b/cmd/review_fix.go @@ -44,9 +44,9 @@ func runReviewFix(_ *cobra.Command, args []string) error { if len(args) > 0 { for _, ref := range args { - r, err := resolveReview(store, ref) - if err != nil { - return err + r, resolveErr := resolveReview(store, ref) + if resolveErr != nil { + return resolveErr } reviews = append(reviews, r) } diff --git a/cmd/review_refine.go b/cmd/review_refine.go index e371c3c8..537744df 100644 --- a/cmd/review_refine.go +++ b/cmd/review_refine.go @@ -46,9 +46,9 @@ func runReviewRefine(_ *cobra.Command, args []string) error { var reviews []*ReviewRecord if len(args) > 0 { for _, ref := range args { - r, err := resolveReview(store, ref) - if err != nil { - return err + r, resolveErr := resolveReview(store, ref) + if resolveErr != nil { + return resolveErr } reviews = append(reviews, r) } diff --git a/internal/cmdhistory/history.go b/internal/cmdhistory/history.go index ad21a475..1c0db829 100644 --- a/internal/cmdhistory/history.go +++ b/internal/cmdhistory/history.go @@ -248,13 +248,13 @@ func (s *Store) Stats() (*HistoryStats, error) { for cmdRows.Next() { var cc CommandCount - if err := cmdRows.Scan(&cc.Command, &cc.Count); err != nil { - return nil, fmt.Errorf("scan command count: %w", err) + if scanErr := cmdRows.Scan(&cc.Command, &cc.Count); scanErr != nil { + return nil, fmt.Errorf("scan command count: %w", scanErr) } stats.TopCommands = append(stats.TopCommands, cc) } - if err := cmdRows.Err(); err != nil { - return nil, err + if iterErr := cmdRows.Err(); iterErr != nil { + return nil, iterErr } // Top 10 directories by frequency. diff --git a/internal/codegraph/algorithms_cgo.go b/internal/codegraph/algorithms_cgo.go index 1d8f3401..acf79e07 100644 --- a/internal/codegraph/algorithms_cgo.go +++ b/internal/codegraph/algorithms_cgo.go @@ -490,15 +490,15 @@ func (cg *CodeGraph) SnapshotGraph() (nodes map[string]bool, edges map[string]bo } for rows.Next() { var id string - if err := rows.Scan(&id); err != nil { + if scanErr := rows.Scan(&id); scanErr != nil { rows.Close() - return nil, nil, fmt.Errorf("scanning node row: %w", err) + return nil, nil, fmt.Errorf("scanning node row: %w", scanErr) } nodes[id] = true } - if err := rows.Err(); err != nil { + if iterErr := rows.Err(); iterErr != nil { rows.Close() - return nil, nil, fmt.Errorf("iterating nodes: %w", err) + return nil, nil, fmt.Errorf("iterating nodes: %w", iterErr) } rows.Close() diff --git a/internal/codegraph/codegraph_cgo.go b/internal/codegraph/codegraph_cgo.go index d928b40d..6e3ef86f 100644 --- a/internal/codegraph/codegraph_cgo.go +++ b/internal/codegraph/codegraph_cgo.go @@ -290,7 +290,7 @@ func (cg *CodeGraph) IndexFile(filePath string) error { return err } - tree, err := cg.parser.ParseCtx(context.TODO(), nil, source) + tree, err := cg.parser.ParseCtx(context.Background(), nil, source) if err != nil { return err } diff --git a/internal/config/migrate.go b/internal/config/migrate.go index 6d7bae42..ade48d9e 100644 --- a/internal/config/migrate.go +++ b/internal/config/migrate.go @@ -343,8 +343,8 @@ func (r *MigrationRegistry) MigrateFile(path string) error { } var data map[string]interface{} - if err := json.Unmarshal(rawData, &data); err != nil { - return fmt.Errorf("failed to parse config JSON: %w", err) + if unmarshalErr := json.Unmarshal(rawData, &data); unmarshalErr != nil { + return fmt.Errorf("failed to parse config JSON: %w", unmarshalErr) } if !r.NeedsMigration(data) { diff --git a/internal/config/migrate_test.go b/internal/config/migrate_test.go index 118a0bac..3c3020a5 100644 --- a/internal/config/migrate_test.go +++ b/internal/config/migrate_test.go @@ -466,7 +466,7 @@ func TestBackupCreation(t *testing.T) { } // Verify backup file exists - if _, err := os.Stat(backupPath); os.IsNotExist(err) { + if _, statErr := os.Stat(backupPath); os.IsNotExist(statErr) { t.Fatal("backup file should exist") } @@ -802,13 +802,13 @@ func TestMigrateFileEndToEnd(t *testing.T) { if err != nil { t.Fatal(err) } - if err := os.WriteFile(configPath, data, 0o644); err != nil { - t.Fatal(err) + if writeErr := os.WriteFile(configPath, data, 0o644); writeErr != nil { + t.Fatal(writeErr) } r := NewMigrationRegistry() - if err := r.MigrateFile(configPath); err != nil { - t.Fatalf("MigrateFile failed: %v", err) + if migrateErr := r.MigrateFile(configPath); migrateErr != nil { + t.Fatalf("MigrateFile failed: %v", migrateErr) } // Read back the migrated config @@ -818,8 +818,8 @@ func TestMigrateFileEndToEnd(t *testing.T) { } var result map[string]interface{} - if err := json.Unmarshal(migratedData, &result); err != nil { - t.Fatalf("failed to parse migrated config: %v", err) + if unmarshalErr := json.Unmarshal(migratedData, &result); unmarshalErr != nil { + t.Fatalf("failed to parse migrated config: %v", unmarshalErr) } // Verify version @@ -877,13 +877,13 @@ func TestMigrateFileAlreadyCurrent(t *testing.T) { if err != nil { t.Fatal(err) } - if err := os.WriteFile(configPath, data, 0o644); err != nil { - t.Fatal(err) + if writeErr := os.WriteFile(configPath, data, 0o644); writeErr != nil { + t.Fatal(writeErr) } r := NewMigrationRegistry() - if err := r.MigrateFile(configPath); err != nil { - t.Fatalf("MigrateFile should succeed for current config: %v", err) + if migrateErr := r.MigrateFile(configPath); migrateErr != nil { + t.Fatalf("MigrateFile should succeed for current config: %v", migrateErr) } // Verify no backup was created (no migration needed) diff --git a/internal/config/validator.go b/internal/config/validator.go index 735bf077..893404ee 100644 --- a/internal/config/validator.go +++ b/internal/config/validator.go @@ -50,7 +50,7 @@ func ValidateSettings(s Settings) ValidationResult { // Validate model selection (stored in eyrie provider.json) activeModel := strings.TrimSpace(s.Model) if activeModel == "" { - activeModel = ActiveModel(context.TODO()) + activeModel = ActiveModel(context.Background()) } if activeModel != "" && strings.Contains(activeModel, " ") { errors = append(errors, ValidationError{ @@ -62,7 +62,7 @@ func ValidateSettings(s Settings) ValidationResult { activeProvider := strings.TrimSpace(s.Provider) if activeProvider == "" { - activeProvider = ActiveProvider(context.TODO()) + activeProvider = ActiveProvider(context.Background()) } // Hawk: validate API key is in the OS secret store (not in settings) if activeProvider != "" { diff --git a/internal/config/xiaomi_setup.go b/internal/config/xiaomi_setup.go index cfdbf502..3819c0b4 100644 --- a/internal/config/xiaomi_setup.go +++ b/internal/config/xiaomi_setup.go @@ -35,8 +35,8 @@ func SetXiaomiTokenPlanRegion(region string) error { cfg = &eyriecfg.ProviderConfig{} } cfg.XiaomiMimoTokenPlanRegion = string(normalized) - if err := eyriecfg.SaveProviderConfig(cfg, ""); err != nil { - return err + if saveErr := eyriecfg.SaveProviderConfig(cfg, ""); saveErr != nil { + return saveErr } _ = os.Setenv(eyriecfg.EnvXiaomiTokenPlanRegion, string(normalized)) base, err := eyriecfg.ResolveXiaomiOpenAIBase(ProviderXiaomiTokenPlan, cfg) diff --git a/internal/diffsandbox/sandbox_test.go b/internal/diffsandbox/sandbox_test.go index 43870c8d..eb09a72a 100644 --- a/internal/diffsandbox/sandbox_test.go +++ b/internal/diffsandbox/sandbox_test.go @@ -60,8 +60,8 @@ func TestProposeModifyAndApply(t *testing.T) { t.Errorf("expected original content, got %q", c.Original) } - if err := sb.Apply(); err != nil { - t.Fatalf("Apply error: %v", err) + if applyErr := sb.Apply(); applyErr != nil { + t.Fatalf("Apply error: %v", applyErr) } data, err := os.ReadFile(origPath) diff --git a/internal/engine/branching/branching_test.go b/internal/engine/branching/branching_test.go index 15f4db30..9e8c234c 100644 --- a/internal/engine/branching/branching_test.go +++ b/internal/engine/branching/branching_test.go @@ -517,8 +517,8 @@ func TestExportImportRoundTrip(t *testing.T) { // Verify it's valid JSON. var raw map[string]interface{} - if err := json.Unmarshal(data, &raw); err != nil { - t.Fatalf("exported data is not valid JSON: %v", err) + if unmarshalErr := json.Unmarshal(data, &raw); unmarshalErr != nil { + t.Fatalf("exported data is not valid JSON: %v", unmarshalErr) } // Import into a new manager. diff --git a/internal/engine/errs/error_recovery.go b/internal/engine/errs/error_recovery.go index f2af43ae..5f360188 100644 --- a/internal/engine/errs/error_recovery.go +++ b/internal/engine/errs/error_recovery.go @@ -166,7 +166,7 @@ func (er *ErrorRecovery) Recover(err error, ctx *RecoveryContext) (*RecoveryResu if ctx == nil { ctx = &RecoveryContext{} } - if ctx.ErrorMsg == "" && err != nil { + if ctx.ErrorMsg == "" { ctx.ErrorMsg = err.Error() } if ctx.Error == nil { diff --git a/internal/engine/git/git_context.go b/internal/engine/git/git_context.go index c7ed56fc..6f158cf8 100644 --- a/internal/engine/git/git_context.go +++ b/internal/engine/git/git_context.go @@ -86,7 +86,7 @@ func (gc *GitContext) GetFileInfo(path string) (*GitFileInfo, error) { lines := strings.Split(logOut, "\n") if len(lines) >= 4 { info.LastAuthor = lines[1] - if t, err := time.Parse(time.RFC3339, lines[2]); err == nil { + if t, parseErr := time.Parse(time.RFC3339, lines[2]); parseErr == nil { info.LastModified = t } info.LastCommitMsg = lines[3] @@ -95,7 +95,7 @@ func (gc *GitContext) GetFileInfo(path string) (*GitFileInfo, error) { // Count commits touching this file countOut, err := gc.runGit("rev-list", "--count", "HEAD", "--", path) if err == nil { - if n, err := strconv.Atoi(countOut); err == nil { + if n, parseErr := strconv.Atoi(countOut); parseErr == nil { info.CommitCount = n } } @@ -392,8 +392,8 @@ func (gc *GitContext) BuildContextForFile(path string) string { commitCount := 0 for _, c := range recentCommits { // Check if this commit touched the file - filesOut, err := gc.runGit("diff-tree", "--no-commit-id", "-r", "--name-only", c.Hash) - if err == nil { + filesOut, diffErr := gc.runGit("diff-tree", "--no-commit-id", "-r", "--name-only", c.Hash) + if diffErr == nil { for _, f := range strings.Split(filesOut, "\n") { if strings.TrimSpace(f) == path { commitCount++ @@ -434,8 +434,8 @@ func (gc *GitContext) BuildContextForSession() string { // Check how far ahead of main aheadBehind := "" for _, base := range []string{"main", "master"} { - out, err := gc.runGit("rev-list", "--count", base+"..HEAD") - if err == nil { + out, revErr := gc.runGit("rev-list", "--count", base+"..HEAD") + if revErr == nil { if n, _ := strconv.Atoi(out); n > 0 { aheadBehind = fmt.Sprintf(" (ahead of %s by %d commits)", base, n) } diff --git a/internal/engine/git/git_context_test.go b/internal/engine/git/git_context_test.go index d82842cf..5db6b0c9 100644 --- a/internal/engine/git/git_context_test.go +++ b/internal/engine/git/git_context_test.go @@ -159,8 +159,8 @@ func TestGetUncommitted(t *testing.T) { } // Modify a file - if err := os.WriteFile(filepath.Join(dir, "main.go"), []byte("package main\n\n// modified\n"), 0o644); err != nil { - t.Fatal(err) + if writeErr := os.WriteFile(filepath.Join(dir, "main.go"), []byte("package main\n\n// modified\n"), 0o644); writeErr != nil { + t.Fatal(writeErr) } files, err = gc.GetUncommitted() @@ -425,8 +425,8 @@ func TestGetDiffSummary(t *testing.T) { } // Modify a file - if err := os.WriteFile(filepath.Join(dir, "main.go"), []byte("package main\n\n// changed\n"), 0o644); err != nil { - t.Fatal(err) + if writeErr := os.WriteFile(filepath.Join(dir, "main.go"), []byte("package main\n\n// changed\n"), 0o644); writeErr != nil { + t.Fatal(writeErr) } summary, err = gc.GetDiffSummary() diff --git a/internal/engine/memory/memory_consolidator_test.go b/internal/engine/memory/memory_consolidator_test.go index 44eabfdf..77e061b0 100644 --- a/internal/engine/memory/memory_consolidator_test.go +++ b/internal/engine/memory/memory_consolidator_test.go @@ -303,7 +303,7 @@ func TestSaveLoad(t *testing.T) { // Verify file exists path := filepath.Join(dir, "consolidated_memory.json") - if _, err := os.Stat(path); os.IsNotExist(err) { + if _, statErr := os.Stat(path); os.IsNotExist(statErr) { t.Fatal("expected consolidated_memory.json to exist") } diff --git a/internal/engine/observability/feedback_collector_test.go b/internal/engine/observability/feedback_collector_test.go index cb1c9d57..f4999155 100644 --- a/internal/engine/observability/feedback_collector_test.go +++ b/internal/engine/observability/feedback_collector_test.go @@ -419,7 +419,7 @@ func TestFeedbackCollectorSaveAndLoad(t *testing.T) { // Verify file exists path := filepath.Join(dir, "feedback.json") - if _, err := os.Stat(path); os.IsNotExist(err) { + if _, statErr := os.Stat(path); os.IsNotExist(statErr) { t.Fatal("feedback.json was not created") } diff --git a/internal/engine/observability/structured_log.go b/internal/engine/observability/structured_log.go index 91daeb7e..645bacf7 100644 --- a/internal/engine/observability/structured_log.go +++ b/internal/engine/observability/structured_log.go @@ -312,8 +312,8 @@ func (rw *RotatingWriter) Write(p []byte) (n int, err error) { defer rw.mu.Unlock() if rw.size+int64(len(p)) > rw.MaxSize { - if err := rw.rotate(); err != nil { - return 0, err + if rotateErr := rw.rotate(); rotateErr != nil { + return 0, rotateErr } } diff --git a/internal/engine/observability/structured_log_test.go b/internal/engine/observability/structured_log_test.go index 1350850c..3cccb3d0 100644 --- a/internal/engine/observability/structured_log_test.go +++ b/internal/engine/observability/structured_log_test.go @@ -338,9 +338,9 @@ func TestRotatingWriter(t *testing.T) { // Write enough data to trigger rotation. data := bytes.Repeat([]byte("A"), 60) for i := 0; i < 5; i++ { - _, err := rw.Write(data) - if err != nil { - t.Fatalf("write %d failed: %v", i, err) + _, writeErr := rw.Write(data) + if writeErr != nil { + t.Fatalf("write %d failed: %v", i, writeErr) } } diff --git a/internal/engine/planning/suggested_tasks.go b/internal/engine/planning/suggested_tasks.go index 1c52112d..692334bc 100644 --- a/internal/engine/planning/suggested_tasks.go +++ b/internal/engine/planning/suggested_tasks.go @@ -378,7 +378,7 @@ func ScanTestFailures(projectDir string) []*SuggestedTask { } // If we detected failures but couldn't parse test names - if len(failedTests) == 0 && err != nil { + if len(failedTests) == 0 { tasks = append(tasks, &SuggestedTask{ ID: generateTaskID(), Title: "Fix failing tests", diff --git a/internal/engine/project/release.go b/internal/engine/project/release.go index e9f0a04d..2795b54a 100644 --- a/internal/engine/project/release.go +++ b/internal/engine/project/release.go @@ -402,11 +402,11 @@ func (rm *ReleaseManager) PrepareRelease() (*Release, error) { sinceTag = "v" + currentVersion cmd := exec.CommandContext(context.Background(), "git", "rev-parse", sinceTag) cmd.Dir = rm.ProjectDir - if err := cmd.Run(); err != nil { + if runErr := cmd.Run(); runErr != nil { sinceTag = currentVersion cmd2 := exec.CommandContext(context.Background(), "git", "rev-parse", sinceTag) cmd2.Dir = rm.ProjectDir - if err := cmd2.Run(); err != nil { + if runErr := cmd2.Run(); runErr != nil { sinceTag = "" } } diff --git a/internal/engine/quality_gate.go b/internal/engine/quality_gate.go index d7bdeeed..c4633ac1 100644 --- a/internal/engine/quality_gate.go +++ b/internal/engine/quality_gate.go @@ -87,7 +87,7 @@ func ImplementGate(validateCmd string, workDir string) QualityGate { Phase: GateImplement, Check: func() GateResult { el := &ExperimentLoop{WorkDir: workDir, ValidateCmd: validateCmd, Timeout: 60_000_000_000} - passed, output := el.validate(context.TODO()) + passed, output := el.validate(context.Background()) if passed { return GateResult{Phase: GateImplement, Passed: true, Reason: "build/tests pass"} } diff --git a/internal/engine/scaffold/scaffold_test.go b/internal/engine/scaffold/scaffold_test.go index c7e4484c..52ccbb6a 100644 --- a/internal/engine/scaffold/scaffold_test.go +++ b/internal/engine/scaffold/scaffold_test.go @@ -144,7 +144,7 @@ func TestGenerateConditionEvaluation(t *testing.T) { } dockerPath := filepath.Join(outputDir1, "myapi/Dockerfile") - if _, err := os.Stat(dockerPath); os.IsNotExist(err) { + if _, statErr := os.Stat(dockerPath); os.IsNotExist(statErr) { t.Error("Dockerfile should be created when WithDocker is true") } @@ -387,8 +387,8 @@ func TestLoadTemplateFromJSON(t *testing.T) { if err != nil { t.Fatalf("marshaling template: %v", err) } - if err := os.WriteFile(jsonPath, data, 0o644); err != nil { - t.Fatalf("writing template file: %v", err) + if writeErr := os.WriteFile(jsonPath, data, 0o644); writeErr != nil { + t.Fatalf("writing template file: %v", writeErr) } // Load it @@ -581,7 +581,7 @@ func TestGeneratePythonCLITemplate(t *testing.T) { } // Check tests are created - if _, err := os.Stat(filepath.Join(outputDir, "mycli/tests/test_cli.py")); os.IsNotExist(err) { + if _, statErr := os.Stat(filepath.Join(outputDir, "mycli/tests/test_cli.py")); os.IsNotExist(statErr) { t.Error("test_cli.py should be created when WithTests is true") } diff --git a/internal/engine/stream.go b/internal/engine/stream.go index 73ea2b35..1cb52760 100644 --- a/internal/engine/stream.go +++ b/internal/engine/stream.go @@ -362,8 +362,8 @@ func (s *Session) agentLoop(ctx context.Context, ch chan<- StreamEvent) { // Rate limit: wait for a token before making the LLM call if s.RateLimiter != nil { - if err := s.RateLimiter.Wait(ctx); err != nil { - ch <- StreamEvent{Type: "error", Content: err.Error()} + if waitErr := s.RateLimiter.Wait(ctx); waitErr != nil { + ch <- StreamEvent{Type: "error", Content: waitErr.Error()} return } } @@ -464,9 +464,6 @@ func (s *Session) agentLoop(ctx context.Context, ch chan<- StreamEvent) { break } if streamAttempt >= maxStreamRetries { - if thinkingOnly { - streamErr = fmt.Errorf("error_only_reasoning: model produced reasoning but no answer") - } break } retryReason := "transient stream error" diff --git a/internal/engine/validation/gen_validator.go b/internal/engine/validation/gen_validator.go index bc58043c..4121bb39 100644 --- a/internal/engine/validation/gen_validator.go +++ b/internal/engine/validation/gen_validator.go @@ -822,14 +822,14 @@ func checkGoCompilation(code string) []GenIssue { defer func() { _ = os.RemoveAll(tmpDir) }() tmpFile := filepath.Join(tmpDir, "generated.go") - if err := os.WriteFile(tmpFile, []byte(code), 0o644); err != nil { + if writeErr := os.WriteFile(tmpFile, []byte(code), 0o644); writeErr != nil { return nil } // Initialize a module in the temp directory cmd := exec.CommandContext(context.Background(), "go", "mod", "init", "temp") cmd.Dir = tmpDir - if err := cmd.Run(); err != nil { + if runErr := cmd.Run(); runErr != nil { return nil } diff --git a/internal/feature/eval/lmeval_test.go b/internal/feature/eval/lmeval_test.go index 4f1233cb..a8e6442c 100644 --- a/internal/feature/eval/lmeval_test.go +++ b/internal/feature/eval/lmeval_test.go @@ -30,8 +30,8 @@ func TestResultStore_SaveLoad(t *testing.T) { if err != nil { t.Fatal(err) } - if _, err := os.Stat(path); err != nil { - t.Fatalf("file not created: %v", err) + if _, statErr := os.Stat(path); statErr != nil { + t.Fatalf("file not created: %v", statErr) } loaded, err := store.Load(path) diff --git a/internal/feature/taste/store_test.go b/internal/feature/taste/store_test.go index 94e03999..ffa82cfb 100644 --- a/internal/feature/taste/store_test.go +++ b/internal/feature/taste/store_test.go @@ -15,8 +15,8 @@ func TestStore_SaveAndLoad(t *testing.T) { profile.Update(CategoryNaming, Signal{Value: "camelCase", Confidence: 0.8}) profile.Update(CategoryComments, Signal{Value: "minimal", Confidence: 0.6}) - if err := store.Save("test-project", profile); err != nil { - t.Fatalf("Save: %v", err) + if saveErr := store.Save("test-project", profile); saveErr != nil { + t.Fatalf("Save: %v", saveErr) } loaded, err := store.Load("test-project") @@ -70,8 +70,8 @@ func TestStore_ExportAndImport(t *testing.T) { profile := NewProfile("export-test") profile.Update(CategoryNaming, Signal{Value: "snake_case", Confidence: 0.9}) - if err := store.Save("export-test", profile); err != nil { - t.Fatalf("Save: %v", err) + if saveErr := store.Save("export-test", profile); saveErr != nil { + t.Fatalf("Save: %v", saveErr) } data, err := store.Export("export-test") @@ -86,8 +86,8 @@ func TestStore_ExportAndImport(t *testing.T) { t.Fatalf("NewStore2: %v", err) } - if err := store2.Import(data); err != nil { - t.Fatalf("Import: %v", err) + if importErr := store2.Import(data); importErr != nil { + t.Fatalf("Import: %v", importErr) } loaded, err := store2.Load("export-test") @@ -130,8 +130,8 @@ func TestStore_Delete(t *testing.T) { store.Save("delete-me", NewProfile("delete-me")) - if err := store.Delete("delete-me"); err != nil { - t.Fatalf("Delete: %v", err) + if deleteErr := store.Delete("delete-me"); deleteErr != nil { + t.Fatalf("Delete: %v", deleteErr) } // Load should return a fresh profile after deletion. diff --git a/internal/intelligence/memory/autodream.go b/internal/intelligence/memory/autodream.go index 73315089..98e2d03f 100644 --- a/internal/intelligence/memory/autodream.go +++ b/internal/intelligence/memory/autodream.go @@ -109,8 +109,8 @@ func RunDream(ctx context.Context, cfg AutoDreamConfig, agentFn func(ctx context if e.IsDir() || filepath.Ext(e.Name()) != ".md" { continue } - data, err := os.ReadFile(filepath.Join(memDir, e.Name())) - if err != nil { + data, readErr := os.ReadFile(filepath.Join(memDir, e.Name())) + if readErr != nil { continue } memoryContent += fmt.Sprintf("--- %s ---\n%s\n\n", e.Name(), string(data)) diff --git a/internal/intelligence/memory/yaad_bridge.go b/internal/intelligence/memory/yaad_bridge.go index 36fb6754..2b61bc57 100644 --- a/internal/intelligence/memory/yaad_bridge.go +++ b/internal/intelligence/memory/yaad_bridge.go @@ -40,7 +40,7 @@ func (b *YaadBridge) init() { return } dbDir := filepath.Join(home, ".yaad", "data") - if err := os.MkdirAll(dbDir, 0o755); err != nil { + if mkErr := os.MkdirAll(dbDir, 0o755); mkErr != nil { return } dbPath := filepath.Join(dbDir, "yaad.db") diff --git a/internal/intelligence/planner/planner_test.go b/internal/intelligence/planner/planner_test.go index fa94a863..327b4e4e 100644 --- a/internal/intelligence/planner/planner_test.go +++ b/internal/intelligence/planner/planner_test.go @@ -161,7 +161,7 @@ func TestSaveAndLoad(t *testing.T) { } // Verify file exists - if _, err := os.Stat(path); os.IsNotExist(err) { + if _, statErr := os.Stat(path); os.IsNotExist(statErr) { t.Fatalf("saved file does not exist: %s", path) } diff --git a/internal/intelligence/repomap/depgraph.go b/internal/intelligence/repomap/depgraph.go index 63742bd0..952d5078 100644 --- a/internal/intelligence/repomap/depgraph.go +++ b/internal/intelligence/repomap/depgraph.go @@ -265,8 +265,8 @@ func (dg *DepGraph) BuildFromPackageJSON(projectDir string) error { Dependencies map[string]string `json:"dependencies"` DevDependencies map[string]string `json:"devDependencies"` } - if err := json.Unmarshal(data, &pkgJSON); err != nil { - return fmt.Errorf("depgraph: parse package.json: %w", err) + if unmarshalErr := json.Unmarshal(data, &pkgJSON); unmarshalErr != nil { + return fmt.Errorf("depgraph: parse package.json: %w", unmarshalErr) } dg.Root = pkgJSON.Name diff --git a/internal/intelligence/repomap/incremental_test.go b/internal/intelligence/repomap/incremental_test.go index 2a64a3c1..e778717d 100644 --- a/internal/intelligence/repomap/incremental_test.go +++ b/internal/intelligence/repomap/incremental_test.go @@ -157,8 +157,8 @@ func TestIncrementalMap_DetectsModifiedFiles(t *testing.T) { } // Modify the file (add a new function) - if err := os.WriteFile(goFile, []byte("package main\n\nfunc main() {}\n\nfunc helper() {}\n"), 0o644); err != nil { - t.Fatal(err) + if writeErr := os.WriteFile(goFile, []byte("package main\n\nfunc main() {}\n\nfunc helper() {}\n"), 0o644); writeErr != nil { + t.Fatal(writeErr) } // Second update: should detect the change @@ -207,8 +207,8 @@ func TestIncrementalMap_RemovesDeletedFiles(t *testing.T) { } // Delete helper.go - if err := os.Remove(helperFile); err != nil { - t.Fatal(err) + if removeErr := os.Remove(helperFile); removeErr != nil { + t.Fatal(removeErr) } // Second update: should detect deletion @@ -264,8 +264,8 @@ func TestIncrementalMap_SymbolPreservation(t *testing.T) { } // Modify only b.go - if err := os.WriteFile(filepath.Join(rootDir, "b.go"), []byte("package main\n\nfunc BetaV2() {}\n"), 0o644); err != nil { - t.Fatal(err) + if writeErr := os.WriteFile(filepath.Join(rootDir, "b.go"), []byte("package main\n\nfunc BetaV2() {}\n"), 0o644); writeErr != nil { + t.Fatal(writeErr) } changed, err := im.Update(rootDir) @@ -304,11 +304,11 @@ func TestIncrementalMap_SaveAndReload(t *testing.T) { if err != nil { t.Fatal(err) } - if _, err := im1.Update(rootDir); err != nil { - t.Fatal(err) + if _, updateErr := im1.Update(rootDir); updateErr != nil { + t.Fatal(updateErr) } - if err := im1.Save(); err != nil { - t.Fatalf("Save failed: %v", err) + if saveErr := im1.Save(); saveErr != nil { + t.Fatalf("Save failed: %v", saveErr) } // Reload from cache diff --git a/internal/intelligence/repomap/semantic_search.go b/internal/intelligence/repomap/semantic_search.go index 5b9a9b1f..35aa23fc 100644 --- a/internal/intelligence/repomap/semantic_search.go +++ b/internal/intelligence/repomap/semantic_search.go @@ -399,13 +399,13 @@ func splitIntoDocuments(path, content string) []*Document { // Convert builders to documents for _, b := range builders { - content := strings.Join(b.lines, "\n") - terms := buildTermFrequency(content) + blockContent := strings.Join(b.lines, "\n") + terms := buildTermFrequency(blockContent) docID := fmt.Sprintf("%s:%s", path, b.name) docs = append(docs, &Document{ ID: docID, Path: path, - Content: content, + Content: blockContent, Terms: terms, Length: countTerms(terms), Type: b.docType, diff --git a/internal/intelligence/repomap/semantic_test.go b/internal/intelligence/repomap/semantic_test.go index 543a9b48..19668220 100644 --- a/internal/intelligence/repomap/semantic_test.go +++ b/internal/intelligence/repomap/semantic_test.go @@ -73,8 +73,8 @@ func TestSemanticIndexSaveLoad(t *testing.T) { } savePath := filepath.Join(dir, "index.gob") - if err := idx.Save(savePath); err != nil { - t.Fatal(err) + if saveErr := idx.Save(savePath); saveErr != nil { + t.Fatal(saveErr) } loaded, err := LoadSemanticIndex(savePath) diff --git a/internal/intelligence/repomap/summary.go b/internal/intelligence/repomap/summary.go index 10b134f4..90837bb0 100644 --- a/internal/intelligence/repomap/summary.go +++ b/internal/intelligence/repomap/summary.go @@ -888,7 +888,7 @@ func summaryFindJSEntryPoints(packageJSONPath string, projectDir string) []strin var pkg struct { Main string `json:"main"` } - if err := json.Unmarshal(data, &pkg); err != nil { + if unmarshalErr := json.Unmarshal(data, &pkg); unmarshalErr != nil { return nil } diff --git a/internal/lsp/client.go b/internal/lsp/client.go index 6d5f26ee..6e447875 100644 --- a/internal/lsp/client.go +++ b/internal/lsp/client.go @@ -99,8 +99,8 @@ func NewLSPClient(ctx context.Context, lang string, cfg ServerConfig) (*LSPClien if err != nil { return nil, fmt.Errorf("lsp: stdout pipe: %w", err) } - if err := cmd.Start(); err != nil { - return nil, fmt.Errorf("lsp: start %s: %w", cfg.Command, err) + if startErr := cmd.Start(); startErr != nil { + return nil, fmt.Errorf("lsp: start %s: %w", cfg.Command, startErr) } c := &LSPClient{ diff --git a/internal/mcp/mcp.go b/internal/mcp/mcp.go index 25c20ea1..8d388daa 100644 --- a/internal/mcp/mcp.go +++ b/internal/mcp/mcp.go @@ -83,8 +83,8 @@ func Connect(ctx context.Context, name, command string, args ...string) (*Server if err != nil { return nil, fmt.Errorf("mcp: stdout pipe: %w", err) } - if err := cmd.Start(); err != nil { - return nil, fmt.Errorf("mcp: start %s: %w", command, err) + if startErr := cmd.Start(); startErr != nil { + return nil, fmt.Errorf("mcp: start %s: %w", command, startErr) } scanner := bufio.NewScanner(stdout) diff --git a/internal/mcp/server_test.go b/internal/mcp/server_test.go index 69d7cb8f..0288cb97 100644 --- a/internal/mcp/server_test.go +++ b/internal/mcp/server_test.go @@ -39,7 +39,7 @@ func TestInitializeHandshake(t *testing.T) { } // Check protocol version - if pv, ok := result["protocolVersion"].(string); !ok || pv != "2025-03-26" { + if pv, typeOK := result["protocolVersion"].(string); !typeOK || pv != "2025-03-26" { t.Errorf("expected protocolVersion 2025-03-26, got %v", result["protocolVersion"]) } diff --git a/internal/mcp/ws.go b/internal/mcp/ws.go index d4411716..54728173 100644 --- a/internal/mcp/ws.go +++ b/internal/mcp/ws.go @@ -174,9 +174,9 @@ func wsDial(ctx context.Context, rawURL string, headers map[string]string) (net. } b.WriteString("\r\n") - if _, err := io.WriteString(conn, b.String()); err != nil { + if _, writeErr := io.WriteString(conn, b.String()); writeErr != nil { _ = conn.Close() - return nil, nil, err + return nil, nil, writeErr } rw := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn)) diff --git a/internal/multiagent/parallel/parallel_test.go b/internal/multiagent/parallel/parallel_test.go index 832bf114..0766a26a 100644 --- a/internal/multiagent/parallel/parallel_test.go +++ b/internal/multiagent/parallel/parallel_test.go @@ -253,18 +253,18 @@ func TestCleanupRemovesAllWorktrees(t *testing.T) { // All worktree paths should exist before cleanup. for _, p := range paths { - if _, err := os.Stat(p); err != nil { - t.Fatalf("worktree %s should exist before cleanup: %v", p, err) + if _, statErr := os.Stat(p); statErr != nil { + t.Fatalf("worktree %s should exist before cleanup: %v", p, statErr) } } - if err := pool.Cleanup(); err != nil { - t.Fatalf("Cleanup: %v", err) + if cleanupErr := pool.Cleanup(); cleanupErr != nil { + t.Fatalf("Cleanup: %v", cleanupErr) } // All worktree paths should be gone after cleanup. for _, p := range paths { - if _, err := os.Stat(p); !os.IsNotExist(err) { + if _, statErr := os.Stat(p); !os.IsNotExist(statErr) { t.Errorf("worktree %s should not exist after cleanup", p) } } diff --git a/internal/multiagent/parallel/worktree_manager_test.go b/internal/multiagent/parallel/worktree_manager_test.go index 83e65cf5..c9642c20 100644 --- a/internal/multiagent/parallel/worktree_manager_test.go +++ b/internal/multiagent/parallel/worktree_manager_test.go @@ -397,8 +397,8 @@ func TestIsClean(t *testing.T) { // Create an uncommitted file. dirty := filepath.Join(wt.Path, "dirty.txt") - if err := os.WriteFile(dirty, []byte("uncommitted\n"), 0o644); err != nil { - t.Fatal(err) + if writeErr := os.WriteFile(dirty, []byte("uncommitted\n"), 0o644); writeErr != nil { + t.Fatal(writeErr) } clean, err = wm.IsClean(wt.ID) @@ -428,8 +428,8 @@ func TestGetDiff(t *testing.T) { // Make a commit in the worktree. newFile := filepath.Join(wt.Path, "diffed.txt") - if err := os.WriteFile(newFile, []byte("new content\n"), 0o644); err != nil { - t.Fatal(err) + if writeErr := os.WriteFile(newFile, []byte("new content\n"), 0o644); writeErr != nil { + t.Fatal(writeErr) } runGitIn(t, wt.Path, "add", "diffed.txt") runGitIn(t, wt.Path, "commit", "-m", "add diffed.txt") diff --git a/internal/observability/insights.go b/internal/observability/insights.go index 9c8ee048..994713e3 100644 --- a/internal/observability/insights.go +++ b/internal/observability/insights.go @@ -45,16 +45,16 @@ func GenerateInsights(days int, analysisFn func(content string) ([]InsightsFacet if e.IsDir() { continue } - info, err := e.Info() - if err != nil || info.ModTime().Before(cutoff) { + info, infoErr := e.Info() + if infoErr != nil || info.ModTime().Before(cutoff) { continue } if filepath.Ext(e.Name()) != ".jsonl" { continue } - data, err := os.ReadFile(filepath.Join(sessDir, e.Name())) - if err != nil { + data, readErr := os.ReadFile(filepath.Join(sessDir, e.Name())) + if readErr != nil { continue } transcripts = append(transcripts, string(data)) diff --git a/internal/observability/metrics/metrics.go b/internal/observability/metrics/metrics.go index 3220aa33..21f7829f 100644 --- a/internal/observability/metrics/metrics.go +++ b/internal/observability/metrics/metrics.go @@ -151,8 +151,8 @@ func (r *Registry) Counter(name string) *Counter { r.mu.Lock() defer r.mu.Unlock() - if c, ok := r.counters[name]; ok { - return c + if existingC, ok := r.counters[name]; ok { + return existingC } c = &Counter{} r.counters[name] = c @@ -170,8 +170,8 @@ func (r *Registry) Gauge(name string) *Gauge { r.mu.Lock() defer r.mu.Unlock() - if g, ok := r.gauges[name]; ok { - return g + if existingG, ok := r.gauges[name]; ok { + return existingG } g = &Gauge{} r.gauges[name] = g @@ -189,8 +189,8 @@ func (r *Registry) Timer(name string) *Timer { r.mu.Lock() defer r.mu.Unlock() - if t, ok := r.timers[name]; ok { - return t + if existingT, ok := r.timers[name]; ok { + return existingT } t = NewTimer() r.timers[name] = t diff --git a/internal/permissions/guardian_test.go b/internal/permissions/guardian_test.go index 0847ce23..68d39b26 100644 --- a/internal/permissions/guardian_test.go +++ b/internal/permissions/guardian_test.go @@ -126,9 +126,9 @@ func TestGuardian_CircuitBreakerResetsOnAllow(t *testing.T) { g.ChatFn = chatFn2 for i := 0; i < 3; i++ { - _, err := g.Review(ctx, req) - if err != nil { - t.Fatalf("unexpected circuit breaker on denial %d after reset: %v", i+1, err) + _, reviewErr := g.Review(ctx, req) + if reviewErr != nil { + t.Fatalf("unexpected circuit breaker on denial %d after reset: %v", i+1, reviewErr) } } diff --git a/internal/plugin/plugin_test.go b/internal/plugin/plugin_test.go index 9eb903fc..94e141c6 100644 --- a/internal/plugin/plugin_test.go +++ b/internal/plugin/plugin_test.go @@ -84,8 +84,8 @@ func TestInstallAndUninstall(t *testing.T) { t.Fatalf("expected 1 plugin, got %d", len(plugins)) } - if err := Uninstall("test-plugin"); err != nil { - t.Fatal(err) + if uninstallErr := Uninstall("test-plugin"); uninstallErr != nil { + t.Fatal(uninstallErr) } plugins, err = List() diff --git a/internal/plugin/registry.go b/internal/plugin/registry.go index 0675980d..1ba6b078 100644 --- a/internal/plugin/registry.go +++ b/internal/plugin/registry.go @@ -213,14 +213,14 @@ func (rc *RegistryClient) Install(repo, skillName, scope string) (string, error) url := "https://github.com/" + repo + ".git" cmd := exec.CommandContext(context.Background(), "git", "clone", "--depth", "1", "--single-branch", url, tmpDir) - if out, err := cmd.CombinedOutput(); err != nil { - return "", fmt.Errorf("git clone failed: %s\n%s", err, string(out)) + if out, cloneErr := cmd.CombinedOutput(); cloneErr != nil { + return "", fmt.Errorf("git clone failed: %s\n%s", cloneErr, string(out)) } // Discover skills in the cloned repo. skillsRoot := tmpDir // Check for skills/ subdirectory (agentskills.io convention). - if info, err := os.Stat(filepath.Join(tmpDir, "skills")); err == nil && info.IsDir() { + if info, statErr := os.Stat(filepath.Join(tmpDir, "skills")); statErr == nil && info.IsDir() { skillsRoot = filepath.Join(tmpDir, "skills") } diff --git a/internal/resilience/circuit.go b/internal/resilience/circuit.go index be6665a5..1300cd57 100644 --- a/internal/resilience/circuit.go +++ b/internal/resilience/circuit.go @@ -218,8 +218,8 @@ func (m *Manager) Get(name string) *Breaker { m.mu.Lock() defer m.mu.Unlock() // Double-check - if b, ok := m.breakers[name]; ok { - return b + if existingB, ok := m.breakers[name]; ok { + return existingB } b = New(m.config) m.breakers[name] = b diff --git a/internal/resilience/ratelimit/ratelimit.go b/internal/resilience/ratelimit/ratelimit.go index 4a178750..7cb99328 100644 --- a/internal/resilience/ratelimit/ratelimit.go +++ b/internal/resilience/ratelimit/ratelimit.go @@ -136,8 +136,8 @@ func (m *Manager) Get(name string, cfg Config) *Limiter { m.mu.Lock() defer m.mu.Unlock() - if l, ok := m.limiters[name]; ok { - return l + if existingL, ok := m.limiters[name]; ok { + return existingL } l = New(cfg) m.limiters[name] = l diff --git a/internal/rules/rules_test.go b/internal/rules/rules_test.go index 774de377..cf6f215a 100644 --- a/internal/rules/rules_test.go +++ b/internal/rules/rules_test.go @@ -372,8 +372,8 @@ func TestRoundTrip_ClaudeCodeToHawk(t *testing.T) { } // Export to hawk. - if err := Export(dir, FormatHawk, imported); err != nil { - t.Fatal(err) + if exportErr := Export(dir, FormatHawk, imported); exportErr != nil { + t.Fatal(exportErr) } // Re-import from hawk. @@ -415,15 +415,15 @@ func TestRoundTrip_CursorToHawkToClaudeCode(t *testing.T) { } // Export to hawk, then to Claude Code. - if err := Export(dir, FormatHawk, imported); err != nil { - t.Fatal(err) + if exportErr := Export(dir, FormatHawk, imported); exportErr != nil { + t.Fatal(exportErr) } hawkRules, err := Import(dir, FormatHawk) if err != nil { t.Fatal(err) } - if err := Export(dir, FormatClaudeCode, hawkRules); err != nil { - t.Fatal(err) + if exportErr := Export(dir, FormatClaudeCode, hawkRules); exportErr != nil { + t.Fatal(exportErr) } // Re-import from Claude Code. @@ -456,15 +456,15 @@ func TestRoundTrip_HawkToCursorToHawk(t *testing.T) { } // Export to hawk, import, export to cursor, import from cursor, export back to hawk. - if err := Export(dir, FormatHawk, original); err != nil { - t.Fatal(err) + if exportErr := Export(dir, FormatHawk, original); exportErr != nil { + t.Fatal(exportErr) } fromHawk, err := Import(dir, FormatHawk) if err != nil { t.Fatal(err) } - if err := Export(dir, FormatCursor, fromHawk); err != nil { - t.Fatal(err) + if exportErr := Export(dir, FormatCursor, fromHawk); exportErr != nil { + t.Fatal(exportErr) } fromCursor, err := Import(dir, FormatCursor) if err != nil { @@ -473,8 +473,8 @@ func TestRoundTrip_HawkToCursorToHawk(t *testing.T) { // Re-export back to hawk in a fresh directory. dir2 := t.TempDir() - if err := Export(dir2, FormatHawk, fromCursor); err != nil { - t.Fatal(err) + if exportErr := Export(dir2, FormatHawk, fromCursor); exportErr != nil { + t.Fatal(exportErr) } final, err := Import(dir2, FormatHawk) if err != nil { diff --git a/internal/sandbox/devenv_test.go b/internal/sandbox/devenv_test.go index 2b0f14b0..0c10fb1b 100644 --- a/internal/sandbox/devenv_test.go +++ b/internal/sandbox/devenv_test.go @@ -69,8 +69,8 @@ func TestDevEnvManager_GetOrBuild_RebuildsOnChange(t *testing.T) { } // Modify Dockerfile - if err := os.WriteFile(dockerfile, []byte("FROM alpine:latest\nRUN echo v2"), 0o644); err != nil { - t.Fatal(err) + if writeErr := os.WriteFile(dockerfile, []byte("FROM alpine:latest\nRUN echo v2"), 0o644); writeErr != nil { + t.Fatal(writeErr) } tag2, err := mgr.GetOrBuild(ctx, dockerfile) diff --git a/internal/sandbox/isolation_verify_test.go b/internal/sandbox/isolation_verify_test.go index 97df0b4b..8acf65e7 100644 --- a/internal/sandbox/isolation_verify_test.go +++ b/internal/sandbox/isolation_verify_test.go @@ -47,11 +47,11 @@ func TestVerify_ContainerDoesNotExposeHostHawkHome(t *testing.T) { t.Fatal(err) } hawkEnv := filepath.Join(home, ".hawk", "env") - if _, err := os.Stat(hawkEnv); err != nil { + if _, statErr := os.Stat(hawkEnv); statErr != nil { // Create a marker file so we can detect accidental host mount exposure. _ = os.MkdirAll(filepath.Dir(hawkEnv), 0o700) - if err := os.WriteFile(hawkEnv, []byte("export VERIFY_HAWK_HOME_SECRET=1\n"), 0o600); err != nil { - t.Fatal(err) + if writeErr := os.WriteFile(hawkEnv, []byte("export VERIFY_HAWK_HOME_SECRET=1\n"), 0o600); writeErr != nil { + t.Fatal(writeErr) } t.Cleanup(func() { _ = os.Remove(hawkEnv) }) } @@ -63,8 +63,8 @@ func TestVerify_ContainerDoesNotExposeHostHawkHome(t *testing.T) { } ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) defer cancel() - if err := cs.Start(ctx); err != nil { - t.Fatalf("container start: %v", err) + if startErr := cs.Start(ctx); startErr != nil { + t.Fatalf("container start: %v", startErr) } t.Cleanup(func() { _ = cs.Stop() }) diff --git a/internal/sandbox/netproxy_test.go b/internal/sandbox/netproxy_test.go index c5637a5a..80d7affc 100644 --- a/internal/sandbox/netproxy_test.go +++ b/internal/sandbox/netproxy_test.go @@ -409,8 +409,8 @@ func TestStop_Clean(t *testing.T) { conn.Close() // Stop the proxy. - if err := proxy.Stop(); err != nil { - t.Fatalf("Stop() error = %v", err) + if stopErr := proxy.Stop(); stopErr != nil { + t.Fatalf("Stop() error = %v", stopErr) } // Give it a moment to close. diff --git a/internal/sandbox/snapshot_sandbox_test.go b/internal/sandbox/snapshot_sandbox_test.go index 7de38d3e..f765b1f1 100644 --- a/internal/sandbox/snapshot_sandbox_test.go +++ b/internal/sandbox/snapshot_sandbox_test.go @@ -101,8 +101,8 @@ func TestPauseAndResume(t *testing.T) { os.WriteFile(filepath.Join(workDir, "new.txt"), []byte("new file"), 0o644) // Pause. - if err := mgr.Pause(sb.ID); err != nil { - t.Fatalf("Pause failed: %v", err) + if pauseErr := mgr.Pause(sb.ID); pauseErr != nil { + t.Fatalf("Pause failed: %v", pauseErr) } if sb.Status != "paused" { t.Errorf("expected status paused, got %q", sb.Status) @@ -113,8 +113,8 @@ func TestPauseAndResume(t *testing.T) { // Verify persisted to disk. path := filepath.Join(dir, sb.ID+".json") - if _, err := os.Stat(path); err != nil { - t.Errorf("expected persisted file at %s: %v", path, err) + if _, statErr := os.Stat(path); statErr != nil { + t.Errorf("expected persisted file at %s: %v", path, statErr) } // Wipe work dir to simulate environment teardown. diff --git a/internal/session/named_checkpoint.go b/internal/session/named_checkpoint.go index fbd093d3..e48e593e 100644 --- a/internal/session/named_checkpoint.go +++ b/internal/session/named_checkpoint.go @@ -74,8 +74,8 @@ func SaveNamedCheckpoint(name string, s *Session) (*NamedCheckpoint, error) { return nil, fmt.Errorf("marshal session: %w", err) } var snap Session - if err := json.Unmarshal(raw, &snap); err != nil { - return nil, fmt.Errorf("copy session: %w", err) + if unmarshalErr := json.Unmarshal(raw, &snap); unmarshalErr != nil { + return nil, fmt.Errorf("copy session: %w", unmarshalErr) } cp := &NamedCheckpoint{ @@ -85,8 +85,8 @@ func SaveNamedCheckpoint(name string, s *Session) (*NamedCheckpoint, error) { } dir := namedCheckpointsDir() - if err := os.MkdirAll(dir, 0o755); err != nil { - return nil, fmt.Errorf("create checkpoints directory: %w", err) + if mkErr := os.MkdirAll(dir, 0o755); mkErr != nil { + return nil, fmt.Errorf("create checkpoints directory: %w", mkErr) } data, err := json.MarshalIndent(cp, "", " ") diff --git a/internal/session/sqlite_store.go b/internal/session/sqlite_store.go index 6aec9ce2..d5788e9b 100644 --- a/internal/session/sqlite_store.go +++ b/internal/session/sqlite_store.go @@ -478,8 +478,8 @@ func (s *SQLiteStore) DeleteSession(id string) error { defer func() { _ = tx.Rollback() }() // Delete messages first (FK constraint). - if _, err := tx.ExecContext(context.Background(), "DELETE FROM messages WHERE session_id = ?", id); err != nil { - return fmt.Errorf("delete messages: %w", err) + if _, execErr := tx.ExecContext(context.Background(), "DELETE FROM messages WHERE session_id = ?", id); execErr != nil { + return fmt.Errorf("delete messages: %w", execErr) } result, err := tx.ExecContext(context.Background(), "DELETE FROM sessions WHERE id = ?", id) @@ -636,8 +636,8 @@ func (s *SQLiteStore) Compact(sessionID string, keepLast int) error { // Recalculate total tokens. var totalTokens int row := tx.QueryRowContext(context.Background(), "SELECT COALESCE(SUM(tokens), 0) FROM messages WHERE session_id = ?", sessionID) - if err := row.Scan(&totalTokens); err != nil { - return fmt.Errorf("sum tokens: %w", err) + if scanErr := row.Scan(&totalTokens); scanErr != nil { + return fmt.Errorf("sum tokens: %w", scanErr) } _, err = tx.ExecContext(context.Background(), "UPDATE sessions SET total_tokens = ?, updated_at = ? WHERE id = ?", diff --git a/internal/snapshot/workspace_test.go b/internal/snapshot/workspace_test.go index cb498fe8..ac41ccb7 100644 --- a/internal/snapshot/workspace_test.go +++ b/internal/snapshot/workspace_test.go @@ -135,7 +135,9 @@ func TestRestore_BringsBackOriginalState(t *testing.T) { // Make changes os.WriteFile(filepath.Join(dir, "main.go"), []byte("package main\n\n// CHANGED\nfunc main() {}\n"), 0o644) os.WriteFile(filepath.Join(dir, "new_file.go"), []byte("package main\n"), 0o644) - os.Remove(filepath.Join(dir, "README.md")) + if removeErr := os.Remove(filepath.Join(dir, "README.md")); removeErr != nil { + t.Fatalf("remove README: %v", removeErr) + } // Verify changes exist content, _ := os.ReadFile(filepath.Join(dir, "main.go")) @@ -159,7 +161,7 @@ func TestRestore_BringsBackOriginalState(t *testing.T) { } // Verify new file was deleted - if _, err := os.Stat(filepath.Join(dir, "new_file.go")); !os.IsNotExist(err) { + if _, statErr := os.Stat(filepath.Join(dir, "new_file.go")); !os.IsNotExist(statErr) { t.Error("new_file.go should be deleted after restore") } diff --git a/internal/tool/api_compat.go b/internal/tool/api_compat.go index ab932978..203c64c3 100644 --- a/internal/tool/api_compat.go +++ b/internal/tool/api_compat.go @@ -688,8 +688,8 @@ func (t *APICompatTool) Execute(ctx context.Context, input json.RawMessage) (str if savePath == "" { savePath = params.PackagePath + "/.api_baseline.json" } - if err := t.checker.SaveSnapshot(current, savePath); err != nil { - return "", err + if saveErr := t.checker.SaveSnapshot(current, savePath); saveErr != nil { + return "", saveErr } return fmt.Sprintf("Saved API baseline to %s (%d functions, %d types, %d interfaces)", savePath, len(current.Functions), len(current.Types), len(current.Interfaces)), nil diff --git a/internal/tool/api_compat_test.go b/internal/tool/api_compat_test.go index 52ff090f..f5e8aeb3 100644 --- a/internal/tool/api_compat_test.go +++ b/internal/tool/api_compat_test.go @@ -410,8 +410,8 @@ func TestSaveAndLoadSnapshot(t *testing.T) { } savePath := filepath.Join(t.TempDir(), "baseline.json") - if err := cc.SaveSnapshot(snap, savePath); err != nil { - t.Fatalf("SaveSnapshot failed: %v", err) + if saveErr := cc.SaveSnapshot(snap, savePath); saveErr != nil { + t.Fatalf("SaveSnapshot failed: %v", saveErr) } loaded, err := cc.LoadSnapshot(savePath) diff --git a/internal/tool/backup.go b/internal/tool/backup.go index c6569244..a7cd890e 100644 --- a/internal/tool/backup.go +++ b/internal/tool/backup.go @@ -67,8 +67,8 @@ func RestoreFromBackup(path string) error { for _, e := range entries { name := e.Name() if len(name) > len(baseName)+1 && name[:len(baseName)] == baseName { - info, err := e.Info() - if err != nil { + info, infoErr := e.Info() + if infoErr != nil { continue } if info.ModTime().After(latestTime) { @@ -124,16 +124,16 @@ func UndoLatest() (string, error) { continue } subDir := filepath.Join(backupsRoot, d.Name()) - entries, err := os.ReadDir(subDir) - if err != nil { + entries, readErr := os.ReadDir(subDir) + if readErr != nil { continue } for _, e := range entries { if strings.HasPrefix(e.Name(), ".") { continue } - info, err := e.Info() - if err != nil { + info, infoErr := e.Info() + if infoErr != nil { continue } if info.ModTime().After(bestTime) { diff --git a/internal/tool/codegraph.go b/internal/tool/codegraph.go index 2464baf6..fd6d6501 100644 --- a/internal/tool/codegraph.go +++ b/internal/tool/codegraph.go @@ -700,7 +700,7 @@ func crossRepoCodeGraph(query string, maxNodes int) (string, error) { for _, entry := range entries { if entry.IsDir() { dbPath := filepath.Join(parentDir, entry.Name(), ".codegraph", "codegraph.db") - if _, err := os.Stat(dbPath); err == nil { + if _, statErr := os.Stat(dbPath); statErr == nil { repos = append(repos, filepath.Join(parentDir, entry.Name())) } } diff --git a/internal/tool/git_commit_test.go b/internal/tool/git_commit_test.go index dbf2377a..e9e50d48 100644 --- a/internal/tool/git_commit_test.go +++ b/internal/tool/git_commit_test.go @@ -85,8 +85,8 @@ func TestAutoCommitAndRevert(t *testing.T) { } // Revert the auto-commit. - if err := RevertLastAutoCommit(); err != nil { - t.Fatalf("RevertLastAutoCommit: %v", err) + if revertErr := RevertLastAutoCommit(); revertErr != nil { + t.Fatalf("RevertLastAutoCommit: %v", revertErr) } // After revert, HEAD should point to the commit before auto-commit. diff --git a/internal/tool/git_fs.go b/internal/tool/git_fs.go index 38a41ae5..163995a0 100644 --- a/internal/tool/git_fs.go +++ b/internal/tool/git_fs.go @@ -30,9 +30,9 @@ func ReadGitState(dir string) (*GitState, error) { // If .git is a file, it's a worktree reference worktree := false if !info.IsDir() { - data, err := os.ReadFile(gitDir) - if err != nil { - return nil, err + data, readErr := os.ReadFile(gitDir) + if readErr != nil { + return nil, readErr } line := strings.TrimSpace(string(data)) if strings.HasPrefix(line, "gitdir: ") { diff --git a/internal/tool/lsp.go b/internal/tool/lsp.go index 7cfbc989..2a3da586 100644 --- a/internal/tool/lsp.go +++ b/internal/tool/lsp.go @@ -143,12 +143,12 @@ func lspReferences(root, filePath string, line int, symbol string) (string, erro // Get symbol name sym := symbol if sym == "" && line > 0 { - absPath, err := filepath.Abs(filePath) - if err != nil { + absPath, absErr := filepath.Abs(filePath) + if absErr != nil { absPath = filePath } - source, err := os.ReadFile(absPath) - if err == nil { + source, readErr := os.ReadFile(absPath) + if readErr == nil { lines := strings.Split(string(source), "\n") if line <= len(lines) { sym = extractSymbolFromLine(lines[line-1]) diff --git a/internal/tool/tool_integration_test.go b/internal/tool/tool_integration_test.go index a8b6db3e..1c030f43 100644 --- a/internal/tool/tool_integration_test.go +++ b/internal/tool/tool_integration_test.go @@ -27,8 +27,8 @@ func TestIntegration_BashThenRead(t *testing.T) { } // Verify the file exists on disk. - if _, err := os.Stat(filePath); err != nil { - t.Fatalf("expected file to exist after bash: %v", err) + if _, statErr := os.Stat(filePath); statErr != nil { + t.Fatalf("expected file to exist after bash: %v", statErr) } // Read reads it back. diff --git a/internal/tool/transaction.go b/internal/tool/transaction.go index ac45d6f0..31d06524 100644 --- a/internal/tool/transaction.go +++ b/internal/tool/transaction.go @@ -115,12 +115,12 @@ func (tx *Transaction) Add(op FileOperation) error { if info.IsDir() { return fmt.Errorf("cannot rename %s: is a directory", op.OldPath) } - if _, err := os.Stat(op.Path); err == nil { + if _, statErr := os.Stat(op.Path); statErr == nil { return fmt.Errorf("cannot rename to %s: file already exists", op.Path) } - data, err := os.ReadFile(op.OldPath) - if err != nil { - return fmt.Errorf("cannot read %s for backup: %w", op.OldPath, err) + data, readErr := os.ReadFile(op.OldPath) + if readErr != nil { + return fmt.Errorf("cannot read %s for backup: %w", op.OldPath, readErr) } op.OldContent = data if op.Mode == 0 {