Skip to content

refactor: split ui/layouts/hud.py along its ADR 0012 widget seams #145

Description

@tony

Summary

src/agentgrep/ui/layouts/hud.py is 3,243 lines — more than twice the next largest module in src/ (discovery.py at 1,563) and the single remaining god module in the tree. Split it along the widget seams that ADR 0012 already sanctions.

This replaces the HUD portion of #128, which is closed: its other two targets are already done. adapters.py became a package in 75a2c680, and tests/test_agentgrep.py was deleted wholesale in e5c2725c. Only the HUD remained, and it grew rather than shrank.

Why this is its own issue

ADR 0012 is Accepted and already specifies both the reusable-widget architecture and a strangler-fig implementation sequence in which app.py stays a thin facade. ADR 0013 (also Accepted) establishes the layout/workflow composition seam. The design work is done; what is missing is the extraction. Widgets already live under src/agentgrep/ui/widgets/, so this is a move into an existing structure, not a new architecture.

The scheduling constraint that shapes the work

Four open PRs queue large deltas against this exact file: #111, #121, #122 and #89. #111 is also the only open PR that currently conflicts with master, and its conflict regions are in this file.

That makes a pure-move extraction the only safe shape. Moving cohesive blocks without renaming public attributes, changing signatures, or re-flowing method bodies keeps those four branches mechanically rebasable. A rewrite would force four separate manual conflict resolutions and would make this issue a hard blocker on the identity stack — which it must not become.

Non-blocking invariants that must survive

ADR 0011 is Accepted and the HUD is the highest-risk surface in the repo for violating it. Enforcement lives entirely in src/agentgrep/ui/_runtime.py; there is no retained static gate, and the decorators only assert under pytest or an explicitly truthy AGENTGREP_TUI_WATCHDOG.

Every moved pump entrypoint keeps its @pump_only, every run_worker target keeps @offload with its existing group=, and no file open, subprocess, sqlite3, filesystem walk, lock or queue wait, .result(), json.load(s)/dump(s), or unbounded CPU may become reachable from a pump callable as a result of the move. Because "blocks the pump" is not statically decidable, the proof runs the TUI lane with the watchdog armed.

Forward-looking

Nothing here may freeze a seam the roadmap needs. The layout registry stays open for new layouts, no widget count or file layout is final, and no keymap or public UI type is frozen — #126 adds a project-aware context switcher to this surface, and #142/#143 will add corpus-backed and multi-tier search results to it.

Goal

Idempotent completion condition for /goal. It asserts an end state, not an action: if the state already holds, the first evaluation passes and nothing is edited.

/goal On a local topic branch cut from master in the primary checkout (never commit on master, never push): src/agentgrep/ui/layouts/hud.py is under 1200 lines. First report git rev-parse --abbrev-ref HEAD and wc -l src/agentgrep/ui/layouts/hud.py, which reports 3243 today; if it already reports under 1200, stop with no edits. End state: the reduction comes only from moving cohesive blocks into modules under src/agentgrep/ui/widgets/ or src/agentgrep/ui/layouts/ that ADR 0012's widget architecture already sanctions, with no behavioural change. Every moved pump entrypoint keeps its @pump_only decorator, every run_worker target keeps @offload with its existing group, and no file open, subprocess, sqlite3, filesystem walk, lock or queue wait, .result(), json load or dump, or unbounded CPU becomes reachable from a pump callable. Constraints: pure move only, so no renamed public attribute, no changed signature, no altered keybinding, and no re-flowed method body beyond import adjustment, keeping the four open PRs that queue hud.py deltas mechanically rebasable; touch no engine or query module. Non-goals: rewriting the layout, adopting pluggable workflows, allocating or renumbering any ADR, and shrinking any other module. Seams: pin no widget count or file layout as final, keep the layout registry open, and freeze no keymap or public UI type. Proof: wc -l on hud.py and each new module, AGENTGREP_TUI_WATCHDOG=1 NO_COLOR=1 just test-tui and NO_COLOR=1 just test exiting 0, and git diff --stat showing insertions within five percent of deletions. Or stop after 25 turns and report what remains.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions