Skip to content

fix(cli): unicode-safe rendering across TUI and commands (3.2.4)#53

Merged
montfort merged 1 commit intomainfrom
chore/bump-cli-3.2.4
Apr 24, 2026
Merged

fix(cli): unicode-safe rendering across TUI and commands (3.2.4)#53
montfort merged 1 commit intomainfrom
chore/bump-cli-3.2.4

Conversation

@montfort
Copy link
Copy Markdown
Contributor

Summary

Follow-up to #52. That PR fixed a UTF-8 panic in wrap_cell_text(); this one removes the byte-vs-visual-column confusion that was scattered across the rest of the CLI — the same anti-pattern that caused the original crash.

All layout sites now route through three new helpers in utils.rs:

  • visual_width(&str) -> usize
  • truncate_visual(&str, max_cols) -> String
  • pad_right_visual(&str, cols) -> String

TUI fixes

  • Scrollbar leak: explore's scrollbar no longer shows the document text through its track. The paragraph renders in a reserved body column and the scrollbar owns the rightmost column. ScrollbarState::viewport_content_length is now set, so the thumb has the correct proportional size.
  • Line-count estimate: doc_viewer measures line width with UnicodeWidthStr::width, not bytes — scroll position is accurate for CJK/emoji content.
  • Navigation tree: date extraction (2026-04-1204-12) is char-safe (no byte slicing on arbitrary created strings); title budget computed in visual columns.
  • Metadata panel: related-link truncation uses truncate_visual.
  • Status bar: right-aligned padding uses visual width — projects in directories with non-ASCII names now stay aligned.
  • Markdown code blocks: alignment fixed for blocks containing CJK / emoji / accented characters.

Command fixes

  • validate: NAMING-001, META-004, and the auto-fix path no longer byte-slice the filename date. Non-ASCII where ASCII was expected produces a clean validation error instead of risking a panic.
  • analyze: path/function truncation uses visual width with a leading ellipsis; padding is correct under any input.
  • status: the Project, Structure, and Documentation tables compute column widths and padding in visual columns.
  • new: slug truncation and sequence-number scan use chars().take(N) instead of byte slices.

Dependency change

  • unicode-width moved from optional (feature tui) to a direct always-compiled dep. It was already transitive via ratatui, so no new compile cost; promoting it lets non-TUI commands measure visually too.

Test plan

  • cargo test — 76 library tests passing (48 pre-existing + 16 markdown regression + 12 new utils::tests::*).
  • cargo build --no-default-features — compiles cleanly.
  • cargo build --all-features — compiles cleanly.
  • cargo build --release — compiles cleanly; devtrail about reports cli-3.2.4.
  • cargo clippy --all-features — no new warnings (the 4 remaining are pre-existing in audit_engine.rs, app.rs, index.rs, markdown.rs:flush_spans).
  • Manual: ./target/release/devtrail status table borders align correctly.
  • Manual: open a doc with CJK content via explore and check nav tree / metadata / code block alignment.
  • Manual: confirm the scrollbar no longer shows document text through the track.

🤖 Generated with Claude Code

Follow-up to 3.2.3. The UTF-8 panic fix in `wrap_cell_text()` exposed
the same byte-vs-visual-column confusion scattered across the rest of
the CLI. This patch removes the class of bugs, not just the specific
instance, by introducing shared visual-width helpers and routing every
layout site through them.

TUI:
- `explore` scrollbar no longer leaks the document text through the
  track: the paragraph now renders in a reserved body column and the
  scrollbar gets its own. `ScrollbarState::viewport_content_length` is
  set so the thumb has the correct proportional size.
- `doc_viewer` measures line width with `UnicodeWidthStr::width` to
  estimate wrapped row count (previously summed `.len()` in bytes).
- `nav_tree` compact-date extraction is now char-safe (no byte slicing
  on the `created` field), and `title_budget` is computed in visual
  columns so CJK titles truncate correctly.
- `metadata_panel` uses a shared `truncate_visual` for related links.
- `status_bar` right-aligned padding uses visual width, so projects
  in directories with non-ASCII names stay aligned.
- `markdown.rs` code blocks pad by visual columns; fixed alignment
  when a block contains CJK / emoji / accented characters.

Commands:
- `validate` filename-date parsing (`NAMING-001`, `META-004`, auto-fix
  path) no longer slices by bytes; non-ASCII in the date component
  fails cleanly with a validation error instead of risking a panic.
- `analyze` path/function truncation uses visual width with a leading
  ellipsis; padding in the report table is correct under any input.
- `status` project, structure, and documentation tables all compute
  column widths and padding in visual columns.
- `new` slug truncation and sequence-number scan switched from byte
  slices to `chars().take(N)`.

Shared helpers in `utils.rs`:
- `visual_width(&str) -> usize`
- `truncate_visual(&str, max_cols) -> String`
- `pad_right_visual(&str, cols) -> String`
- 12 unit tests covering ASCII, accents, CJK, em-dash, emoji, and
  zero-width edge cases.

Dependency change: `unicode-width` is now a direct always-compiled dep
(previously optional under feature `tui`). It was already transitive
via `ratatui`; promoting it lets non-TUI commands measure visually.

Bump CLI to 3.2.4.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@montfort montfort merged commit 1eda03c into main Apr 24, 2026
1 check passed
montfort added a commit that referenced this pull request May 7, 2026
…#112)

Documents the follow-ups backlog convention contributed by the Sentinel
adopter via issue #111. Empirically validated in StrangeDaysTech/sentinel
CHARTER-12 (47 AILOGs across CHARTER-08 → CHARTER-11). Adopters reaching
~20+ AILOGs benefit from a central registry + per-AILOG drift detection
script + agent integration block.

This release is docs only — no CLI changes, no schema changes, no audit
flow changes. Cristalization as a `devtrail followups` subcommand is
deferred until a second adopter validates the pattern.

Adds:
- dist/.devtrail/00-governance/FOLLOW-UPS-BACKLOG-PATTERN.md (EN, ES, zh-CN)
  documenting the registry shape, 5 buckets, per-entry schema, drift
  detection (3 modes), agent integration, adoption walkthrough, reference
  implementation (Sentinel CHARTER-12 PRs #53/#54), and v0 open questions.
- "Patterns" sections in AGENT-RULES.md and QUICK-REFERENCE.md (3 langs)
  pointing to the new document.

Bumps:
- dist/dist-manifest.yml to 4.10.0.
- Footer versions and adopter doc references from v4.9.0 to v4.10.0
  (skill version markers preserved as historical "since" annotations).

Closes the upstream side of issue #111 (option A: docs-only adoption).

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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