Skip to content

v0.2.1 delight pass: color hierarchy, warmer empty state, home-relative paths - #13

Merged
AnobleSCM merged 3 commits into
mainfrom
delight-pass-0.2.1
Aug 3, 2026
Merged

AnobleSCM merged 3 commits into
mainfrom
delight-pass-0.2.1

Conversation

@AnobleSCM

Copy link
Copy Markdown
Owner

Summary

Strictly-scoped presentation polish on the local stack report, releasing as v0.2.1. Exactly three things, per spec:

  1. Terminal color hierarchy (TTY only). Type labels (mcp/plugin/skill/subagent) get a single cyan accent; per-type counts are bold. Header/footer unchanged from today.
  2. Empty state. Warmer, honest headline (No AI tooling detected on this machine yet. — reused verbatim from the existing --markdown empty-state sentence for consistency, rather than inventing new wording). Looked in: paths now print home-relative (~/.claude/skills); paths outside $HOME stay absolute.
  3. Release prep. 0.2.0 → 0.2.1 in package.json and CLI_VERSION, plus a CHANGELOG entry.

Do not merge — draft only, per instructions. Not published to npm.

Taste call: one shared accent, not one per type

Went with a single cyan accent for all four type labels rather than a distinct hue per type. Reasoning:

  • Four hues across up to 4 rows per client block starts to read as a legend, not a restrained CLI (the explicit "not rainbow soup" target).
  • cyan is already the established accent in this codebase (used for the verification URI in the sync device-flow prompt) — extending it keeps one stable accent-to-meaning mapping instead of inventing a second convention.
  • The type words are already text-distinguished from each other; color's job here is separating "label" from "count" and "name list," not distinguishing the four types from one another.
  • Matches restrained modern-CLI conventions (pnpm/vite/biome: one accent + bold + dim, not a hue-per-category legend).

Invariant evidence

All diffs below are v0.2.0 (origin/main, built fresh) vs this branch, run against byte-identical fixture input (same fixture $HOME + cwd, both dist builds invoked directly).

(a) Piped (non-TTY) main-report text — byte-identical except the empty-state copy change

$ diff old.default.txt new.default.txt   # rich case, 7-tool fixture
IDENTICAL

$ diff old.empty.txt new.empty.txt       # empty case — the deliberate exception
1c1
< ✓ No AI tooling detected.
---
> ✓ No AI tooling detected on this machine yet.
9,16c9,16
<   - /…/fixture-home-empty/.claude.json          (8 lines, all absolute)
---
>   - ~/.claude.json                                (same 8 lines, home-relative)

Also verified on this machine's real $HOME (~121 real tools) — piped rich-case output is byte-identical, confirmed with diff (see "Sanity runs" below).

(b) --json / --markdown — byte-identical except the cli_version field

$ diff old.json.txt new.json.txt
2c2
<   "cli_version": "0.2.0",
---
>   "cli_version": "0.2.1",

$ diff old.markdown.txt new.markdown.txt
IDENTICAL   # markdown carries no version field, so no exception at all here

$ diff old.empty.json.txt new.empty.json.txt   # empty case too
2c2
<   "cli_version": "0.2.0",
---
>   "cli_version": "0.2.1"
# paths_checked stays absolute — the display-only home-relativization never
# touches --json, confirmed by a dedicated test.

stderr streams (truncation warnings) are also identical across all modes — confirmed empty in this fixture (no truncation).

(c) README demo/example verbatim-match invariant
assets/devcat-report.svg is untouched (git diff origin/main -- assets/devcat-report.svg is empty). I manually line-matched its <tspan> text content against the README's "same output as text" block — still byte-identical, since color is TTY-only ANSI and never touches text content (this is now also a standing test: "colorizing never changes the underlying text — stripped output matches the plain render").

One thing to flag: the SVG's fill colors (#c9d1d9 flat gray body text) reflect the pre-delight-pass monochrome scheme. A real colorized TTY run now differs visually from the static demo (cyan labels, bold counts). Regenerating the SVG is conditioned in the brief on visible text changing, which it hasn't — so I left the asset alone rather than reverse-engineer its original generation pipeline. Flagging so it's a deliberate call, not an oversight, in case a follow-up wants to regenerate it.

(d) README sentences
Only one edit: the illustrative "cli_version": "0.2.0" literal inside the --json example block → "0.2.1", since real --json output will say 0.2.1 the moment this ships. No other README sentence references anything this pass touched (grepped for the old empty-state copy — it isn't quoted anywhere in the README).

Explicitly not touched, flagged rather than fixed: the README's "Profile sync — paused while devcat.dev is rebuilt" framing is drifting stale now that the static landing page is live (per the knowledge-plane rider expecting this to "ride along with 0.2.1"), but rewording it touches the profile-sync/devcat.dev framing the freeze record governs and isn't one of the three named items — left for a separate, deliberate pass rather than folded in here.

(e) No new network paths; skills/subagents-never-in-sync-payload guarantee untouched
Nothing under src/api/, src/auth/, src/commands/sync.ts, or src/manifest/index.ts (home of SyncableToolEntry/syncableTools) appears in the diff — confirmed via git diff origin/main --stat. Full file list touched: CHANGELOG.md, README.md, package.json, src/lib/isHeadless.ts, src/ui/report.ts, src/version.ts, plus 6 test files.

Gates (all green)

npm test    → 246/246 passed (238 pre-existing + 8 new/updated)
npm run lint → clean
npm run build → clean
npm pack --dry-run → 67 files, identical file LIST to a fresh v0.2.0 pack (diffed)

New tests specifically added for this pass: TTY-color vs non-TTY plain (report.tty-color.test.ts), NO_COLOR gating including the empty-string edge case (colors.test.ts, isHeadless.test.ts), and empty-state copy + home-relative path display (report.test.ts).

Sanity runs on this machine

Rich case (real $HOME, 121 tools) — before/after diff is byte-identical:

✓ Your AI-coding stack — 121 tools

Claude Code · 111 tools
    4 mcp      atelier-board, codegraph, mcphub-gateway, workshop
   44 plugin   accessibility-compliance, agent-orchestration, clangd-lsp, …
   56 skill    ask-fable, ask-matt, clarify, codebase-design, …
    7 subagent clean-code-reviewer, code-reviewer, debugger, …

Codex · 9 tools
    3 mcp      computer-use, node_repl, openaiDeveloperDocs
    6 skill    claude-workflow-compat, design-taste-frontend, humanizer, …

Cursor · 1 tool
    1 mcp      posthog

121 tools in Claude Code, Codex, and Cursor · 13 locations checked

(identical before and after — piped output is unaffected by the color change, as required)

Real colorized TTY output, captured via script(1) against a real pty (cat -v rendering so the escape codes are visible as text):

^[[1mClaude Code^[[22m ^[[2m· 111 tools^[[22m
  ^[[1m  4^[[22m ^[[36mmcp      ^[[39matelier-board, codegraph, mcphub-gateway, workshop

— bold count (^[[1m...^[[22m), cyan type label (^[[36m...^[[39m), plain name list. Matches the design exactly.

Empty case (HOME → empty temp dir) — before/after:

BEFORE: ✓ No AI tooling detected.
AFTER:  ✓ No AI tooling detected on this machine yet.

BEFORE:   - /Users/andrewnoble/.claude.json
AFTER:    - ~/.claude.json
(cwd-relative project paths outside $HOME — e.g. …/real-cwd/.mcp.json — stay absolute in both)

Judgment calls

  1. One shared cyan accent, not one hue per type — see "Taste call" above.
  2. Reused the existing --markdown empty-state sentence verbatim for the terminal empty state, rather than inventing new copy — it was already the warmer, "yet"-qualified phrasing the original author chose for that sibling code path; consistency over a third distinct phrasing.
  3. Fixed NO_COLOR='' (empty value) not counting as "set." !!process.env.NO_COLOR treated an empty-string value as unset, contradicting the no-color.org standard this README already cites ("disable color when [NO_COLOR is] present, regardless of its value"). Judged in-scope because the brief explicitly pre-authorizes NO_COLOR correctness work ("presentation-correctness and in scope") and the fix sits directly in the TTY-detection module the brief names. Updated the one existing test that had locked in the old (incorrect) behavior.
  4. Did not touch the stale "paused while devcat.dev is rebuilt" copy — see invariant (d) above. Flagged, not fixed.
  5. Did not regenerate assets/devcat-report.svg — see invariant (c) above. Flagged, not fixed.
  6. Restored an incidental package-lock.json diff (npm-client peer-metadata normalization noise from npm install, zero actual dependency changes) rather than committing it — kept the diff surgical.
  7. src/ui/render.ts (sync/device-flow renderers: renderSuccessSummary, renderEmptyManifest, renderUserCodePrompt) was left untouched — the task's CONTEXT section describes only the default report command's current output, and render.ts serves the separate, currently-paused sync feature.

Housekeeping note (unrelated, no action taken)

Noticed a stale, already-merged worktree (.worktrees/polly/readme-truth-pass, commit 8357786, one commit behind the tip of the README-polish PR that's already on main) sitting in the local checkout this session started from. Didn't touch it — flagging only in case it's worth pruning.

…-relative paths

Presentation-only polish on the local stack report, scoped to exactly three
things: a restrained cyan/bold color hierarchy for type labels and counts
(TTY-only, NO_COLOR-aware), warmer empty-state copy with home-relative
"Looked in:" paths, and the 0.2.0 -> 0.2.1 release bump. --json/--markdown
output is byte-identical to v0.2.0 apart from the cli_version field.

Also fixes NO_COLOR='' (empty value) not being treated as "set" per the
no-color.org spec this README already claims to follow.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

AnobleSCM and others added 2 commits August 3, 2026 10:16
package.json and src/version.ts were bumped to 0.2.1 but package-lock.json's
top-level "version" and packages[""].version were left at 0.2.0. Updated both
fields directly — `npm install --package-lock-only` on this npm version
(10.9.8) also strips unrelated "peer": true flags from 8 packages, so hand
editing keeps the diff to just the version bump. Extends the version-parity
test to assert both lockfile fields track package.json, so a partial bump
fails loudly instead of shipping quietly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Two issues in the v0.2.1 delight pass's home-relative path work, both in
toHomeRelative (src/ui/report.ts) and its tests:

- The new home-relative tests in test/unit/ui/report.test.ts hardcoded POSIX
  fixtures ('/Users/testuser', '~/.claude/skills'). toHomeRelative's
  separator-boundary check uses native path.sep, so on win32 (sep is '\')
  those fixtures silently failed to match — both windows-latest CI lanes
  (Node 20 + 22) were red while all four Unix lanes passed. Fixtures now
  build from node:path (sep/join) so every lane exercises its own real
  native-separator behavior.
- toHomeRelative's home-prefix match is now a deliberate policy instead of an
  accidental one: case-insensitive on win32/darwin (both default to
  case-insensitive filesystems) and case-sensitive elsewhere. The match folds
  case; the returned string never does — only the matched home-prefix span is
  replaced by '~', so the rest of the path keeps its original casing. The
  sibling-directory boundary guard (/Users/name2 must not become ~2) holds in
  both modes. caseSensitivity is exported as an explicit parameter (default
  derived from process.platform) so both modes run deterministically on every
  platform in CI, not just whatever the host happens to do.

Neither change touches the non-TTY/--json/--markdown byte-identical-to-0.2.0
invariant or its stripAnsi(colored) === plain test.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@AnobleSCM
AnobleSCM marked this pull request as ready for review August 3, 2026 17:22
@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@AnobleSCM
AnobleSCM merged commit 462dc2b into main Aug 3, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant