Repository navigation
fix(tui): harden TUI surface — markup escape, audit + rate-limit, bounded context - #49
Merged
Merged
Conversation
…ed context Port onto v0.2.0 (v0.2.0 never touched tui/app.py or assistant.py, so these were all still live). Adapts to v0.2.0's reworked tasks.py/security.py. - Escape untrusted page titles before the tab bar renders them (a title with Rich-markup metacharacters could raise MarkupError or inject styling). - New security.RequestGuard pairs the rate limiter with the audit log; the TUI commands/assist path and the background task probes now go through it, so the TUI surface is finally audited and background watches are metered (they were not). The MCP server keeps its own inline guard with correlation ids. - TaskManager.aclose() now awaits the cancelled probe handles before returning, so quitting the TUI doesn't race on_unmount closing the shared clients. - Bound per-turn assistant context to the most-recent few open tabs; run /search's ranked-results and grounded-answer calls concurrently (with return_exceptions so a failure in one doesn't orphan the other); derive /task's valid kinds from get_args(TaskKind). - group_tabs now absorbs a malformed/non-conforming model response (catches the ValueError _content raises, and guards non-dict groups / non-list indexes) instead of crashing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This was referenced Jun 12, 2026
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.
Re-targeted onto v0.2.0 (supersedes #42). v0.2.0 never touched
tui/app.pyorassistant.py, so all of these were still live; the guard wiring is adapted to v0.2.0's reworkedtasks.py/security.py.Still-live issues fixed
_refresh_tabbarnow escapes the page title, so[2026] Best [GPU] dealsis shown literally instead of raisingMarkupErroror injecting styling.security.RequestGuardpairs the rate limiter with the audit log. The TUI commands/assist path and the background/taskprobes now go through it, so the TUI is audited and background watches are metered (aRateLimitErrorjust counts as a probe failure toward v0.2.0's give-up threshold). The MCP server keeps its own inline guard (with correlation ids) untouched.TaskManager.aclose()awaits the cancelled probe handles before returning, so quitting doesn't raceon_unmountclosing the shared fetcher/client./searchruns its two independent calls viaasyncio.gather(return_exceptions=True), so a failure in one no longer orphans the other./taskderives valid kinds fromget_args(TaskKind).Tests (113 passed, +6)
RequestGuardaudit + rate-limit; guard-metered probe;acloseawaits an in-flight probe; tab-bar escaping a bracketed title;/searchsurfacing an error without crashing. ruff + mypy --strict clean, coverage 89.5%.Supersedes #42.
🤖 Generated with Claude Code