Polish: theme, animation, non-TTY purity, robustness - #282
Merged
Conversation
The index URL referenced GrayCodeAI/starling, a repo renamed to graycode-skills whose registry.json is generated and never committed, so the URL 404d under either name. It now reads the rolling release asset published by graycode-skills' publish-registry.yml. Claude-Session: https://claude.ai/code/session_01MTUKadN91fcmuhxGWYVe2k
plugins-registry.json is generated by nothing in any of the four GrayCode repos; the only reference anywhere was this default source. FetchAll with no sources returns an empty list rather than erroring. Claude-Session: https://claude.ai/code/session_01MTUKadN91fcmuhxGWYVe2k
The wire contract's servers.url is the browser BFF, which rejects a device token; the worker itself has no route or custom domain. Claude-Session: https://claude.ai/code/session_01MTUKadN91fcmuhxGWYVe2k
check-support-repo-coupling.sh built its regex from an empty peer list, degenerating to a pattern matching nothing. The engine-boundary script ran in CI but not on pre-push. Both AST tests carried a gateway->credentials exception that no production file uses. Claude-Session: https://claude.ai/code/session_01MTUKadN91fcmuhxGWYVe2k
Also replaces GrayCodeAI/starling test fixtures with the repo's current name, and fixes an 'execution swift' typo left by an earlier substring rename in the generated GitNexus tables. Claude-Session: https://claude.ai/code/session_01MTUKadN91fcmuhxGWYVe2k
- eval list --json: project BenchmarkTask (func fields) to a JSON-safe struct - stream: use a single RawMessages() snapshot (fixes len()+copy reallocation race) - crash_unix: drop unreachable nil-return branch from raiseSignal - tool: replace deprecated strings.Title with x/text cases.Title - daemon: replace no-arg fmt.Sprintf with string literals - fuzzyfind: replace deprecated filepath.HasPrefix with strings.HasPrefix - memory: thread context.Context through MemoryRecaller.Remember so background remember goroutines honor their timeout (fixes goroutine leak from discarded rCtx) - contracts/types: remove deprecated fail-open ParseSeverity (zero callers)
Wire the previously-unused ProgressTracker into real command flows via a new CLIProgress helper: - cmd/progress_cli.go: TTY-aware progress renderer. On a terminal it repaints the active step in place with a braille spinner, theme-colored progress bar, and live N/M counter; piped/CI output is one clean static line per step with no ANSI. Completion prints a themed summary with the final bar (errorCoral when any step failed). Glyphs come from internal/ui/icons; block glyphs stay in the audit-permitted U+2500-U+25FF range. - cmd/review_run.go: progress over Building model / Reviewing code / Saving results, silent in background/hook mode. - cmd/audit.go: per-session progress, gated to TTY + text output so --json stays pure and piped output isn't spammed. - cmd/progress_cli_test.go: non-TTY, TTY, fail-step, and multi-step regression tests (the multi-step test covers a fresh-spinner-per-step fix for BrailleSpinner's one-shot Start/Stop panic).
Wire CLIProgress into the harness command over Evaluating workspace / Writing markdown / Writing HTML / Writing JSON. Reports are written to files (not stdout), so progress never corrupts structured output; piped runs get clean static lines, TTY runs get in-place animation.
Run project test/verify commands can be slow with no feedback until each finishes. Show a TTY-only animated indicator while they execute, then clear it before printing the structured [OK]/[FAIL]/[SKIP] results, so piped and structured output stay untouched.
Append a live ETA to the animated line once the tracker has completed steps to extrapolate from (ProgressTracker.EstimateRemaining). Hidden until meaningful, so the first step shows no spurious ETA.
Extract the per-session progress gate into auditProgressEnabled(format, tty) and cover it: JSON output must stay pure on any terminal, and piped text must not be spammed with per-session lines.
Colorize the report title (brand gold), section headers (infoSky), and severity column (semantic colors: high/critical errorCoral, medium warnAmber, info/low infoSky) on a TTY only. Piped output stays plain. Severity is padded to the column width before colorizing so zero-width ANSI escapes don't break the fixed-width alignment.
Show a TTY-only animated indicator around the slow full agent loop. It clears before the JSON report prints, so piped and structured output stay pure.
Wire the canonical ShouldColor()/IsQuiet() gates into CLIProgress and the audit report so the new animated/theme output respects the same controls as the rest of the CLI. --quiet now fully suppresses spinners, progress lines, and decoration (the documented contract) and produces plain output; NO_COLOR strips color while keeping the TTY animation; FORCE_COLOR colors piped output. Make --quiet a persistent root flag so it is usable on subcommands (graycode audit --quiet, verify --quiet, eval loop --quiet) instead of only the interactive root. Previously subcommands rejected it with 'unknown flag'. Add tests for quiet suppression, NO_COLOR, and FORCE_COLOR.
Insert a 'Repairing harness' progress step around FixWorkspaceHarness (and the post-fix re-evaluation) when --fix is used. Report-write steps reindex dynamically so the animation stays correct in both modes.
Add an optional Progress callback to the eval Runner, invoked before each task with its index, total, and ID. runEval wires it to a CLIProgress with one step per benchmark task, closing the previous step and opening the next. Quiet mode suppresses the animation. Backward-compatible: no existing Runner construction breaks (keyed literals), and the callback is nil by default.
Colorize the review summary to match the audit report: green check for a clean review, coral alert with semantic severity colors for findings. Honors ShouldColor() so --quiet/NO_COLOR/FORCE_COLOR behave consistently.
Theme the summary labels (muted) and the total-hits count (green when clean, coral when findings exist); the empty-detectors success line is now green. Consistent with the themed title and severity columns.
Gold completion banner; semantic status color (green EXCELLENT/GOOD, amber NEEDS_IMPROVEMENT, coral POOR); labels in textPrimary. Honors ShouldColor().
Colorize the [OK]/[FAIL]/[SKIP] markers (green/coral/muted) and the 'verification passed' line. Markers are padded to a fixed width before colorizing so ANSI escapes don't break column alignment. Plain when piped via ShouldColor().
Gold title, muted header/separator, violet cost column (pad-then-colorize to preserve alignment), textPrimary total label. Honors ShouldColor() so piped output stays plain.
Gold title, sky section headers, muted labels/headers, violet cost figures, teal top-tool bars. Consistent with the audit report. Honors ShouldColor().
Green check / coral close / amber alert statuses, textPrimary names, and status-colored messages. Honors ShouldColor() so piped output stays plain.
Gold title, muted labels, textPrimary values. Honors ShouldColor() so piped/JSON output stays plain.
Green OK marker, textPrimary count, muted path. Honors ShouldColor().
Muted label, status-colored counts (open sky, passed green, fixed teal, failed coral), and severity-colored open-review lines. Honors ShouldColor().
Muted header, state-colored STATE column (active green, failed coral, disabled dim, discovered/loaded sky). Honors ShouldColor().
Green running, muted not-running, amber unknown/stale; muted labels with textPrimary values. JSON output stays pure.
models refresh (slow 60s network discover) and models list --live (live provider fetch) now show a CLIProgress step. JSON/raw list output stays pure. Honors --quiet/NO_COLOR.
The first-run setup wizard and welcome banner emitted hardcoded ANSI escapes unconditionally, breaking the CLI's non-TTY purity (colored output even under NO_COLOR). Gate the color codes on theme.ColorEnabled() and use the theme's brand ANSI for the banner, so scripted or NO_COLOR environments get plain text. Update TestColorConstants to assert the gating behavior.
graycode mission's per-feature output was themed but the final Mission summary line stayed plain. Colorize it textPrimary to match the rest of the command's visual identity.
graycode sandbox status printed a plain multi-line report while every other CLI status report was themed. Colorize the header, per-change type tags, and stats line using the semantic theme colors, honoring NO_COLOR/FORCE_COLOR/TTY via theme.Tint. The Summary method is CLI-only.
The 'Installed <shell> completion to <path>' status line was the last plain confirmation in the CLI. Colorize 'Installed' in doneGreen and the target path in textPrimary, honoring ShouldColor() via auditTint.
The 'System prompt fragment that would be injected:' heading and its separator were plain. Colorize the heading in textPrimary and the separator in textMuted via auditTint; the injected fragment itself stays plain (it is data).
The review list row printed the status text and findings bracket in plain text while the status glyph was already colored. Colorize the status via reviewStatusColor and the [maxSeverity] bracket via severityStyle, keeping the row layout intact.
The trending skill list printed plain numeric prefixes. Colorize the index in textMuted via auditTint; the shared FormatSkillEntry body stays plain.
The findings list printed plain indices and file:line locations. Colorize the index in textMuted and the file path in textPrimary via auditTint, matching the themed severity bracket and message lines.
The modern help template rendered command descriptions in plain text while headers were gold and names textPrimary. Colorize descriptions in textMuted via a new gcDesc template func for clearer visual hierarchy. Descriptions are the last column, so zero-width ANSI cannot break the padded name alignment; under NO_COLOR auditTint keeps them plain, so the golden help files stay unchanged.
After an exec run prints its response, emit a muted token/turn/duration/ model summary to stderr so stdout stays byte-clean for piping and the model output remains the sole data. Gated by --quiet; color honors ShouldColor() via auditTint.
The issue command ran 'gh issue create' with context.Background() and no deadline, so a stalled GitHub call could hang the CLI indefinitely. Wrap it in a 60s context timeout and report a clear deadline-exceeded error.
review fix iterates open reviews and runs a multi-turn graycode exec for each. It printed only the completion status after each exec, so with --all the user could not tell which review was being worked on. Print a themed 'Fixing review #N (sha)...' line (gold bolt + textPrimary) before each exec run.
review analyze ran a single kestrel model call (up to the 3-minute analyze timeout) behind a static 'Analyzing...' line. Replace it with a CLIProgress animation (rainbow spinner + themed bar + ETA) so the wait has live feedback, matching review run. Gated by --quiet; findings output stays clean after the step completes.
The mission command ran up to 30 minutes of parallel LLM workers behind a static 'Executing with N parallel workers...' line with no live feedback. Wrap the run in a single-step CLIProgress animation (rainbow spinner + themed bar) showing the feature/worker count. Gated by --quiet; the per-feature results still print cleanly after the step completes.
The best-of-N fanout loop printed each attempt header to stderr in plain text. Theme them with the info-sky accent so each attempt reads as a distinct phase, matching the themed exec usage summary. Stderr-only, so the model output on stdout stays byte-clean.
The best-of-N comparison report printed each attempt's ok/failed status in plain text. Colorize the status (green ok / coral failed, with the error appended in coral) and the report header in the info-sky accent, matching the themed attempt headers. Stderr-only; stdout stays byte-clean.
The exec command printed error/hint/warning diagnostics to stderr in plain text. Colorize them with semantic accents — errors in coral, hints in muted, and warnings (untrusted GitHub autonomy cap, session-persist failure) in amber — matching the themed usage summary and fanout headers. Stderr-only; the model output on stdout stays byte-clean.
Theme the one-off stderr diagnostics in ai-comments (directive dispatch and token-strip failures in coral) and chat (ignored --session-id notice in muted, plugin load failure warning in amber). Consistent with the themed exec diagnostics; stderr-only.
The interactive chat REPL printed errors to stderr in plain text. Colorize them in coral. The REPL's streamed tool output stays plain (data).
Theme the daemon telemetry/file-logging fallback warnings and the eval results-save warning in amber. Consistent with the themed exec and chat diagnostics; stderr-only.
config set now reads the current value before writing and, when it changes, prints a modern old → new transition (key: old → new (updated)) instead of the bare 'updated key'. Falls back to the plain confirmation when there is no prior value or the value is unchanged. Settable keys are non-secret (API keys error out before reaching here), so no secret is exposed. Honors NO_COLOR via auditTint.
Extract the old → new transition rendering into printConfigSetResult and use it for the config set, config provider, and config model paths so all three show the same modern transition (key: old → new (updated)) with the plain fallback when there is no prior value.
config get printed a blank line when a valid key had no value. Print '(unset)' in muted instead, so an empty result is distinguishable from a missing key (which still errors).
verify now reports how long the check run took (verification passed in Xs), which is genuinely useful in non-TTY mode where no animation shows the elapsed time. The duration is muted so the done-green confirmation stays the visual anchor.
- Apply gofumpt to cmd/exec.go and two internal/intelligence/memory files (formatting-only) to satisfy the CI format check. - Remove docs/plans/2026-09-05-graycode-eco-integrity.md from the branch: it is a working planning note (not a CLI deliverable) whose malformed code fences and hard tabs fail the repo's markdownlint gate. Kept locally as untracked.
- progress_cli.go: explicitly discard fmt.Fprintf/Fprintln return values (errcheck) in the spinner frame callback and writeLine. - developer_path.go: omit redundant color.Color type annotation (ST1023); theme.ReportWarn is already color.Color and all switch assignments share that type.
Use := instead of var for the first declaration of statusColor so the file passes the CI gofumpt gate.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Modernizes and hardens the graycode CLI across four dimensions:
Theming
auditTinthelper + self-containedinternal/themefor non-cmd packages.NO_COLOR/FORCE_COLOR/--quiet; tables/JSON/markdown/streams stay byte-clean.Animation
CLIProgress(themed progress bar + ETA) wired into every slow flow: review run/analyze, audit, harness, verify, eval, models, doctor, preflight, cloud login, context--output, mission.Non-TTY purity
--quiet; onboarding honorsNO_COLOR;doctor --jsonnow emits real JSON; pad-then-colorize alignment.Robustness
gh issue create60s timeout; BrailleSpinner one-shot panic fix.Modern UX
config set/provider/modelold→new transitions;config get(unset);verifyelapsed time.All tests pass (
go test ./...), build/vet/gofmt clean.