Skip to content

feat(rotatui): double-ruled gum UI, failure-resilient rituals, CI lint - #320

Merged
drawmeanelephant merged 4 commits into
mainfrom
feat/rotatui-gum-leverage
Sep 10, 2026
Merged

drawmeanelephant merged 4 commits into
mainfrom
feat/rotatui-gum-leverage

Conversation

@drawmeanelephant

@drawmeanelephant drawmeanelephant commented Sep 10, 2026

Copy link
Copy Markdown
Owner

Summary

Follow-up to the Rotatui charm-stack work (#319). Fixes a latent bug where any failing ritual killed the whole TUI, unifies the visual language on a double-ruled border, and leans harder on the Gum feature set.

Bug fix — failed rituals aborted the TUI

rotatui.sh sets set -euo pipefail, but every spooky_spin/run_with_spin call site captured $? on the next line. Under set -e a non-zero return aborts before that line, so the ❌ RITUAL FAILED panel / log / pager never rendered and the process exited. It only ever looked fine because success paths never tripped it.

  • Guard every capture site: spooky_spin ... || code=$?
  • run_with_spin now stores status in RITUAL_STATUS and returns 0 (it already reports pass/fail)
  • Wrap the menu dispatch in case ... esac || true so a stray failure returns to the menu

UI — consistent double-ruled framing

  • New panel() / section_header() helpers; every panel, table, and header now shares one double-ruled border (no rounded borders remain)
  • Main menu normalized to a consistent emoji gutter + fixed-width label column so descriptions line up (fixes the ⚙️ Initialize Env / 🏷️ Version Bump drift)

More Gum

  • gum spin replaces the hand-rolled braille spinner; spinner varies per ritual, overridable with RK_SPINNER
  • gum log for the Charm stack notice and inline diagnostics
  • gum format --type markdown as the Tomb Peek fallback when glow is absent
  • Tomb Peek style now matches the tomb's template: frontmatter (or default_template): light→light, pride/kawaii/flash/daisy→pink, spooky/necropolis/dark→dracula
  • gum choose --no-limit for multi-target Book Binders
  • gum filter --select-if-one --fuzzy for template selection
  • themed confirm --affirmative/--negative labels throughout
  • gum table --columns with a double border
  • gum join --horizontal for two-up status cards, and gum format --type template for the colored freshness line
  • Status script-health table is now interactive (gum table --return-column) and opens the selected script's doc page (or source) in gum pager
  • add init and help rituals to the menu; Showcase derives its theme count

CI

  • Add shellcheck rotatui.sh to the lint step (it wasn't covered before)

Validation

  • bash -n rotatui.sh + shellcheck rotatui.sh clean (one targeted SC2016 disable for the intentional inner-bash expansion)
  • bash rotkeeper.sh status
  • bash rotkeeper.sh test — 3/3 layouts + contract/DIP/regression suites passed
  • pty smoke runs: menu renders and exits cleanly; the System Status screen renders the joined cards + colored freshness line; gum table --return-column returns the selected script under a pty; a ritual runs through gum spin + panel + return to menu
  • scripted check that all 21 menu options still match a dispatcher case pattern
  • Verified all flags used are available in Gum 0.x; v2.0.0 has no CLI/UX changes

Notes

  • Emoji cell width is terminal-dependent; if a specific glyph renders 1-cell the row can drift by one. Padding itself is now uniform.
  • gum join is now used; no Gum subcommands remain unused.

Bug fix: rotatui sets `set -euo pipefail`, so any ritual that failed
aborted the whole TUI before its own "RITUAL FAILED" panel could render.
Guard every capture site (`spooky_spin ... || code=$?`), have
run_with_spin report via RITUAL_STATUS and return 0, and wrap the menu
case in `esac || true` so a stray failure returns to the menu.

UI: unify every panel/table/section on one double-ruled border via
panel()/section_header() helpers, and normalize the main menu to a
consistent emoji gutter + fixed-width label column so descriptions align.

Leverage more of Gum:
- gum spin replaces the hand-rolled braille spinner
- gum log for the Charm stack notice and inline diagnostics
- gum format --type markdown as the Tomb Peek fallback when glow is absent
- gum choose --no-limit for multi-target Book Binders
- gum filter --select-if-one --fuzzy for template selection
- themed confirm affirmative/negative labels throughout
- gum table --columns with a double border
- add init and help rituals to the menu; derive Showcase theme count

Also add rotatui.sh to the CI ShellCheck step.
…tatus cards

More Gum surfaced through the CLI:
- Status: two double-ruled cards via `gum join --horizontal`, and the
  freshness line via `gum format --type template` (colored by status)
- Status: the script-health table is now interactive (`--return-column`)
  and opens the selected script's doc page (or source) in `gum pager`
- Peek: glow/gum-format style is chosen from the tomb's `template:`
  frontmatter (falling back to `default_template`), so previews match
  the page's theme
- spin: per-ritual spinner selection, overridable with `RK_SPINNER`
- panel(): accepts an optional numeric width so cards can sit side by side
@drawmeanelephant

Copy link
Copy Markdown
Owner Author

Added a follow-up commit (2159283) with the Gum wins: theme-matched peek, interactive script-health table → doc/source pager, gum join two-up status cards, gum format template freshness line, and per-ritual spinners. Lint + pty smoke re-run green.

gum 2.0 (Bubble Tea v2) probes terminal capabilities on startup; because
`gum spin` is short-lived, the terminal's reply can arrive after gum
restores echo and print as junk like ^[[?1u (bubbletea #1627/#1749).

Add settle_terminal(): briefly disable echo on the controlling tty and
drain, so late replies are swallowed. Runs after every spin, restores the
saved termios via an EXIT/INT/TERM trap, and is a no-op when no tty is
available.
@drawmeanelephant

Copy link
Copy Markdown
Owner Author

Added settle_terminal (commit 06949fb) to absorb the late Kitty-protocol reply that was leaking as ^[[?1u after gum spin (bubbletea #1627/#1749). It disables echo briefly post-spin and drains, then restores termios via a trap; no-op without a tty. Echo restoration verified under a pty.

…lies

The previous post-spin drain was too late: Bubble Tea v2 sends its
capability probes before it settles into raw mode, so the terminal's
replies (^[[?2026;2$y, ^[[?2027;4$y, ^[[?1u) land while echo is still on
and get echoed as junk at spin startup. iTerm and Ghostty both show it.

Instead, disable echo before launching gum spin and keep it off through
the spin and a short drain, then restore the saved termios via an
EXIT/INT/TERM trap. No-op when there is no controlling tty. This removes
the window in which the replies could echo.

Replaces settle_terminal (post-spin only).
@drawmeanelephant

Copy link
Copy Markdown
Owner Author

Reworked the leak mitigation (commit faf211d). The post-spin drain was too late — Bubble Tea v2 sends its capability probes before entering raw mode, so replies like ^[[?2026;2$y, ^[[?2027;4$y, ^[[?1u echo at spin startup (seen on both iTerm and Ghostty). Now echo is disabled before gum spin and held off through the spin and a short drain, then termios is restored via a trap. No tty → no-op. Verified: echo restored and the ritual→menu flow intact under a pty.

@drawmeanelephant
drawmeanelephant merged commit e9a3cb8 into main Sep 10, 2026
3 checks passed
@drawmeanelephant
drawmeanelephant deleted the feat/rotatui-gum-leverage branch September 10, 2026 20:55
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