feat(tui): implement TuiMaterializer bridging A2A event queue to conversation view with ThoughtBlockWidget #11164

Merged
HAL9000 merged 4 commits from pr/10589-tui-materializer into master 2026-06-15 11:14:32 +00:00
8 changed files with 1309 additions and 788 deletions
+13 -1
View File
@@ -527,6 +527,18 @@ _ALL_DATA_COLUMNS + ") " "SELECT " + _ALL_DATA_COLUMNS + " FROM v3_plans"`.
machine-readable JSON envelope structure shared across all CLI commands, and CI-friendly
`diagnostics --check` health monitoring. Registered in `docs/showcase/examples.json`. Closes #7592.
- **TuiMaterializer A2A integration layer** (#5326): Implemented the
``TuiMaterializer`` class that bridges the Output Rendering Framework to
Textual UI widgets, enabling all CLI command producers to render in the TUI
without modification. Implements the ``MaterializationStrategy`` protocol and
maps ``ElementHandle`` events (Panel, Table, Status, Progress, Tree, Code,
Diff, Separator, ActionHint, Text) to plain-text renderings for TUI display.
Includes A2A event routing for ``PermissionRequest`` and ``ThoughtBlock`` events.
Thread-safe event accumulation with thread-lock guards on all state mutations.
Supports real-time streaming updates via the ``on_event`` callback pattern.
Comprehensive Behave BDD test suite covering all element types, callback
invocation, rendered output accumulation, A2A routing, and concurrent thread safety.
- `agents actor context clear` command to reset actor message history and
state while preserving the underlying context directory via `ContextManager`
(#6370).
@@ -1271,4 +1283,4 @@ iteration` and data corruption under concurrent plan execution. All public
- **TUI -- Permission Question Widget**: A new inline `PermissionQuestionWidget`
renders permission requests directly in the conversation stream for single-key
operations. Users can allow/reject with single-key shortcuts (`a`/`A`/`r`/`R`),
navigate with arrow keys, confirm with `Enter`, or press `v` to open the full
navigate with arrow keys, confirm with `Enter`, or press `v` to open the full
+3
View File
1
@@ -68,6 +68,9 @@ Below are some of the specific details of various contributions.
* HAL 9000 has contributed the concurrent ValidationPipeline stdout/stderr restoration fix (PR #7811 / issue #7623): introduced a reference-counted shared stream wrapper manager so concurrent ValidationPipeline.run() calls correctly restore the true sys.stdout/sys.stderr after all pipelines finish, preventing permanent stream wrapping under concurrent execution.
* HAL 9000 has contributed the LLMTraceRepository data-integrity fix (PR #8185 / issue #7505): replaced the unconditional `session.commit()` in `LLMTraceRepository.save()` with a dual-path implementation that respects the UnitOfWork pattern — flushing only when an external session is provided, and flushing + committing + closing when operating standalone. This eliminates premature transaction commits, loss of rollback capability, and a docstring/implementation mismatch.
* HAL 9000 has contributed the ACMS Index Data Model and File Traversal Engine (PR #9664 / issue #9579): foundational data structures for indexed context entries with hot/warm/cold/archive storage tier classification, tag system, and a timeout-safe chunked file traversal engine for large projects with 10,000+ files.
* HAL 9000 has contributed the TuiMaterializer A2A integration layer (PR #10589 / issue #5326): implemented the ``TuiMaterializer`` class bridging the Output Rendering Framework to Textual UI widgets, implementing the ``MaterializationStrategy`` protocol, mapping all element types (Panel, Table, Status, Progress, Tree, Code, Diff, Separator, ActionHint, Text) to plain-text renderings, adding A2A routing for PermissionRequest and ThoughtBlock events, with comprehensive Behave BDD test coverage including thread-safety verification.
* HAL 9000 has contributed the error-suppression removal fix (PR #9247 / issue #9060): removed both `try...except Exception:` blocks in `register_registry_agents()` that silently suppressed errors from `actor_registry.list_actors()` and the route bridge refresh, enabling exceptions to propagate per CONTRIBUTING.md fail-fast policy. Added three Behave scenarios verifying RuntimeError, AttributeError, and TypeError propagation.
* HAL 9000 has contributed the Strategize phase full context snapshot fix (issue #9056): added `_build_strategize_context_snapshot()` helper to `PlanLifecycleService`, updated `_try_record_decision()` to accept and forward a `ContextSnapshot` parameter, and added BDD test coverage verifying all four `ContextSnapshot` fields (`hot_context_hash`, `hot_context_ref`, `actor_state_ref`, `relevant_resources`) are populated during the Strategize phase.
* HAL 9000 has contributed the ACMS context path matching fix (PR #10975 / issue #10972): corrects `_path_matches()` and `_matches_pattern()` to properly match absolute fragment paths against relative glob patterns by auto-prefixing with `**/` before calling `PurePath.full_match()`, preventing silent inefficacy of include/exclude filters for absolute paths in fragment metadata.
+515
View File
@@ -0,0 +1,515 @@
"""Step definitions for tui_materializer.feature."""
Outdated
Review

BLOCKING — CI lint and unit_tests are both failing

This file is part of the ruff lint scope (features/ directory). The CI / lint job failed after 1m14s. Please run nox -s lint locally to identify and fix all ruff violations.

Additionally, CI / unit_tests failed after 3m47s. Please run nox -s unit_tests to reproduce and fix all failing Behave scenarios. Once passing, verify nox -s coverage_report still reports >=97%.


Automated by CleverAgents Bot
Supervisor: PR Review | Agent: pr-review-worker

**BLOCKING — CI lint and unit_tests are both failing** This file is part of the ruff lint scope (`features/` directory). The `CI / lint` job failed after 1m14s. Please run `nox -s lint` locally to identify and fix all ruff violations. Additionally, `CI / unit_tests` failed after 3m47s. Please run `nox -s unit_tests` to reproduce and fix all failing Behave scenarios. Once passing, verify `nox -s coverage_report` still reports >=97%. --- Automated by CleverAgents Bot Supervisor: PR Review | Agent: pr-review-worker
from __future__ import annotations
import threading
from typing import Any
from behave import given, then, when # type: ignore[import-untyped]
# ---------------------------------------------------------------------------
# Background
# ---------------------------------------------------------------------------
@given("the tui materializer module is imported")
def step_import_tui_materializer(context: Any) -> None:
from cleveragents.tui.materializer import (
TuiMaterializer,
TuiWidgetEvent,
TuiWidgetEventType,
render_element_for_tui,
)
context.TuiMaterializer = TuiMaterializer
context.TuiWidgetEvent = TuiWidgetEvent
context.TuiWidgetEventType = TuiWidgetEventType
context.render_element_for_tui = render_element_for_tui
context.materializer = None
context.session = None
context.panel_handle = None
context.status_handle = None
context.rendered_text = ""
context.callback_events: list[TuiWidgetEvent] = []
context.last_event: TuiWidgetEvent | None = None
# ---------------------------------------------------------------------------
# Module exports
# ---------------------------------------------------------------------------
@then("TuiMaterializer should be importable from tui.materializer")
def step_check_tui_materializer_importable(context: Any) -> None:
from cleveragents.tui.materializer import TuiMaterializer
assert TuiMaterializer is not None
@then("TuiWidgetEvent should be importable from tui.materializer")
def step_check_tui_widget_event_importable(context: Any) -> None:
from cleveragents.tui.materializer import TuiWidgetEvent
assert TuiWidgetEvent is not None
@then("TuiWidgetEventType should be importable from tui.materializer")
def step_check_tui_widget_event_type_importable(context: Any) -> None:
from cleveragents.tui.materializer import TuiWidgetEventType
assert TuiWidgetEventType is not None
@then("render_element_for_tui should be importable from tui.materializer")
def step_check_render_element_for_tui_importable(context: Any) -> None:
from cleveragents.tui.materializer import render_element_for_tui
assert render_element_for_tui is not None
# ---------------------------------------------------------------------------
# TuiMaterializer instantiation
# ---------------------------------------------------------------------------
@when("I create a TuiMaterializer without a callback")
def step_create_materializer_no_callback(context: Any) -> None:
from cleveragents.tui.materializer import TuiMaterializer
context.materializer = TuiMaterializer()
@when("I create a TuiMaterializer with a callback")
def step_create_materializer_with_callback(context: Any) -> None:
from cleveragents.tui.materializer import TuiMaterializer, TuiWidgetEvent
context.callback_events = []
def _callback(event: TuiWidgetEvent) -> None:
context.callback_events.append(event)
context.materializer = TuiMaterializer(on_event=_callback)
@then('the materializer strategy_name should be "tui"')
def step_check_strategy_name(context: Any) -> None:
assert context.materializer.strategy_name == "tui"
@then("the materializer supports_incremental_updates should be True")
def step_check_supports_incremental(context: Any) -> None:
assert context.materializer.supports_incremental_updates is True
@then("the materializer events list should be empty")
def step_check_events_empty(context: Any) -> None:
assert context.materializer.events == []
# ---------------------------------------------------------------------------
# the materializer should still be running (alias for strategy checks)
# ---------------------------------------------------------------------------
@then("the materializer should still be running")
def step_materializer_still_running(context: Any) -> None:
"""The materializer is considered 'running' when it reports a valid
strategy name and supports incremental updates."""
assert context.materializer.strategy_name == "tui"
assert context.materializer.supports_incremental_updates is True
# ---------------------------------------------------------------------------
# on_session_begin
# ---------------------------------------------------------------------------
@when("I call on_session_begin with a mock session")
def step_call_on_session_begin(context: Any) -> None:
context.materializer.on_session_begin(None) # type: ignore[arg-type]
# ---------------------------------------------------------------------------
# OutputSession integration
# ---------------------------------------------------------------------------
@when("I use the materializer with an OutputSession")
def step_use_with_output_session(context: Any) -> None:
from cleveragents.cli.output.session import OutputSession
context.session = OutputSession(strategy=context.materializer)
@when('I create a panel handle titled "{title}"')
def step_create_panel_handle(context: Any, title: str) -> None:
context.panel_handle = context.session.panel(title)
@when('I create a table handle titled "{title}"')
def step_create_table_handle(context: Any, title: str) -> None:
context.table_handle = context.session.table(title)
@when('I create a progress handle with label "{label}"')
def step_create_progress_handle(context: Any, label: str) -> None:
context.progress_handle = context.session.progress(label, indeterminate=True)
@when("I create a separator handle")
def step_create_separator_handle(context: Any) -> None:
context.separator_handle = context.session.separator()
@when('I create an action hint handle with command "{command}"')
def step_create_action_hint_handle(context: Any, command: str) -> None:
context.action_hint_handle = context.session.action_hint([command])
@when("I close the session")
def step_close_session(context: Any) -> None:
context.session.close()
@when('I create and close a status handle with message "{message}"')
def step_create_and_close_status_handle(context: Any, message: str) -> None:
handle = context.session.status(message)
handle.close()
# ---------------------------------------------------------------------------
# Event assertions
# ---------------------------------------------------------------------------
@then("an element_created event should be emitted")
def step_check_element_created_event(context: Any) -> None:
events = context.materializer.events
created_events = [e for e in events if e.event_type == "element_created"]
assert len(created_events) > 0, f"No element_created events found. Events: {events}"
context.last_event = created_events[-1]
@then('the event element_kind should be "{kind}"')
def step_check_event_element_kind(context: Any, kind: str) -> None:
assert context.last_event is not None
assert context.last_event.element_kind == kind, (
f"Expected element_kind={kind!r}, got {context.last_event.element_kind!r}"
)
@then('the event rendered_text should contain "{text}"')
def step_check_event_rendered_text_contains(context: Any, text: str) -> None:
assert context.last_event is not None
assert text in context.last_event.rendered_text, (
f"Expected {text!r} in rendered_text={context.last_event.rendered_text!r}"
)
@then("an element_closed event should be emitted")
def step_check_element_closed_event(context: Any) -> None:
events = context.materializer.events
closed_events = [e for e in events if e.event_type == "element_closed"]
assert len(closed_events) > 0, f"No element_closed events found. Events: {events}"
context.last_closed_event = closed_events[-1]
@then('the closed event rendered_text should contain "{text}"')
def step_check_closed_event_rendered_text(context: Any, text: str) -> None:
assert context.last_closed_event is not None
assert text in context.last_closed_event.rendered_text, (
f"Expected {text!r} in rendered_text={context.last_closed_event.rendered_text!r}"
)
@then("a session_end event should be emitted")
def step_check_session_end_event(context: Any) -> None:
events = context.materializer.events
end_events = [e for e in events if e.event_type == "session_end"]
assert len(end_events) > 0, f"No session_end events found. Events: {events}"
# ---------------------------------------------------------------------------
# Callback assertions
# ---------------------------------------------------------------------------
@then("the callback should have been called")
def step_check_callback_called(context: Any) -> None:
assert len(context.callback_events) > 0, "Callback was not called"
@then('the callback event type should be "element_created"')
def step_check_callback_event_type_created(context: Any) -> None:
created = [e for e in context.callback_events if e.event_type == "element_created"]
assert len(created) > 0, (
f"No element_created callback events. Got: {[e.event_type for e in context.callback_events]}"
)
@then('the callback should have been called with event_type "{event_type}"')
def step_check_callback_event_type(context: Any, event_type: str) -> None:
matching = [e for e in context.callback_events if e.event_type == event_type]
assert len(matching) > 0, (
f"No {event_type!r} callback events. Got: {[e.event_type for e in context.callback_events]}"
)
# ---------------------------------------------------------------------------
# rendered_output property
# ---------------------------------------------------------------------------
@then("the materializer rendered_output should be empty")
def step_check_rendered_output_empty(context: Any) -> None:
assert context.materializer.rendered_output == "", (
f"Expected empty rendered_output, got: {context.materializer.rendered_output!r}"
)
@then('the materializer rendered_output should contain "{text}"')
def step_check_rendered_output_contains(context: Any, text: str) -> None:
output = context.materializer.rendered_output
assert text in output, f"Expected {text!r} in rendered_output={output!r}"
# ---------------------------------------------------------------------------
# render_element_for_tui
# ---------------------------------------------------------------------------
@when('I render a Panel element with title "{title}" and entry "{key}" "{value}"')
def step_render_panel_element(context: Any, title: str, key: str, value: str) -> None:
from cleveragents.cli.output.handles._models import Panel, PanelEntry
from cleveragents.tui.materializer import render_element_for_tui
element = Panel(title=title, entries=[PanelEntry(key=key, value=value)])
context.rendered_text = render_element_for_tui(element)
@when('I render a Table element with title "{title}" and column "{column}"')
def step_render_table_element(context: Any, title: str, column: str) -> None:
from cleveragents.cli.output.handles._models import ColumnDef, Table
from cleveragents.tui.materializer import render_element_for_tui
element = Table(title=title, columns=[ColumnDef(name=column)])
context.rendered_text = render_element_for_tui(element)
@when('I render a StatusMessage element with level "{level}" and message "{message}"')
def step_render_status_element(context: Any, level: str, message: str) -> None:
from cleveragents.cli.output.handles._models import StatusMessage
from cleveragents.tui.materializer import render_element_for_tui
element = StatusMessage(message=message, level=level)
context.rendered_text = render_element_for_tui(element)
@when('I render an indeterminate ProgressIndicator with label "{label}"')
def step_render_indeterminate_progress(context: Any, label: str) -> None:
from cleveragents.cli.output.handles._models import ProgressIndicator
from cleveragents.tui.materializer import render_element_for_tui
element = ProgressIndicator(label=label, indeterminate=True)
context.rendered_text = render_element_for_tui(element)
@when(
'I render a determinate ProgressIndicator with label "{label}" current {current:d} total {total:d}'
)
def step_render_determinate_progress(
context: Any, label: str, current: int, total: int
) -> None:
from cleveragents.cli.output.handles._models import ProgressIndicator
from cleveragents.tui.materializer import render_element_for_tui
element = ProgressIndicator(label=label, current=current, total=total)
context.rendered_text = render_element_for_tui(element)
@when('I render a Tree element with root "{root}" and child "{child}"')
def step_render_tree_element(context: Any, root: str, child: str) -> None:
from cleveragents.cli.output.handles._models import Tree, TreeNode
from cleveragents.tui.materializer import render_element_for_tui
root_node = TreeNode(label=root, children=[TreeNode(label=child)])
element = Tree(root=root_node)
context.rendered_text = render_element_for_tui(element)
@when('I render a CodeBlock element with language "{language}" and content "{content}"')
def step_render_code_element(context: Any, language: str, content: str) -> None:
from cleveragents.cli.output.handles._models import CodeBlock
from cleveragents.tui.materializer import render_element_for_tui
element = CodeBlock(content=content, language=language)
context.rendered_text = render_element_for_tui(element)
@when('I render a DiffBlock element with file_a "{file_a}" and file_b "{file_b}"')
def step_render_diff_element(context: Any, file_a: str, file_b: str) -> None:
from cleveragents.cli.output.handles._models import DiffBlock
from cleveragents.tui.materializer import render_element_for_tui
element = DiffBlock(file_a=file_a, file_b=file_b)
context.rendered_text = render_element_for_tui(element)
@when('I render a Separator element with style "{style}"')
def step_render_separator_element(context: Any, style: str) -> None:
from cleveragents.cli.output.handles._models import Separator
from cleveragents.tui.materializer import render_element_for_tui
element = Separator(style=style)
context.rendered_text = render_element_for_tui(element)
@when('I render an ActionHint element with command "{command}"')
def step_render_action_hint_element(context: Any, command: str) -> None:
from cleveragents.cli.output.handles._models import ActionHint
from cleveragents.tui.materializer import render_element_for_tui
element = ActionHint(commands=[command])
context.rendered_text = render_element_for_tui(element)
@when('I render a TextBlock element with content "{content}"')
def step_render_text_element(context: Any, content: str) -> None:
from cleveragents.cli.output.handles._models import TextBlock
from cleveragents.tui.materializer import render_element_for_tui
element = TextBlock(content=content)
context.rendered_text = render_element_for_tui(element)
@when('I render a TextBlock element with content "{content}" and indent {indent:d}')
def step_render_text_element_with_indent(
context: Any, content: str, indent: int
) -> None:
from cleveragents.cli.output.handles._models import TextBlock
from cleveragents.tui.materializer import render_element_for_tui
element = TextBlock(content=content, indent=indent)
context.rendered_text = render_element_for_tui(element)
@then('the render output should contain "{text}"')
def step_check_rendered_text_contains(context: Any, text: str) -> None:
assert text in context.rendered_text, (
f"Expected {text!r} in rendered_text={context.rendered_text!r}"
)
@then("the render output should be empty")
def step_check_rendered_text_empty(context: Any) -> None:
assert context.rendered_text == "", (
f"Expected empty rendered_text, got: {context.rendered_text!r}"
)
# ---------------------------------------------------------------------------
# A2A event routing
# ---------------------------------------------------------------------------
@when('I route a permission request for "{file_path}" with type "{request_type}"')
def step_route_permission_request(
context: Any, file_path: str, request_type: str
) -> None:
from cleveragents.domain.models.core.inline_permission_question import (
InlinePermissionQuestion,
PermissionRequestType,
)
question = InlinePermissionQuestion(
file_path=file_path,
request_type=PermissionRequestType(request_type),
)
context.permission_question = question
context.materializer.route_permission_request(question)
@then("a permission_request event should be emitted")
def step_check_permission_request_event(context: Any) -> None:
events = context.materializer.events
perm_events = [e for e in events if e.event_type == "permission_request"]
assert len(perm_events) > 0, f"No permission_request events found. Events: {events}"
context.last_perm_event = perm_events[-1]
@then("the permission event extra should be the InlinePermissionQuestion")
def step_check_permission_event_extra(context: Any) -> None:
assert context.last_perm_event.extra is context.permission_question
@then('the permission event rendered_text should contain "{text}"')
def step_check_permission_event_rendered_text(context: Any, text: str) -> None:
assert text in context.last_perm_event.rendered_text, (
f"Expected {text!r} in rendered_text={context.last_perm_event.rendered_text!r}"
)
@when('I route a thought block with content "{content}"')
def step_route_thought_block(context: Any, content: str) -> None:
from cleveragents.domain.models.thought.thought_block import ThoughtBlock
thought = ThoughtBlock(content=content)
context.thought_block = thought
context.materializer.route_thought_block(thought)
@then("a thought_block event should be emitted")
def step_check_thought_block_event(context: Any) -> None:
events = context.materializer.events
thought_events = [e for e in events if e.event_type == "thought_block"]
assert len(thought_events) > 0, f"No thought_block events found. Events: {events}"
context.last_thought_event = thought_events[-1]
@then("the thought event extra should be the ThoughtBlock")
def step_check_thought_event_extra(context: Any) -> None:
assert context.last_thought_event.extra is context.thought_block
@then('the thought event rendered_text should contain "{text}"')
def step_check_thought_event_rendered_text(context: Any, text: str) -> None:
assert text in context.last_thought_event.rendered_text, (
f"Expected {text!r} in rendered_text={context.last_thought_event.rendered_text!r}"
)
# ---------------------------------------------------------------------------
# Thread safety
# ---------------------------------------------------------------------------
@when("I create multiple status handles concurrently")
def step_create_multiple_status_handles_concurrently(context: Any) -> None:
errors: list[Exception] = []
def _create_handle(i: int) -> None:
try:
handle = context.session.status(f"Message {i}")
handle.close()
except Exception as exc:
errors.append(exc)
threads = [threading.Thread(target=_create_handle, args=(i,)) for i in range(10)]
for t in threads:
t.start()
for t in threads:
t.join()
context.thread_errors = errors
@then("all events should be recorded without data corruption")
def step_check_thread_safety(context: Any) -> None:
assert context.thread_errors == [], f"Thread errors: {context.thread_errors}"
events = context.materializer.events
# We should have at least 10 element_created + 10 element_closed events
created = [e for e in events if e.event_type == "element_created"]
closed = [e for e in events if e.event_type == "element_closed"]
assert len(created) >= 10, f"Expected >= 10 created events, got {len(created)}"
assert len(closed) >= 10, f"Expected >= 10 closed events, got {len(closed)}"
+233
View File
@@ -0,0 +1,233 @@
Feature: TUI Materializer
As a TUI developer
I want a TuiMaterializer that bridges the Output Rendering Framework to Textual widgets
So that all CLI command producers can render in the TUI without modification
Background:
Given the tui materializer module is imported
# ── Module exports ────────────────────────────────────────────────────────
Scenario: TuiMaterializer is importable from tui.materializer
Then TuiMaterializer should be importable from tui.materializer
And TuiWidgetEvent should be importable from tui.materializer
And TuiWidgetEventType should be importable from tui.materializer
And render_element_for_tui should be importable from tui.materializer
# ── TuiMaterializer instantiation ────────────────────────────────────────
Scenario: TuiMaterializer can be instantiated without arguments
When I create a TuiMaterializer without a callback
Then the materializer strategy_name should be "tui"
And the materializer supports_incremental_updates should be True
And the materializer events list should be empty
Scenario: TuiMaterializer can be instantiated with a callback
When I create a TuiMaterializer with a callback
Then the materializer strategy_name should be "tui"
# ── MaterializationStrategy protocol ─────────────────────────────────────
Scenario: TuiMaterializer implements on_session_begin
When I create a TuiMaterializer without a callback
And I call on_session_begin with a mock session
Then the materializer should still be running
Scenario: TuiMaterializer emits element_created event for panel
When I create a TuiMaterializer without a callback
And I use the materializer with an OutputSession
And I create a panel handle titled "Test Panel"
Then an element_created event should be emitted
And the event element_kind should be "panel"
And the event rendered_text should contain "Test Panel"
Scenario: TuiMaterializer emits element_created event for table
When I create a TuiMaterializer without a callback
And I use the materializer with an OutputSession
And I create a table handle titled "Results"
Then an element_created event should be emitted
And the event element_kind should be "table"
And the event rendered_text should contain "Results"
Scenario: TuiMaterializer emits element_created event for status
When I create a TuiMaterializer without a callback
And I use the materializer with an OutputSession
And I create a status handle with message "Operation complete"
Then an element_created event should be emitted
And the event element_kind should be "status"
And the event rendered_text should contain "Operation complete"
Scenario: TuiMaterializer emits element_created event for progress
When I create a TuiMaterializer without a callback
And I use the materializer with an OutputSession
And I create a progress handle with label "Loading"
Then an element_created event should be emitted
And the event element_kind should be "progress"
And the event rendered_text should contain "Loading"
Scenario: TuiMaterializer emits element_created event for code block
When I create a TuiMaterializer without a callback
And I use the materializer with an OutputSession
And I create a code handle with content "print('hello')" and language "python"
Then an element_created event should be emitted
And the event element_kind should be "code"
And the event rendered_text should contain "print('hello')"
Scenario: TuiMaterializer emits element_created event for separator
When I create a TuiMaterializer without a callback
And I use the materializer with an OutputSession
And I create a separator handle
Then an element_created event should be emitted
And the event element_kind should be "separator"
Scenario: TuiMaterializer emits element_created event for action hint
When I create a TuiMaterializer without a callback
And I use the materializer with an OutputSession
And I create an action hint handle with command "agents plan list"
Then an element_created event should be emitted
And the event element_kind should be "action_hint"
And the event rendered_text should contain "agents plan list"
Scenario: TuiMaterializer emits element_closed event when handle is closed
When I create a TuiMaterializer without a callback
And I use the materializer with an OutputSession
And I create a panel handle titled "Closing Panel"
And I close the panel handle
Then an element_closed event should be emitted
And the closed event rendered_text should contain "Closing Panel"
Scenario: TuiMaterializer emits session_end event when session ends
When I create a TuiMaterializer without a callback
And I use the materializer with an OutputSession
And I create a status handle with message "Done"
And I close the session
Then a session_end event should be emitted
# ── Callback invocation ───────────────────────────────────────────────────
Scenario: TuiMaterializer invokes callback on element_created
When I create a TuiMaterializer with a callback
And I use the materializer with an OutputSession
And I create a status handle with message "Callback test"
Then the callback should have been called
And the callback event type should be "element_created"
Scenario: TuiMaterializer invokes callback on element_closed
When I create a TuiMaterializer with a callback
And I use the materializer with an OutputSession
And I create a status handle with message "Close callback test"
And I close the status handle
Then the callback should have been called with event_type "element_closed"
Scenario: TuiMaterializer invokes callback on session_end
When I create a TuiMaterializer with a callback
And I use the materializer with an OutputSession
And I close the session
Then the callback should have been called with event_type "session_end"
# ── rendered_output property ──────────────────────────────────────────────
Scenario: rendered_output returns empty string when no elements
When I create a TuiMaterializer without a callback
Then the materializer rendered_output should be empty
Scenario: rendered_output accumulates closed element text
When I create a TuiMaterializer without a callback
And I use the materializer with an OutputSession
And I create and close a status handle with message "Accumulated"
Then the materializer rendered_output should contain "Accumulated"
# ── render_element_for_tui ────────────────────────────────────────────────
Scenario: render_element_for_tui renders Panel with title and entries
When I render a Panel element with title "Info" and entry "key" "value"
Then the render output should contain "Info"
And the render output should contain "key"
And the render output should contain "value"
Scenario: render_element_for_tui renders Table with columns and rows
When I render a Table element with title "Data" and column "Name"
Then the render output should contain "Data"
And the render output should contain "Name"
Scenario: render_element_for_tui renders StatusMessage ok level
When I render a StatusMessage element with level "ok" and message "Success"
Then the render output should contain "ok"
And the render output should contain "Success"
Scenario: render_element_for_tui renders StatusMessage error level
When I render a StatusMessage element with level "error" and message "Failed"
Then the render output should contain "error"
And the render output should contain "Failed"
Scenario: render_element_for_tui renders indeterminate ProgressIndicator
When I render an indeterminate ProgressIndicator with label "Thinking"
Then the render output should contain "Thinking"
Scenario: render_element_for_tui renders determinate ProgressIndicator
When I render a determinate ProgressIndicator with label "Loading" current 5 total 10
Then the render output should contain "Loading"
And the render output should contain "50%"
Scenario: render_element_for_tui renders Tree with root and children
When I render a Tree element with root "root" and child "child1"
Then the render output should contain "root"
And the render output should contain "child1"
Scenario: render_element_for_tui renders CodeBlock with language
When I render a CodeBlock element with language "python" and content "x = 1"
Then the render output should contain "python"
And the render output should contain "x = 1"
Scenario: render_element_for_tui renders DiffBlock with hunks
When I render a DiffBlock element with file_a "old.py" and file_b "new.py"
Then the render output should contain "old.py"
And the render output should contain "new.py"
Scenario: render_element_for_tui renders Separator line style
When I render a Separator element with style "line"
Then the render output should contain "-"
Scenario: render_element_for_tui renders Separator blank style
When I render a Separator element with style "blank"
Then the render output should be empty
Scenario: render_element_for_tui renders Separator double style
When I render a Separator element with style "double"
Then the render output should contain "="
Scenario: render_element_for_tui renders ActionHint with commands
When I render an ActionHint element with command "agents plan list"
Then the render output should contain "agents plan list"
Scenario: render_element_for_tui renders TextBlock content
When I render a TextBlock element with content "Hello world"
Then the render output should contain "Hello world"
Scenario: render_element_for_tui renders TextBlock with indent
When I render a TextBlock element with content "indented" and indent 4
Then the render output should contain " indented"
# ── A2A event routing ─────────────────────────────────────────────────────
Scenario: route_permission_request emits permission_request event
When I create a TuiMaterializer without a callback
And I route a permission request for "src/main.py" with type "file_write"
Then a permission_request event should be emitted
And the permission event extra should be the InlinePermissionQuestion
And the permission event rendered_text should contain "src/main.py"
Scenario: route_thought_block emits thought_block event
When I create a TuiMaterializer without a callback
And I route a thought block with content "I am thinking"
Then a thought_block event should be emitted
And the thought event extra should be the ThoughtBlock
And the thought event rendered_text should contain "I am thinking"
# ── Thread safety ─────────────────────────────────────────────────────────
Scenario: TuiMaterializer events list is thread-safe
When I create a TuiMaterializer without a callback
And I use the materializer with an OutputSession
And I create multiple status handles concurrently
Then all events should be recorded without data corruption
+92
View File
@@ -0,0 +1,92 @@
"""TUI widget events — event type constants and event model classes.
This module is a companion to ``materializer.py`` to keep that file
under the 500-line file limit. Re-exported publicly through
``cleveragents.tui.materializer``.
"""
from __future__ import annotations
from typing import TYPE_CHECKING, Any
if TYPE_CHECKING:
from cleveragents.cli.output.handles._models import (
ElementSnapshot,
)
# ---------------------------------------------------------------------------
# Event type string constants
# ---------------------------------------------------------------------------
class TuiWidgetEventType:
"""String constants for TUI widget event types."""
ELEMENT_CREATED: str = "element_created"
ELEMENT_UPDATED: str = "element_updated"
ELEMENT_CLOSED: str = "element_closed"
SESSION_END: str = "session_end"
PERMISSION_REQUEST: str = "permission_request"
THOUGHT_BLOCK: str = "thought_block"
# ---------------------------------------------------------------------------
# Event class
# ---------------------------------------------------------------------------
class TuiWidgetEvent:
"""An event emitted by the TuiMaterializer to the host application.
The host application (e.g. ``_TextualCleverAgentsTuiApp``) subscribes
to these events to update the conversation widget incrementally.
Attributes:
event_type: One of the ``TuiWidgetEventType`` constants.
handle_id: The handle ID of the element that triggered the event.
element_kind: The element kind (e.g. ``"panel"``, ``"table"``).
rendered_text: Plain-text rendering of the element for display.
element_snapshot: The element snapshot at the time of the event.
extra: Optional extra data (e.g. permission question, thought block).
"""
__slots__ = (
"element_kind",
"element_snapshot",
"event_type",
"extra",
"handle_id",
"rendered_text",
)
def __init__(
self,
*,
event_type: str,
handle_id: str,
element_kind: str,
rendered_text: str = "",
element_snapshot: ElementSnapshot | None = None,
extra: Any = None,
) -> None:
self.event_type = event_type
self.handle_id = handle_id
self.element_kind = element_kind
self.rendered_text = rendered_text
self.element_snapshot = element_snapshot
self.extra = extra
def __repr__(self) -> str:
return (
f"TuiWidgetEvent("
f"event_type={self.event_type!r}, "
f"handle_id={self.handle_id!r}, "
f"element_kind={self.element_kind!r})"
)
__all__ = [
"TuiWidgetEvent",
"TuiWidgetEventType",
]
+204
View File
@@ -0,0 +1,204 @@
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
"""Plain-text rendering helpers for TUI display.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
This module is a companion to ``materializer.py`` to keep that file
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
under the 500-line file limit. Re-exported publicly through
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
``cleveragents.tui.materializer``.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
"""
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
from __future__ import annotations
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
from cleveragents.cli.output.handles._models import (
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
ActionHint,
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
CodeBlock,
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
DiffBlock,
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
ElementSnapshot,
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Panel,
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
ProgressIndicator,
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Separator,
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
StatusMessage,
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Table,
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
TextBlock,
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Tree,
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
TreeNode,
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
)
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
# ---------------------------------------------------------------------------
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
# Rendering helpers
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
# ---------------------------------------------------------------------------
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
def _render_panel(element: Panel) -> str:
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
"""Render a Panel element as plain text."""
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
lines: list[str] = [f"-- {element.title} --"]
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
for entry in element.entries:
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
icon_prefix = f"{entry.icon} " if entry.icon else ""
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
lines.append(f" {icon_prefix}{entry.key}: {entry.value}")
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
return "\n".join(lines)
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
def _render_table(element: Table) -> str:
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
"""Render a Table element as plain text."""
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
lines: list[str] = []
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
if element.title:
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
lines.append(f"-- {element.title} --")
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
if element.columns:
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
header = " | ".join(col.name for col in element.columns)
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
lines.append(header)
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
lines.append("-" * len(header))
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
for row in element.rows:
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
if element.columns:
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
cells = [str(row.get(col.name, "")) for col in element.columns]
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
else:
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
cells = [str(v) for v in row.values()]
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
lines.append(" | ".join(cells))
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
if element.summary:
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
lines.append(f"Summary: {element.summary}")
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
return "\n".join(lines)
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
def _render_status(element: StatusMessage) -> str:
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
"""Render a StatusMessage element as plain text."""
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
level_icons: dict[str, str] = {
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
"ok": "[ok]",
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
"info": "[info]",
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
"warn": "[warn]",
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
"error": "[error]",
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
}
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
icon = level_icons.get(element.level, "[*]")
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
text = f"{icon} {element.message}"
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
if element.detail:
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
text += f"\n {element.detail}"
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
return text
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
def _render_progress(element: ProgressIndicator) -> str:
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
"""Render a ProgressIndicator element as plain text."""
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
if element.indeterminate:
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
return f"[...] {element.label}"
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
if element.total is not None and element.total > 0 and element.current is not None:
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
pct = int(element.current / element.total * 100)
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
bar_width = 20
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
filled = int(bar_width * element.current / element.total)
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
bar = "#" * filled + "." * (bar_width - filled)
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
return f"{element.label} [{bar}] {pct}%"
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
if element.steps:
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
lines = [f"{element.label}:"]
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
step_icons: dict[str, str] = {
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
"done": "[done]",
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
"running": "[run]",
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
"pending": "[wait]",
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
}
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
for step in element.steps:
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
status_icon = step_icons.get(step.status, "[*]")
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
lines.append(f" {status_icon} {step.label}")
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
return "\n".join(lines)
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
return f"[...] {element.label}"
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
def _render_tree(element: Tree) -> str:
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
"""Render a Tree element as plain text."""
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
lines: list[str] = []
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
def _render_node(node: TreeNode, prefix: str, is_last: bool) -> None:
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
connector = "L-- " if is_last else "+-- "
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
lines.append(f"{prefix}{connector}{node.label}")
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
child_prefix = prefix + (" " if is_last else "| ")
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
for i, child in enumerate(node.children):
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
_render_node(child, child_prefix, i == len(node.children) - 1)
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
root = element.root
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
lines.append(root.label)
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
for i, child in enumerate(root.children):
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
_render_node(child, "", i == len(root.children) - 1)
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
return "\n".join(lines)
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
def _render_code(element: CodeBlock) -> str:
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
"""Render a CodeBlock element as plain text."""
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
lang_hint = element.language or ""
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
header = f"```{lang_hint}"
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
footer = "```"
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
return f"{header}\n{element.content}\n{footer}"
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
def _render_diff(element: DiffBlock) -> str:
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
"""Render a DiffBlock element as plain text."""
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
lines: list[str] = []
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
if element.file_a or element.file_b:
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
lines.append(f"--- {element.file_a or '/dev/null'}")
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
lines.append(f"+++ {element.file_b or '/dev/null'}")
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
for hunk in element.hunks:
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
lines.append(hunk.header)
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
for diff_line in hunk.lines:
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
prefix = {"add": "+", "remove": "-", "context": " "}.get(
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
diff_line.line_type, " "
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
)
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
lines.append(f"{prefix}{diff_line.content}")
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
return "\n".join(lines)
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
def _render_separator(element: Separator) -> str:
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
"""Render a Separator element as plain text."""
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
if element.style == "blank":
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
return ""
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
if element.style == "double":
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
return "=" * 40
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
return "-" * 40
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
def _render_action_hint(element: ActionHint) -> str:
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
"""Render an ActionHint element as plain text."""
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
lines: list[str] = []
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
if element.description:
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
lines.append(element.description)
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
for cmd in element.commands:
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
lines.append(f" $ {cmd}")
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
return "\n".join(lines)
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
def _render_text(element: TextBlock) -> str:
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
"""Render a TextBlock element as plain text."""
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
if element.indent > 0:
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
indent_str = " " * element.indent
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
return "\n".join(indent_str + line for line in element.content.splitlines())
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
return element.content
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
def render_element_for_tui(element: ElementSnapshot) -> str:
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
"""Render any element snapshot to a plain-text string for TUI display.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
This is the TUI equivalent of ``render_element_plain`` from the CLI
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
output framework, adapted for Textual widget display.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Args:
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
element: The element snapshot to render.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Returns:
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
A plain-text string suitable for display in a Textual Static widget.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
"""
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
if isinstance(element, Panel):
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
return _render_panel(element)
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
if isinstance(element, Table):
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
return _render_table(element)
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
if isinstance(element, StatusMessage):
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
return _render_status(element)
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
if isinstance(element, ProgressIndicator):
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
return _render_progress(element)
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
if isinstance(element, Tree):
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
return _render_tree(element)
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
if isinstance(element, CodeBlock):
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
return _render_code(element)
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
if isinstance(element, DiffBlock):
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
return _render_diff(element)
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
if isinstance(element, Separator):
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
return _render_separator(element)
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
if isinstance(element, ActionHint):
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
return _render_action_hint(element)
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
if isinstance(element, TextBlock):
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
return _render_text(element)
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
return str(element) # pragma: no cover
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
__all__ = [
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
"render_element_for_tui",
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
]
Review

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.

BLOCKING: # type: ignore[union-attr] violates zero-tolerance for inline type suppression (CONTRIBUTING.md). The _render_node recursive calls on lines 93, 95, 96 each use # type: ignore. Per CONTRIBUTING.pyright strict must pass with NO suppressions. Fix by providing proper typing for the node parameter instead of suppressing.
File diff suppressed because it is too large Load Diff
+22
View File
@@ -261,6 +261,15 @@ ColumnDef # noqa: B018, F821
StatusMessage # noqa: B018, F821
ProgressIndicator # noqa: B018, F821
ProgressStep # noqa: B018, F821
TreeNode # noqa: B018, F821
Tree # noqa: B018, F821
TextBlock # noqa: B018, F821
CodeBlock # noqa: B018, F821
DiffLine # noqa: B018, F821
DiffHunk # noqa: B018, F821
DiffBlock # noqa: B018, F821
Separator # noqa: B018, F821
ActionHint # noqa: B018, F821
LiveMaterializationStrategy # noqa: B018, F821
MaterializationStrategy # noqa: B018, F821
RichMaterializer # noqa: B018, F821
@@ -292,6 +301,19 @@ _snapshot_to_dict # noqa: B018, F821
_create_strategy # noqa: B018, F821
VALID_FORMATS # noqa: B018, F821
# TUI materializer — bridges Output Rendering Framework to Textual widgets
TuiMaterializer # noqa: B018, F821
TuiWidgetEvent # noqa: B018, F821
TuiWidgetEventType # noqa: B018, F821
render_element_for_tui # noqa: B018, F821
# TUI companion modules (split to keep materializer.py < 500 lines)
_tui_events # noqa: B018, F821
_tui_renderers # noqa: B018, F821
# TUI thought block widget — muted expandable actor reasoning trace
ThoughtBlockWidget # noqa: B018, F821
# Plan apply service — public API for diff/artifacts/apply integration (D0b.apply)
PlanApplyService # noqa: B018, F821
_render_diff_plain # noqa: B018, F821