diff --git a/internal/agent/profile_controller.go b/internal/agent/profile_controller.go index 416c60f0d..c1d093506 100644 --- a/internal/agent/profile_controller.go +++ b/internal/agent/profile_controller.go @@ -91,7 +91,7 @@ func (c *profileController) maybeEscalate() (PostureEscalation, bool) { if c.policy == nil || c.escalated { return PostureEscalation{}, false } - if !(c.failureTripped || c.riskTripped || c.scTripped || c.uncertainTrip) { + if !c.failureTripped && !c.riskTripped && !c.scTripped && !c.uncertainTrip { return PostureEscalation{}, false } c.escalated = true diff --git a/internal/agenteval/score.go b/internal/agenteval/score.go index 73002902a..174aa3cca 100644 --- a/internal/agenteval/score.go +++ b/internal/agenteval/score.go @@ -125,9 +125,7 @@ func Score(suite Suite, input ScoreInput) Report { if len(task.RequiredTraceEvents) > 0 { report.Results = append(report.Results, scoreTraceEvents(task.RequiredTraceEvents, input)) } - for _, result := range unknownCommandResults(input.CommandResults, seenCommands, input) { - report.Results = append(report.Results, result) - } + report.Results = append(report.Results, unknownCommandResults(input.CommandResults, seenCommands, input)...) report.finishSummary() return report } diff --git a/internal/agentinit/agentinit.go b/internal/agentinit/agentinit.go index 060fe4f68..a65b5486a 100644 --- a/internal/agentinit/agentinit.go +++ b/internal/agentinit/agentinit.go @@ -40,14 +40,14 @@ func FormatFacts(info repoinfo.Info) string { b.WriteString("Pre-computed repository facts (from a local scan — verify and fill gaps):\n") if info.PrimaryLanguage != "" { - b.WriteString(fmt.Sprintf("- Primary language: %s (of %d detected)\n", info.PrimaryLanguage, info.LanguageCount)) + fmt.Fprintf(&b, "- Primary language: %s (of %d detected)\n", info.PrimaryLanguage, info.LanguageCount) } if langs := topLanguages(info.Languages, 5); langs != "" { b.WriteString("- Languages: " + langs + "\n") } - b.WriteString(fmt.Sprintf("- Size: ~%d files, ~%d LOC, max dir depth %d\n", info.FileCount, info.LOCEstimate, info.MaxDepth)) + fmt.Fprintf(&b, "- Size: ~%d files, ~%d LOC, max dir depth %d\n", info.FileCount, info.LOCEstimate, info.MaxDepth) if info.WorkspaceType != "" && info.WorkspaceType != "none" { - b.WriteString(fmt.Sprintf("- Workspace: %s (%d packages)\n", info.WorkspaceType, info.WorkspacePackageCount)) + fmt.Fprintf(&b, "- Workspace: %s (%d packages)\n", info.WorkspaceType, info.WorkspacePackageCount) } if len(info.BuildTools) > 0 { b.WriteString("- Build tools: " + strings.Join(info.BuildTools, ", ") + "\n") diff --git a/internal/cli/agent_eval.go b/internal/cli/agent_eval.go index e8cb80fef..d0f6e6ce8 100644 --- a/internal/cli/agent_eval.go +++ b/internal/cli/agent_eval.go @@ -515,9 +515,7 @@ func agentEvalReportFromBenchmark(suite agenteval.Suite, report agenteval.Benchm if task.Agent.Truncated { converted.Truncated = true } - for _, failure := range agentEvalFailuresFromTaskReport(task) { - converted.Failures = append(converted.Failures, failure) - } + converted.Failures = append(converted.Failures, agentEvalFailuresFromTaskReport(task)...) } return converted } diff --git a/internal/cli/mcp_config.go b/internal/cli/mcp_config.go index 603fcd50a..6abd20365 100644 --- a/internal/cli/mcp_config.go +++ b/internal/cli/mcp_config.go @@ -734,14 +734,12 @@ func (cfg *mcpWritableConfig) setServerDisabled(name string, disabled bool) (boo switch { case legacyFound: raw = legacyRaw - found = true case config.IsDefaultMCPServer(name): // A built-in default server isn't written to the file until the user // overrides it. Treat it as present with an empty base so disabling it // writes a minimal {"disabled":true} entry that merges over the default — // letting `zero mcp disable ` work even though it lives in code. raw = nil - found = true default: return false, false, nil } diff --git a/internal/cli/provider_detect.go b/internal/cli/provider_detect.go index c4063bd90..8c06667c0 100644 --- a/internal/cli/provider_detect.go +++ b/internal/cli/provider_detect.go @@ -83,10 +83,10 @@ func runProvidersDetect(args []string, stdout io.Writer, stderr io.Writer, deps func parseProviderDetectArgs(args []string) (providerDetectOptions, bool, error) { options := providerDetectOptions{} for _, arg := range args { - switch { - case arg == "-h" || arg == "--help" || arg == "help": + switch arg { + case "-h", "--help", "help": return options, true, nil - case arg == "--json": + case "--json": options.json = true default: return options, false, execUsageError{fmt.Sprintf("unexpected argument %q", arg)} diff --git a/internal/cli/usage.go b/internal/cli/usage.go index 0c133d68e..bdffe2652 100644 --- a/internal/cli/usage.go +++ b/internal/cli/usage.go @@ -244,19 +244,19 @@ func parseUsageArgs(args []string) (usageOptions, bool, error) { func FormatReport(report usage.Report, insertions int, deletions int) string { var builder strings.Builder builder.WriteString("Usage report (cost is a reconstructed estimate)\n\n") - builder.WriteString(fmt.Sprintf("%-12s %10s %14s %14s\n", "date", "requests", "tokens", "est. cost")) + fmt.Fprintf(&builder, "%-12s %10s %14s %14s\n", "date", "requests", "tokens", "est. cost") for _, bucket := range report.Buckets { - builder.WriteString(fmt.Sprintf("%-12s %10d %14s %14s\n", - bucket.Date, bucket.Requests, groupThousands(bucket.TotalTokens), formatUSD(bucket.TotalCost))) + fmt.Fprintf(&builder, "%-12s %10d %14s %14s\n", + bucket.Date, bucket.Requests, groupThousands(bucket.TotalTokens), formatUSD(bucket.TotalCost)) } - builder.WriteString(fmt.Sprintf("\n%-12s %10d %14s %14s\n", - "total", report.Total.Requests, groupThousands(report.Total.TotalTokens), formatUSD(report.Total.TotalCost))) + fmt.Fprintf(&builder, "\n%-12s %10d %14s %14s\n", + "total", report.Total.Requests, groupThousands(report.Total.TotalTokens), formatUSD(report.Total.TotalCost)) - builder.WriteString(fmt.Sprintf("\nnet LOC (estimate): +%d / -%d = %d\n", - insertions, deletions, report.NetLOC)) + fmt.Fprintf(&builder, "\nnet LOC (estimate): +%d / -%d = %d\n", + insertions, deletions, report.NetLOC) if report.NetLOCPositive { - builder.WriteString(fmt.Sprintf("tokens per net LOC: %.1f\n", report.TokensPerNetLOC)) - builder.WriteString(fmt.Sprintf("est. cost per net LOC: %s\n", formatUSD(report.CostPerNetLOC))) + fmt.Fprintf(&builder, "tokens per net LOC: %.1f\n", report.TokensPerNetLOC) + fmt.Fprintf(&builder, "est. cost per net LOC: %s\n", formatUSD(report.CostPerNetLOC)) } else { builder.WriteString("tokens per net LOC: n/a (net LOC <= 0)\n") builder.WriteString("est. cost per net LOC: n/a (net LOC <= 0)\n") diff --git a/internal/config/mcp_merge.go b/internal/config/mcp_merge.go index 816ccb54c..4a1717f38 100644 --- a/internal/config/mcp_merge.go +++ b/internal/config/mcp_merge.go @@ -87,7 +87,7 @@ func mergeMCPServer(base MCPServerConfig, next MCPServerConfig, canReenable bool // server the user explicitly enabled. The only layer allowed to // override an explicit higher-scope decision is the CLI override scope // (canReenable=true). - if canReenable || !(baseDisabledSet && baseDisabled != next.Disabled) { + if canReenable || !baseDisabledSet || baseDisabled == next.Disabled { base.Disabled = next.Disabled } } diff --git a/internal/dictation/transcriber_deepgram.go b/internal/dictation/transcriber_deepgram.go index b8b9319aa..d4a69ce7f 100644 --- a/internal/dictation/transcriber_deepgram.go +++ b/internal/dictation/transcriber_deepgram.go @@ -100,7 +100,7 @@ func (d *deepgramTranscriber) StreamTranscribe(ctx context.Context, chunks <-cha } default: } - return compose(), fmt.Errorf("Deepgram stream error: %w", err) + return compose(), fmt.Errorf("Deepgram stream error: %w", err) //nolint:staticcheck // Preserve established user-facing error text. } if typ != websocket.MessageText { continue diff --git a/internal/imageinput/pdf_test.go b/internal/imageinput/pdf_test.go index 72d61d081..614250ab3 100644 --- a/internal/imageinput/pdf_test.go +++ b/internal/imageinput/pdf_test.go @@ -48,7 +48,7 @@ func buildMinimalPDF(text string) []byte { buf.WriteString("0 " + strconv.Itoa(len(offsets)+1) + "\n") buf.WriteString("0000000000 65535 f \n") for _, off := range offsets { - buf.WriteString(fmt.Sprintf("%010d 00000 n \n", off)) + fmt.Fprintf(&buf, "%010d 00000 n \n", off) } buf.WriteString("trailer\n<< /Size " + strconv.Itoa(len(offsets)+1) + " /Root 1 0 R >>\n") buf.WriteString("startxref\n" + strconv.Itoa(xrefStart) + "\n%%EOF\n") @@ -277,7 +277,7 @@ func buildEmptyTextPDF() []byte { buf.WriteString("0 " + strconv.Itoa(len(offsets)+1) + "\n") buf.WriteString("0000000000 65535 f \n") for _, off := range offsets { - buf.WriteString(fmt.Sprintf("%010d 00000 n \n", off)) + fmt.Fprintf(&buf, "%010d 00000 n \n", off) } buf.WriteString("trailer\n<< /Size " + strconv.Itoa(len(offsets)+1) + " /Root 1 0 R >>\n") buf.WriteString("startxref\n" + strconv.Itoa(xrefStart) + "\n%%EOF\n") diff --git a/internal/lsp/navigate_test.go b/internal/lsp/navigate_test.go index 2976a0e88..d209f7125 100644 --- a/internal/lsp/navigate_test.go +++ b/internal/lsp/navigate_test.go @@ -1,6 +1,7 @@ package lsp import ( + "context" "encoding/json" "testing" ) @@ -64,7 +65,7 @@ func TestDecodeSymbols(t *testing.T) { func TestNavigateUnknownOp(t *testing.T) { m := NewManager(t.TempDir()) - _, _, ok, err := m.Navigate(nil, NavRequest{Op: "bogus", Path: "x.go"}) + _, _, ok, err := m.Navigate(context.TODO(), NavRequest{Op: "bogus", Path: "x.go"}) if err == nil { t.Fatal("expected an error for an unknown nav op") } @@ -76,7 +77,7 @@ func TestNavigateUnknownOp(t *testing.T) { func TestNavigateUnsupportedExtensionDegrades(t *testing.T) { // A file type with no configured server degrades to ok=false, no error. m := NewManager(t.TempDir()) - _, _, ok, err := m.Navigate(nil, NavRequest{Op: NavDefinition, Path: "notes.unknownext", Line: 1, Character: 1}) + _, _, ok, err := m.Navigate(context.TODO(), NavRequest{Op: NavDefinition, Path: "notes.unknownext", Line: 1, Character: 1}) if err != nil { t.Fatalf("unsupported extension should not error, got %v", err) } diff --git a/internal/providerhealth/providerhealth.go b/internal/providerhealth/providerhealth.go index fe375a43f..b213a9d88 100644 --- a/internal/providerhealth/providerhealth.go +++ b/internal/providerhealth/providerhealth.go @@ -391,7 +391,7 @@ func validateEndpoint(ctx context.Context, endpoint string, resolver Resolver, a return endpointSafetyError{message: "provider connectivity URL is unsafe: localhost hosts are blocked"} } if addr, err := netip.ParseAddr(normalized); err == nil { - if reason := blockedAddrReason(addr); reason != "" && !(allowLoopbackOrPrivate && (addr.IsLoopback() || addr.IsPrivate())) { + if reason := blockedAddrReason(addr); reason != "" && (!allowLoopbackOrPrivate || (!addr.IsLoopback() && !addr.IsPrivate())) { return endpointSafetyError{message: "provider connectivity URL is unsafe: " + reason} } return nil @@ -407,7 +407,7 @@ func validateEndpoint(ctx context.Context, endpoint string, resolver Resolver, a return endpointSafetyError{message: "provider connectivity host resolved to no addresses"} } for _, addr := range addrs { - if reason := blockedAddrReason(addr); reason != "" && !(allowLoopbackOrPrivate && (addr.IsLoopback() || addr.IsPrivate())) { + if reason := blockedAddrReason(addr); reason != "" && (!allowLoopbackOrPrivate || (!addr.IsLoopback() && !addr.IsPrivate())) { return endpointSafetyError{message: "provider connectivity URL is unsafe: " + reason} } } @@ -529,7 +529,7 @@ func safeDialContext(resolver Resolver, allowLoopbackOrPrivate bool) func(contex return nil, err } if addr, parseErr := netip.ParseAddr(host); parseErr == nil { - if reason := blockedAddrReason(addr); reason != "" && !(allowLoopbackOrPrivate && (addr.IsLoopback() || addr.IsPrivate())) { + if reason := blockedAddrReason(addr); reason != "" && (!allowLoopbackOrPrivate || (!addr.IsLoopback() && !addr.IsPrivate())) { return nil, endpointSafetyError{message: "provider connectivity URL is unsafe: " + reason} } return dialer.DialContext(ctx, network, address) @@ -542,7 +542,7 @@ func safeDialContext(resolver Resolver, allowLoopbackOrPrivate bool) func(contex return nil, endpointSafetyError{message: "provider connectivity host resolved to no addresses"} } for _, addr := range addrs { - if reason := blockedAddrReason(addr); reason != "" && !(allowLoopbackOrPrivate && (addr.IsLoopback() || addr.IsPrivate())) { + if reason := blockedAddrReason(addr); reason != "" && (!allowLoopbackOrPrivate || (!addr.IsLoopback() && !addr.IsPrivate())) { return nil, endpointSafetyError{message: "provider connectivity URL is unsafe: " + reason} } } diff --git a/internal/provideronboarding/localruntime_test.go b/internal/provideronboarding/localruntime_test.go index 29df60f2b..8889cc1d4 100644 --- a/internal/provideronboarding/localruntime_test.go +++ b/internal/provideronboarding/localruntime_test.go @@ -62,7 +62,7 @@ func TestDetectLocalRuntimesReportsReachableRuntime(t *testing.T) { if !detected[0].Reachable { t.Fatalf("runtime should be reachable: %#v", detected[0]) } - if detected[0].Models == nil || len(detected[0].Models) == 0 || detected[0].Models[0] != "llama3.1" { + if len(detected[0].Models) == 0 || detected[0].Models[0] != "llama3.1" { t.Fatalf("expected discovered model list, got %#v", detected[0].Models) } } diff --git a/internal/repomap/prompt.go b/internal/repomap/prompt.go index 42390a2fb..f92c64387 100644 --- a/internal/repomap/prompt.go +++ b/internal/repomap/prompt.go @@ -188,7 +188,7 @@ func writePromptLine(builder *strings.Builder, format string, args ...any) { if builder.Len() > 0 { builder.WriteByte('\n') } - builder.WriteString(fmt.Sprintf(format, args...)) + fmt.Fprintf(builder, format, args...) } func clampBudget(text string, budget int) string { diff --git a/internal/sandbox/adapters.go b/internal/sandbox/adapters.go index 41f5fef1c..24e01d2b5 100644 --- a/internal/sandbox/adapters.go +++ b/internal/sandbox/adapters.go @@ -225,7 +225,7 @@ func (backend Backend) SandboxEnvMarkers(policy Policy) []string { if policy.Mode == ModeDisabled { return nil } - if !(backend.CommandWrapping && backend.Available) && backend.Name != BackendWSL { + if (!backend.CommandWrapping || !backend.Available) && backend.Name != BackendWSL { return nil } name := backend.Name diff --git a/internal/sandbox/command_prefix.go b/internal/sandbox/command_prefix.go index e9f402adb..53a4efd4c 100644 --- a/internal/sandbox/command_prefix.go +++ b/internal/sandbox/command_prefix.go @@ -153,10 +153,7 @@ func unsafeCommandPrefix(prefix []string) bool { return true } } - if unsafeCommandPrefixLauncher(prefix[0]) { - return true - } - return false + return unsafeCommandPrefixLauncher(prefix[0]) } func unsafeCommandPrefixPart(part string) bool { diff --git a/internal/sandbox/engine.go b/internal/sandbox/engine.go index db66d54a9..ed7440780 100644 --- a/internal/sandbox/engine.go +++ b/internal/sandbox/engine.go @@ -249,7 +249,7 @@ func (engine *Engine) shellSandboxActive(policy Policy) bool { return false } backend := engine.backend - if !(backend.Available && backend.Executable != "" && backend.CommandWrapping && backend.NativeIsolation) { + if !backend.Available || backend.Executable == "" || !backend.CommandWrapping || !backend.NativeIsolation { return false } // On Windows the command is only actually wrapped once `zero sandbox setup` diff --git a/internal/sandbox/landlock_other.go b/internal/sandbox/landlock_other.go index ec221dfb5..b271e9650 100644 --- a/internal/sandbox/landlock_other.go +++ b/internal/sandbox/landlock_other.go @@ -4,7 +4,7 @@ package sandbox import "errors" -var ErrLandlockUnsupported = errors.New("Landlock is only supported on Linux") +var ErrLandlockUnsupported = errors.New("Landlock is only supported on Linux") //nolint:staticcheck // Preserve the exported sentinel's established text. func ApplyLandlockFilesystemProfile(profile PermissionProfile, cwd string) error { return ErrLandlockUnsupported diff --git a/internal/sandbox/windows_network.go b/internal/sandbox/windows_network.go index 55fb419b6..0d614a0fc 100644 --- a/internal/sandbox/windows_network.go +++ b/internal/sandbox/windows_network.go @@ -10,7 +10,7 @@ import ( "strings" ) -var ErrWindowsNetworkEnforcementUnavailable = errors.New("Windows sandbox network enforcement is not available") +var ErrWindowsNetworkEnforcementUnavailable = errors.New("Windows sandbox network enforcement is not available") //nolint:staticcheck // Preserve the exported sentinel's established text. const ( windowsWFPProviderKey = "2e31d31c-3948-4753-9117-e5d1a6496f41" diff --git a/internal/specialist/exec.go b/internal/specialist/exec.go index 6dac1d259..702360543 100644 --- a/internal/specialist/exec.go +++ b/internal/specialist/exec.go @@ -827,7 +827,7 @@ func runChildProcess(ctx context.Context, binaryPath string, args []string, prog // ExitCode() is -1 when the child was terminated by a signal rather // than exiting. ProcessState.String() is the portable description // (e.g. "signal: killed") — capture it so the failure isn't opaque. - signalDesc = exitErr.ProcessState.String() + signalDesc = exitErr.String() } } else { return ChildRunResult{Events: events, Stderr: stderr.String(), ExitCode: -1, Started: started}, fmt.Errorf("run specialist child: %w", err) diff --git a/internal/tui/command_center.go b/internal/tui/command_center.go index 8db9f822f..d3449a538 100644 --- a/internal/tui/command_center.go +++ b/internal/tui/command_center.go @@ -548,7 +548,7 @@ func (m model) switchProviderModel(providerName, modelID string) (model, string, // and a stored OAuth login (e.g. ChatGPT) is a credential too — the profile stays // keyless on purpose so newProvider attaches the bearer resolver + login key. if strings.TrimSpace(target.APIKey) == "" && strings.TrimSpace(target.AuthHeaderValue) == "" && - !(hasDescriptor && descriptor.Local) && !oauthLoginAvailable(target) { + (!hasDescriptor || !descriptor.Local) && !oauthLoginAvailable(target) { return m, "Model\nprovider " + strconv.Quote(providerName) + " has no usable credential — run setup or `zero auth login " + providerName + "`.", false, nil } next, err := m.newProvider(target) diff --git a/internal/tui/export_test.go b/internal/tui/export_test.go index f9af6f45a..180e4b03d 100644 --- a/internal/tui/export_test.go +++ b/internal/tui/export_test.go @@ -8,7 +8,6 @@ import ( "strings" "time" - tea "charm.land/bubbletea/v2" "charm.land/lipgloss/v2" "github.com/Gitlawb/zero/internal/dictation" ) @@ -87,10 +86,6 @@ func (m model) scrollableTranscriptLayoutView(header string, body transcriptBody return m.renderScrollableTranscriptWindow(frame, bodyWindow, window, width, overlay) } -func (m model) scrollableTranscriptView(header string, body string, footer string, width int, overlay string) string { - return m.scrollableTranscriptLayoutView(header, transcriptBodyLayout{lines: viewLines(body)}, footer, width, overlay) -} - func (m model) overlayMouseTop(overlayHeight int, width int) int { return m.overlayMouseRect(overlayHeight, width).y } @@ -230,17 +225,6 @@ func (d *streamingDecoder) tailLines() []string { return out } -// ensureAgeTickReschedule is a small helper used after a fade-state change -// to start the tick if it's not already running. The age-tick case -// short-circuits when fadeActive is false, so calling this on a no-op -// transition (e.g. a 0-byte delta) is safe. -func (m model) ensureAgeTickReschedule() tea.Cmd { - if !m.fadeActive { - return nil - } - return streamingFadeTick() -} - // newSTTDownloadPicker builds the model-download chooser, seeded with the // curated shortlist. The full model list from the release is fetched // asynchronously and merged in (see fetchSTTModelsCmd / handleSTTModelsFetched). @@ -288,11 +272,6 @@ func transcriptViewportStartForFrame(body string, frame transcriptFrameLayout, s return window.start, window.height, frame.bodyRect.y } -func transcriptViewportStartForLayout(layout transcriptBodyLayout, frame transcriptFrameLayout, scrollOffset int) (int, int, int) { - window := transcriptViewportForLayout(layout, frame, scrollOffset).window() - return window.start, window.height, frame.bodyRect.y -} - func transcriptViewportForBody(body string, frame transcriptFrameLayout, offset int) transcriptViewport { return newTranscriptViewport(len(viewLines(body)), frame.bodyRect.height, offset) } diff --git a/internal/tui/files_git_sweep_test.go b/internal/tui/files_git_sweep_test.go index 484392e39..cccdcb4d9 100644 --- a/internal/tui/files_git_sweep_test.go +++ b/internal/tui/files_git_sweep_test.go @@ -1,6 +1,7 @@ package tui import ( + "context" "os" "os/exec" "path/filepath" @@ -192,7 +193,7 @@ func TestGitSweepCmdAgainstRealRepo(t *testing.T) { run("commit", "-q", "-m", "seed") write("pre-existing.txt", "dirt\n") // dirty BEFORE the TUI "opens" - baseline := gitSweepCmd(nil, dir, true)().(gitSweepMsg) + baseline := gitSweepCmd(context.TODO(), dir, true)().(gitSweepMsg) if !baseline.ok || len(baseline.files) != 1 || baseline.files[0].path != "pre-existing.txt" { t.Fatalf("baseline should see only the pre-existing dirt: %+v", baseline) } @@ -201,7 +202,7 @@ func TestGitSweepCmdAgainstRealRepo(t *testing.T) { write("scaffolded.txt", "hello\n") write("tracked.txt", "one\ntwo\nthree\nfour\n") - sweep := gitSweepCmd(nil, dir, false)().(gitSweepMsg) + sweep := gitSweepCmd(context.TODO(), dir, false)().(gitSweepMsg) if !sweep.ok { t.Fatal("sweep failed") } @@ -224,7 +225,7 @@ func TestGitSweepCmdAgainstRealRepo(t *testing.T) { run("commit", "-q", "-m", "second") run("mv", "tracked.txt", "renamed.txt") write("renamed.txt", "one\ntwo\nthree\nfour\nfive\n") - renameSweep := gitSweepCmd(nil, dir, false)().(gitSweepMsg) + renameSweep := gitSweepCmd(context.TODO(), dir, false)().(gitSweepMsg) if !renameSweep.ok { t.Fatal("rename sweep failed") } @@ -237,7 +238,7 @@ func TestGitSweepCmdAgainstRealRepo(t *testing.T) { } // Not-a-repo → ok=false (the sweep latches off). - if msg := gitSweepCmd(nil, t.TempDir(), false)().(gitSweepMsg); msg.ok { + if msg := gitSweepCmd(context.TODO(), t.TempDir(), false)().(gitSweepMsg); msg.ok { t.Fatal("a non-repo should report ok=false") } } diff --git a/internal/tui/flush.go b/internal/tui/flush.go index 8034500b8..0d5e1548e 100644 --- a/internal/tui/flush.go +++ b/internal/tui/flush.go @@ -46,7 +46,7 @@ func (m model) settledRow(row transcriptRow, rc rowContext) bool { if row.id != "" && rc.resolved[rcKey(row.runID, row.id)] { return true } - return !(m.pending && row.runID != 0 && row.runID == m.activeRunID) + return !m.pending || row.runID == 0 || row.runID != m.activeRunID case rowPermission: event := row.permission if event == nil || event.ToolCallID == "" || event.Action != agent.PermissionActionPrompt { @@ -57,7 +57,7 @@ func (m model) settledRow(row transcriptRow, rc rowContext) bool { } // An undecided prompt renders live (with the modal card) until its // decision lands or its run ends. - return !(m.pending && row.runID != 0 && row.runID == m.activeRunID) + return !m.pending || row.runID == 0 || row.runID != m.activeRunID default: // User/system/error/assistant/ask-user rows are appended in final form; // welcome rows render nothing and settle trivially. diff --git a/internal/tui/image_attach_test.go b/internal/tui/image_attach_test.go index d4754028d..33a78b771 100644 --- a/internal/tui/image_attach_test.go +++ b/internal/tui/image_attach_test.go @@ -290,7 +290,7 @@ func writeTestPDF(t *testing.T, dir, name, text string) string { xrefStart := buf.Len() buf.WriteString("xref\n0 " + strconv.Itoa(len(offsets)+1) + "\n0000000000 65535 f \n") for _, off := range offsets { - buf.WriteString(fmt.Sprintf("%010d 00000 n \n", off)) + fmt.Fprintf(&buf, "%010d 00000 n \n", off) } buf.WriteString("trailer\n<< /Size " + strconv.Itoa(len(offsets)+1) + " /Root 1 0 R >>\nstartxref\n" + strconv.Itoa(xrefStart) + "\n%%EOF\n") diff --git a/internal/tui/loop.go b/internal/tui/loop.go index 0d0ea7392..03fb5803f 100644 --- a/internal/tui/loop.go +++ b/internal/tui/loop.go @@ -594,8 +594,8 @@ func (m model) loopListText() string { when = "due" } } - b.WriteString(fmt.Sprintf(" %s · %s · iter %d · %s · %s\n", - l.id, l.cadenceText(), l.iteration, when, truncateLoopPrompt(l.prompt))) + fmt.Fprintf(&b, " %s · %s · iter %d · %s · %s\n", + l.id, l.cadenceText(), l.iteration, when, truncateLoopPrompt(l.prompt)) } b.WriteString("Stop with /loop stop or /loop stop all.") return b.String() diff --git a/internal/tui/model_test.go b/internal/tui/model_test.go index 65bc18fd4..f2be354aa 100644 --- a/internal/tui/model_test.go +++ b/internal/tui/model_test.go @@ -1396,7 +1396,7 @@ func TestBeginRunPreparesRunCompletionWarningEachTurn(t *testing.T) { }) m = m.beginRun(nil) - m = m.beginRun(nil) + _ = m.beginRun(nil) if prepares != 2 { t.Fatalf("PrepareRunCompletionWarning called %d times, want once per run", prepares) diff --git a/internal/tui/onboarding.go b/internal/tui/onboarding.go index c4b26705c..ed09f3a87 100644 --- a/internal/tui/onboarding.go +++ b/internal/tui/onboarding.go @@ -218,20 +218,22 @@ func (m model) handleSetupKey(msg tea.KeyMsg) (tea.Model, tea.Cmd) { } return m, nil case keyIs(msg, tea.KeyUp) || keyCtrl(msg, 'p'): - if m.setup.stage == setupStageMethod { + switch m.setup.stage { + case setupStageMethod: m.moveSetupMethod(-1) - } else if m.setup.stage == setupStageProvider { + case setupStageProvider: m.moveSetupProvider(-1) - } else if m.setup.stage == setupStageModel { + case setupStageModel: m.moveSetupModel(-1) } return m, nil case keyIs(msg, tea.KeyDown) || keyCtrl(msg, 'n'): - if m.setup.stage == setupStageMethod { + switch m.setup.stage { + case setupStageMethod: m.moveSetupMethod(1) - } else if m.setup.stage == setupStageProvider { + case setupStageProvider: m.moveSetupProvider(1) - } else if m.setup.stage == setupStageModel { + case setupStageModel: m.moveSetupModel(1) } return m, nil @@ -279,15 +281,17 @@ func (m model) handleSetupKey(msg tea.KeyMsg) (tea.Model, tea.Cmd) { case "q": return m, tea.Quit case "k": - if m.setup.stage == setupStageProvider { + switch m.setup.stage { + case setupStageProvider: m.moveSetupProvider(-1) - } else if m.setup.stage == setupStageModel { + case setupStageModel: m.moveSetupModel(-1) } case "j": - if m.setup.stage == setupStageProvider { + switch m.setup.stage { + case setupStageProvider: m.moveSetupProvider(1) - } else if m.setup.stage == setupStageModel { + case setupStageModel: m.moveSetupModel(1) } } @@ -360,16 +364,18 @@ func (m model) handleSetupMouse(msg tea.MouseMsg) (tea.Model, tea.Cmd) { switch { case mouseWheelUp(msg): m.clearMouseSelection() - if m.setup.stage == setupStageProvider { + switch m.setup.stage { + case setupStageProvider: m.moveSetupProvider(-1) - } else if m.setup.stage == setupStageModel { + case setupStageModel: m.moveSetupModel(-1) } case mouseWheelDown(msg): m.clearMouseSelection() - if m.setup.stage == setupStageProvider { + switch m.setup.stage { + case setupStageProvider: m.moveSetupProvider(1) - } else if m.setup.stage == setupStageModel { + case setupStageModel: m.moveSetupModel(1) } } diff --git a/internal/tui/provider_wizard_test.go b/internal/tui/provider_wizard_test.go index ef65cb426..1013bd917 100644 --- a/internal/tui/provider_wizard_test.go +++ b/internal/tui/provider_wizard_test.go @@ -687,7 +687,7 @@ func TestProviderWizardPersistsPastedKeyToUserConfig(t *testing.T) { updated, _ = next.Update(testKey(tea.KeyEnter)) next = updated.(model) updated, _ = next.Update(testKey(tea.KeyEnter)) - next = updated.(model) + _ = updated.(model) if captured.APIKey != secret { t.Fatalf("captured APIKey = %q, want pasted secret", captured.APIKey) diff --git a/internal/tui/rendering.go b/internal/tui/rendering.go index c64a8c259..a5e6ec4ab 100644 --- a/internal/tui/rendering.go +++ b/internal/tui/rendering.go @@ -1473,7 +1473,7 @@ func renderToolResultCard(row transcriptRow, width int, rc rowContext, opts card // scrollback clean. Skipped for: the uncapped detailed view (opts.bodyCap==0), // diff tools whose body must stay reviewable, and short output. collapsedFooter := "" - if opts.bodyCap > 0 && !toolCardAlwaysExpands(name) && !(!failed && (isExploreTool(name) || isLocalControlTool(name))) { + if opts.bodyCap > 0 && !toolCardAlwaysExpands(name) && (failed || (!isExploreTool(name) && !isLocalControlTool(name))) { collapsedFooter = collapsedToolFooter(row.detail) } if collapsedFooter != "" && !row.expanded { diff --git a/internal/tui/specialist_card.go b/internal/tui/specialist_card.go index 0ba119ba3..2bd7160fd 100644 --- a/internal/tui/specialist_card.go +++ b/internal/tui/specialist_card.go @@ -393,10 +393,10 @@ func toolCallSummary(event streamjson.Event) string { case "write_stdin": sessionID := toolCallIntArg(args, "session_id") chars, _ := args["chars"].(string) - switch { - case chars == "": + switch chars { + case "": return fmt.Sprintf("poll session %d", sessionID) - case chars == "\x03": + case "\x03": return fmt.Sprintf("interrupt session %d", sessionID) default: return fmt.Sprintf("send input to session %d", sessionID) diff --git a/internal/tui/theme.go b/internal/tui/theme.go index 4859fd45a..9e708c3b3 100644 --- a/internal/tui/theme.go +++ b/internal/tui/theme.go @@ -220,8 +220,3 @@ func (t tuiTheme) onPanel(style lipgloss.Style) lipgloss.Style { func (t tuiTheme) onSel(style lipgloss.Style) lipgloss.Style { return style.Background(t.bgSel) } - -// onPerm paints on the permission-card tint. -func (t tuiTheme) onPerm(style lipgloss.Style) lipgloss.Style { - return style.Background(t.bgPerm) -} diff --git a/internal/tui/transcript_selection.go b/internal/tui/transcript_selection.go index a04fe1724..8a70bf08e 100644 --- a/internal/tui/transcript_selection.go +++ b/internal/tui/transcript_selection.go @@ -1360,7 +1360,7 @@ func (m model) handleTranscriptSelectionMouse(msg tea.MouseMsg) (model, tea.Cmd, } return m, nil, false } - if line.permOption && !(m.pendingPermission != nil && m.pendingPermission.typing) { + if line.permOption && (m.pendingPermission == nil || !m.pendingPermission.typing) { // A left-click on a permission-popup option resolves it directly. The // typing guard is defence-in-depth: renderFocusedPermissionPrompt already // returns nil offsets in feedback mode, so no option row is registered as diff --git a/internal/update/apply.go b/internal/update/apply.go index 29736de1a..4f97dd458 100644 --- a/internal/update/apply.go +++ b/internal/update/apply.go @@ -162,10 +162,11 @@ func applyStandaloneUpdate(ctx context.Context, result Result, executablePath st binaryName := "zero" optionalBinaries := linuxOptionalBinaries - if runtime.GOOS == "windows" { + switch runtime.GOOS { + case "windows": binaryName = "zero.exe" optionalBinaries = windowsOptionalBinaries - } else if runtime.GOOS == "darwin" { + case "darwin": optionalBinaries = nil } diff --git a/internal/update/apply_test.go b/internal/update/apply_test.go index 379273498..80e9d9f01 100644 --- a/internal/update/apply_test.go +++ b/internal/update/apply_test.go @@ -151,10 +151,11 @@ func TestApplyStandaloneUpdateReplacesBinary(t *testing.T) { func TestApplyStandaloneUpdateWarnsWhenHelperRefreshFails(t *testing.T) { binaryName := "zero" optionalName := "zero-seccomp" - if runtime.GOOS == "windows" { + switch runtime.GOOS { + case "windows": binaryName = "zero.exe" optionalName = "zero-windows-command-runner.exe" - } else if runtime.GOOS == "darwin" { + case "darwin": t.Skip("macOS ships no optional helper binaries to refresh") } diff --git a/internal/update/update.go b/internal/update/update.go index 43e875d84..b4b11d1f0 100644 --- a/internal/update/update.go +++ b/internal/update/update.go @@ -344,7 +344,7 @@ func releasePlatform(goos string) (string, error) { // self-updating release asset. Point users at `npm update` rather // than a source rebuild, since that's the documented Termux // install/upgrade path and doesn't require a Go toolchain. - return "", fmt.Errorf("no published release for %q (release assets: linux, macos, windows). Your build is the current version of record. Upgrade with `npm update -g @gitlawb/zero` to get the latest.", goos) + return "", fmt.Errorf("no published release for %q (release assets: linux, macos, windows). Your build is the current version of record. Upgrade with `npm update -g @gitlawb/zero` to get the latest.", goos) //nolint:staticcheck // Preserve established user-facing error text. } } diff --git a/internal/usercommands/usercommands.go b/internal/usercommands/usercommands.go index 3cb969ca9..f043e1bb9 100644 --- a/internal/usercommands/usercommands.go +++ b/internal/usercommands/usercommands.go @@ -109,7 +109,7 @@ func validCommandName(name string) bool { return false } for _, r := range name { - if !(r >= 'a' && r <= 'z') && !(r >= '0' && r <= '9') && r != '-' { + if (r < 'a' || r > 'z') && (r < '0' || r > '9') && r != '-' { return false } }