Skip to content

refactor: remove dead parallel abstraction from tool renderer subsystem - #479

Open
tunahorse wants to merge 1 commit into
masterfrom
claude/codebase-complexity-cleanup-gxyl8u
Open

refactor: remove dead parallel abstraction from tool renderer subsystem#479
tunahorse wants to merge 1 commit into
masterfrom
claude/codebase-complexity-cleanup-gxyl8u

Conversation

@tunahorse

@tunahorse tunahorse commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Description

Removes a dead parallel abstraction layer from src/tunacode/ui/renderers/tools/ (net −133 lines, no behavior change):

  • ToolRendererProtocol (~90 lines in base.py): a runtime_checkable Protocol that duplicated the BaseToolRenderer ABC method-for-method, docstrings included. All six renderers subclass the ABC; the Protocol was never used as a type annotation, isinstance check, or generic bound anywhere in src, tests, or scripts — it was a second copy of the same seven-method interface to keep in sync for no benefit.
  • pad_lines: free function duplicating BaseToolRenderer.pad_viewport_lines line-for-line, zero callers.
  • list_renderers: zero callers.
  • Package __init__.py re-export surface: previously re-exported 13 symbols under # noqa: F401, but external code only imports get_renderer (in panels.py) and render_bash (directly from its submodule). The init now exports get_renderer plus the six submodule imports whose side effect registers each renderer, with a docstring explaining the registration mechanism.

Every removed symbol was verified dead via repo-wide grep (zero usages outside its definition site) before deletion.

Pre-PR Checklist

  • Rebased onto master (git fetch origin && git rebase origin/master)
  • All pre-commit hooks pass (uv run pre-commit run --all-files)
  • Tech debt baseline updated — N/A, no TODO/FIXME markers added

Type of Change

  • Refactoring (code improvement without changing functionality)

Testing

  • All existing tests pass (uv run pytest) — 325 passed, 2 skipped
  • New tests have been added to cover the changes — N/A, deletion of verified-dead code only
  • Tests have been run locally
  • Golden/character tests established for new features — N/A

Test Coverage

  • Deletion-only change; also verified at runtime that all six renderers still register through the dispatch registry (get_renderer returns a renderer for bash, discover, hashline_edit, read_file, web_fetch, write_file).

Pre-commit Checks

  • All pre-commit hooks pass
  • Code formatted with ruff format
  • Code passes ruff check without warnings
  • No non-test Python file exceeds 600 lines

Checklist

  • My code follows the Python coding standards (type hints, f-strings, pathlib, etc.)
  • I have performed a self-review of my own code
  • I have commented my code where necessary, particularly in hard-to-understand areas
  • I have updated documentation in @documentation/ and .claude/ directories — N/A, removed symbols are not documented there
  • My changes generate no new warnings
  • Dependencies are properly managed in pyproject.toml — no dependency changes
  • Any dependent changes have been merged and published — none
  • Created rollback point with clear commit message before changes

Documentation Updates

  • Updated relevant files in @documentation/ — N/A
  • Updated developer notes in .claude/ — N/A
  • README.md updated (if needed) — N/A

Additional Notes

Audit also surfaced six exception classes in src/tunacode/exceptions.py with zero references (StateError, ServiceError, GitOperationError, ModelConfigurationError, SetupValidationError, ToolBatchingJSONError, ~70 lines) — left out of this PR to keep it a single focused change; can follow up separately.

🤖 Generated with Claude Code

https://claude.ai/code/session_01HF5Lg9K7LhXLFstq2CKkKq


Generated by Claude Code

Summary

  • Simplified tool renderer registration and reduced package-level exports to get_renderer and renderer imports needed for registration.
  • Removed unused ToolRendererProtocol, pad_lines, and list_renderers abstractions.
  • Documented the renderer registration mechanism.
  • No changes to session state, messages, tool-call handling, or exception paths.
  • Reduced unused typing abstractions without affecting the existing registry or renderer behavior.
  • Confirmed all six renderers remain registered; tests and quality checks pass.

ToolRendererProtocol was a ~90-line runtime_checkable Protocol that
exactly duplicated the BaseToolRenderer ABC method-for-method, yet was
never used as an annotation, isinstance check, or bound anywhere.
Renderers all subclass the ABC, so the Protocol was a second copy of
the same interface to keep in sync for no benefit.

Also removes two helpers with zero callers (pad_lines, which duplicated
BaseToolRenderer.pad_viewport_lines, and list_renderers) and trims the
package __init__ re-export list to what external code actually imports:
get_renderer plus the submodule imports that register each renderer.

Verified by repo-wide grep (zero usages of every removed symbol outside
its definition) and the full test suite.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HF5Lg9K7LhXLFstq2CKkKq
@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: eb056198-829a-4e74-9320-484ddba3df6d

📥 Commits

Reviewing files that changed from the base of the PR and between 853724d and aea5365.

📒 Files selected for processing (2)
  • src/tunacode/ui/renderers/tools/__init__.py
  • src/tunacode/ui/renderers/tools/base.py
📜 Recent review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: pre-commit
🧰 Additional context used
📓 Path-based instructions (4)
**/*.py

📄 CodeRabbit inference engine (Custom checks)

**/*.py: Enforce dependency direction: ui → core → tools → utils/types. Flag violations where core/ imports from ui/, tools/ imports from ui/, tools/ imports from core/, or types/ imports from anything except stdlib/typing
In agent/orchestration code, verify exception handlers clean up state: flag except (UserAbortError, CancelledError) patterns that exist without corresponding cleanup like _remove_dangling_tool_calls() or state rollback. State mutations (messages.append, session modifications) followed by await/function calls that could raise must be cleaned up in except blocks
Check for shallow copy followed by nested dict mutation: flag .copy() on dicts that contain nested dicts/lists. Use deepcopy() instead or use dictionary spreading syntax to avoid mutating original objects
Enforce error handling principle: 'Fail fast, fail loud. No silent fallbacks.' Flag except: pass, except Exception: pass, empty except blocks, catching broad exceptions without re-raising or logging, and returning None/[]/{} sentinel values instead of raising exceptions for invalid inputs

**/*.py: Use Python 3.11 or newer.
Do not introduce new file-specific exemptions to the >600 line rule; fix the enforcement path or split the code instead.

Files:

  • src/tunacode/ui/renderers/tools/__init__.py
  • src/tunacode/ui/renderers/tools/base.py
src/tunacode/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

src/tunacode/**/*.py: Keep application code under the primary src/tunacode/ package and preserve its documented package structure.
Preserve the dependency direction types -> utils -> infrastructure -> configuration -> tools -> core -> ui; do not add imports across forbidden layers.
Follow the repository's documented import ordering for shared modules and layered modules.
Do not add TunaCode-owned message-contract wrappers around tinyagent message types; use tinyagent models directly in memory and keep dict payloads at real boundaries.
Prefer small, scoped, minimal, and targeted edits; follow existing nearby patterns, including command and test naming.

Files:

  • src/tunacode/ui/renderers/tools/__init__.py
  • src/tunacode/ui/renderers/tools/base.py
src/tunacode/ui/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Keep Rich default/ANSI color handling local to TunaCode; preserve the startup/theme stability behavior involving render_safety.py and built-in theme wrapping in constants.py.

Files:

  • src/tunacode/ui/renderers/tools/__init__.py
  • src/tunacode/ui/renderers/tools/base.py

⚙️ CodeRabbit configuration file

src/tunacode/ui/**/*.py: UI layer rules:

  1. DEPENDENCY DIRECTION: ui/ can import from core/, tools/, utils/, types/

    • core/ MUST NOT import from ui/ (check for violations)
  2. GATE 5 - Indirection Requires Verification:

    • If using expand=True, verify actual rendered width
    • Panel widths should be explicit, not delegated
  3. Command implementations:

    • Must handle errors gracefully
    • Must not corrupt session state (see PR #264 /update crash)

Files:

  • src/tunacode/ui/renderers/tools/__init__.py
  • src/tunacode/ui/renderers/tools/base.py
**/*

📄 CodeRabbit inference engine (AGENTS.md)

**/*: Before any Git operation, read docs/git/practices.md in the current session.
Never delete or clean untracked files or directories without explicit user confirmation; pause and ask if unknown files appear during checks.
During commit-time check failures, apply only trivial lint-only fixes; otherwise stop and request user instruction rather than making architectural or refactoring changes.
Do not edit unrelated local changes unless they are within the task scope.
Avoid adding empty directories or __init__.py-only directories.
Run validation commands before handoff when touching architecture, dependencies, or shared packages.

Files:

  • src/tunacode/ui/renderers/tools/__init__.py
  • src/tunacode/ui/renderers/tools/base.py
🔇 Additional comments (2)
src/tunacode/ui/renderers/tools/base.py (1)

1-1: LGTM!

Also applies to: 17-17, 78-78

src/tunacode/ui/renderers/tools/__init__.py (1)

8-21: LGTM!


📝 Walkthrough

Walkthrough

The renderer package now exposes only lookup-focused imports, while the base module removes protocol-related typing and updates its documentation. Renderer registration continues through side-effect imports.

Changes

Renderer API cleanup

Layer / File(s) Summary
Base renderer contract cleanup
src/tunacode/ui/renderers/tools/base.py
Updates the base renderer documentation and removes Protocol and runtime_checkable typing imports.
Renderer registration import surface
src/tunacode/ui/renderers/tools/__init__.py
Keeps get_renderer available and imports individual renderer functions for decorator-based registration without re-exporting unrelated helpers.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 9
✅ Passed checks (9 passed)
Check name Status Explanation
Title check ✅ Passed The title uses the required conventional-commits refactor: prefix and clearly matches the code removal/refactor in the PR.
Description check ✅ Passed The description largely follows the repository template and includes the required sections, change type, testing, checklist, and notes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Noshallowcopymutation ✅ Passed The PR diff only removes code/imports in base.py and init.py; no .copy() or nested mutation appears in the touched files or diff.
Exceptionpathcleanup ✅ Passed PASS: PR only changes tool-renderer registration; no agent/orchestration exception handlers were touched, and the core/agents CancelledError handler already calls cleanup.
Dependencydirection ✅ Passed Both changed files are in ui; imports are same-package or lower-layer (constants/types), with no ui/core/tool upward violation.
Nosilentfailures ✅ Passed Deletion-only diff; no added broad/empty excepts. Existing None returns in renderer lookup/render are intentional and handled by panels.py.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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.

2 participants