feat(tui): render hardening, visible state, clipboard/export - #60
Merged
Merged
Conversation
- sanitize: C1 controls, bidi overrides, zero-width classes; tabs expand to columns; tool/model/version/risk wire fields collapsed at ingestion - truncate(): display-column cut via x/ansi — CJK/emoji can no longer overflow budgets; conversation lines hard-clamped so hit-tests stay true - visible state: armed gates render at the composer, disarmed runes fall through, events tab + copy cursor drawn, find n/N + live scroll, queue two-step delete, /help truth pass, jump landing notes - clipboard: pbcopy/wl-copy/clip exec chain with honest notes, OSC 52 fallback for SSH; ^Y no longer copies raw ANSI cards - /export [md|json]: owner-only 0600, never overwrites - voice sweep: pluralization, units, jargon bans, single count surface - hostile terminals: status row clamped, viewport floor 1 with composer degradation step
- clampLines: per-line truncate, never pad; offsets track the clamped text so hit-test indices cannot drift (P1) - jumpTurn landing notes batch their sweep cmd — they fade instead of sticking forever (P1) - queue: armed row disarms on moves and head drains; armed state gets a visible ! marker in mouse mode too (P2) - relayout ladder skips the composer shrink while an approval panel owns the input area (P2) - tabs survive sanitize for copy fidelity; display paths (truncate, clampLines) expand them where cell math happens (P2) - writeExport stat loop bounded (P2)
- find bar: width budget from live chrome + hard clamp — the bar can no longer wrap on narrow terminals; pasted queries sanitized; empty query drops the empty quotes - clampLines: tabs expand before measuring, so a passing line can never render past the viewport - queue: y joins d as the confirm verb (matches every other gate); the armed hint explains itself in mouse mode too; transient note dropped - jump landing note keys off the landed line — it can no longer name a turn alt+y won't copy - clipboard: small payloads write synchronously (no goroutine leak on a failed helper start) - writeExport: O_EXCL create — a race can no longer truncate a file - statusLine shear marked with an ellipsis
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
Implements TEMP_BODEK_UX_POLISH_PLAN.md — five adversarial audits (~130 verified findings) fixed in six batches, then re-attacked by three review judges (25 findings, all addressed).
W1 — Hardening (sanitize + width discipline)
sanitize()now also strips C1 controls, bidi overrides/isolates, zero-width/soft-hyphen/line-separator classes; tabs stay in stored content (copy fidelity) and expand at render boundariestruncate()cuts by display columns (x/ansi, grapheme-safe) — CJK/emoji can no longer overflow ~40 budget sitesclampLines()choke point: transcript lines hard-clamped so logical rows == physical rows (mouse/scroll hit-tests stay true)W2 — Visible state & escape stack
alt+↑/↓jumps report their landing (turn 2/7 — alt+y copies this reply)nnext /Nprev, scrolling stays live while searching;/helptruth pass (phantomrremoved,^S/^K/alt+f/^Ydocumented)darms →y/dconfirms) with a visible!armed markerW3 — Clipboard & export
pbcopy/wl-copy/clip) → OSC 52 fallback (SSH-aware); notes are honest (copied N bytes via <tool>, OSC 52 marked unconfirmed)^Y/alt+yno longer copy raw ANSI cards/export [md|json]: current-session transcript to CWD, 0600, never overwrites (O_EXCL + suffix)W4–W6 — Voice, rhythm, hostile terminals
1 matches→plural()), units (bytes), jargon bans (swarm→sub-agents, SA#→#n, ws conns→connections, trust class→always allow), single count surface for approvals, unified header separators, help key column alignedVerification
make fmt✓make vet✓make lint0 issues ✓make test(-race, all packages) ✓Deliberately deferred (next milestone)
🤖 Generated with odek