fix(cli): align search & verify table output (#21)#22
Conversation
`skillrig search` printed name/version/description with single-space separators and no padding, so columns were ragged and unreadable (#21). Render both the search list and the verify failure list through a shared text/tabwriter helper (stdlib, no new dependency) so columns align across rows. Also make truncateDesc rune-safe: byte-slicing could split a multibyte rune into invalid UTF-8, and rune width matches how tabwriter measures cell width. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Keep the intentional CLI output glyphs (the → next-step hint, ✓/✗ verify status, the —/·/… separators) but guard against ACCIDENTAL new non-ASCII runes (copy-pasted smart quotes, non-breaking spaces, homoglyphs) that render unpredictably and are nearly invisible in review. golangci-lint can't catch these: asciicheck only inspects identifiers, bidichk only catches dangerous invisible/bidi runes. - internal/sourceguard: a test-only package that scans every .go file and fails on any non-ASCII rune outside a documented allowlist, reporting file:line:col. Runs via 'go test ./...', so 'make check' and CI enforce it for free — no workflow edit. - .claude/settings.json: a PostToolUse hook (Edit|Write|MultiEdit) that runs the guard after .go edits and blocks with exit 2 on a violation, feeding the offending location back — the agent-loop guard. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Review Summary by Qodo(Agentic_describe updated until commit 0d66d94)Fix table alignment and add non-ASCII source guard
WalkthroughsDescription• Fix ragged table output in search and verify commands using stdlib text/tabwriter • Make truncateDesc rune-safe to prevent UTF-8 corruption from multibyte character splitting • Add internal/sourceguard test package to guard against accidental non-ASCII runes in source • Add Claude agent-loop hook in .claude/settings.json to enforce ASCII guard on .go edits Diagramflowchart LR
A["search/verify output"] -->|"ragged columns"| B["renderSearchResult<br/>renderVerifyFailure"]
B -->|"new: writeAlignedColumns"| C["text/tabwriter<br/>elastic tabstops"]
C -->|"aligned output"| D["fixed-width columns"]
E["truncateDesc<br/>byte-slicing"] -->|"UTF-8 corruption risk"| F["rune-safe conversion"]
F -->|"rune counting"| G["matches tabwriter width"]
H[".go source edits"] -->|"PostToolUse hook"| I["sourceguard test"]
I -->|"sanctioned allowlist"| J["intentional glyphs only"]
File Changes1. internal/cli/output.go
|
Code Review by Qodo
Context used✅ Tickets:
🎫 Bug: Tables are unreadable in CLI✅ Compliance rules (platform):
152 rules 1. tabwriter.NewWriter args not multiline
|
🤖 I have created a release *beep* *boop* --- ## [1.0.1](v1.0.0...v1.0.1) (2026-06-02) ### Bug Fixes * add MIT license ([#14](#14)) ([346bce0](346bce0)) * **cli:** align search & verify table output ([#21](#21)) ([#22](#22)) ([b54d751](b54d751)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: skillrig-release-bot[bot] <289564490+skillrig-release-bot[bot]@users.noreply.github.com>
Summary
Fixes #21 —
skillrig searchprintedname version — descriptionwith single-space separators and no column padding, so every row's columns started at a different offset and the list was unreadable. This renders the search list (and the verify failure list, which had the same defect) through a sharedtext/tabwriterhelper — stdlib elastic tabstops, no new dependency (confirmed none of go-toml/cobra/yaml provide table formatting, and Cobra has no fixed-width helper).Changes
internal/cli/output.gowriteAlignedColumnshelper (one shared tabwriter renderer for bothsearchand theverifyfailure list — no duplicated setup).truncateDescis now rune-safe: the olds[:n]byte-slice could split a multibyte rune into invalid UTF-8, and rune width matches how tabwriter measures cell width.→ ✓ ✗ — · …but guard against accidental new non-ASCII — smart quotes, NBSP, homoglyphs — which golangci-lint can't catch:asciicheckis identifiers-only,bidichkis dangerous-invisibles-only):internal/sourceguard/— a test-only package that scans every.gofile and fails on any non-ASCII rune outside a documented allowlist (file:line:col+ codepoint). Runs viago test ./..., somake checkand CI enforce it for free — no workflow edit..claude/settings.json— aPostToolUsehook (Edit|Write|MultiEdit) that runs the guard after.goedits and blocks (exit 2) on a violation, feeding the location back. Validated end-to-end (caught an injectedU+2019).Before / after (
skillrig search)Testing
make check— green: gofmt clean,go vetclean, golangci-lint 0 issues, all tests.make test-integration—TestQuickstart_*(builds & execs the real binary) pass; the search/verify assertions check output shape (bounded line count, name/footer presence), which the tabwriter change preserves.internal/sourceguardguard proven to catch injected smart quotes; thePostToolUsehook proven to fire and block.Closes #21.