diff --git a/CHANGELOG.md b/CHANGELOG.md index c472412de..bdea20376 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,6 +53,7 @@ Changed `wf10_batch.robot` to be less likely to create files, and `final_validation_results` fields on the result model, DI container ## [Unreleased] +- **fix(tui): rename ActorSelectionOverlay._render to _refresh_display (issue #11039)** — `ActorSelectionOverlay._render()` shadows Textual's `Widget._render()` which must return a `Strip`. In textual >=1.0, layout calls `get_content_height()` `self._render()` gets `None` `AttributeError: 'NoneType' object has no attribute 'get_height'`. Renamed the method to `_refresh_display()` and updated all four internal call sites (`show()`, `move_up()`, `move_down()`, `set_search()`) to use the new name. - **Structural Component Output Validation** (#8164): Replaces exact character matching with structural component checking for output validation. Implements three validators covering plan tree output, decision CLI dicts, and structured session snapshots. The `validate_plan_tree` function validates node dicts for required keys (`decision_id`, `type`, `sequence`, `question`, `children`), ULID format, correct types, and sibling ordering. The `validate_decision_dict` function validates decision CLI output against the `Decision.as_cli_dict()` schema with field presence, type, ULID pattern, confidence range [0..1], and boolean field checks. The `validate_structured_output` function validates the StructuredOutput envelope for `command`, `session_id` (ULID), status membership, `exit_code`, and elements integrity. A unified dispatcher (`validate_structured_component_output`) enables routing by target_type. BDD test coverage added in `features/structural_validation.feature`. [Epic #8137](https://git.cleverthis.com/cleveragents/cleveragents-core/issues/8137) - **Fixed `agents actor add --config` crash with nested `actors:` map and `config.actor` combined shorthand** (#11189): The diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index bf1d924b9..e97eb3f11 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -45,3 +45,4 @@ Below are some of the specific details of various contributions. * HAL 9000 has contributed the agents plan rollback command (PR #8674 / issue #8557): implemented checkpoint-based plan state restoration with the `agents plan rollback []` CLI command as part of Epic #8493, enabling plans to be restored to previous checkpoints, discarding post-checkpoint decisions, and resuming execution from the rolled-back state. Supported by `--yes/-y`, `--to-checkpoint`, and `--format/-f` flags. Includes comprehensive BDD test coverage (>= 97%) for rollback, decision discarding, and plan resume functionality. * HAL 9000 has contributed the PyYAML security upgrade (PR #11012 / issue #9055): added `pyyaml>=6.0.3` dependency constraint to address known YAML parsing vulnerabilities. * HAL 9000 has contributed the A2A module rename standardization BDD tests (PR #10583 / issue #8615): comprehensive Behave test suite validating that all 22 A2A symbols are properly exported from `cleveragents.a2a`, no legacy ACP references remain in the module source, and documentation uses correct A2A naming conventions — fixing inline imports, unused behave symbols, cross-scenario context dependencies, and missing type annotations. +* HAL 9000 has contributed the `ActorSelectionOverlay._render` → `_refresh_display` rename fix (PR #11176 / issue #11039, Epic #8174): renamed `_render()` method to `_refresh_display()` to avoid shadowing Textual's `Widget._render()`, fixing a crash in textual >=1.0 where `get_content_height()` would receive `None` and raise `AttributeError: 'NoneType' object has no attribute 'get_height'`. diff --git a/src/cleveragents/tui/widgets/actor_selection_overlay.py b/src/cleveragents/tui/widgets/actor_selection_overlay.py index d515924d8..fd27c1b3d 100644 --- a/src/cleveragents/tui/widgets/actor_selection_overlay.py +++ b/src/cleveragents/tui/widgets/actor_selection_overlay.py @@ -145,7 +145,7 @@ class ActorSelectionOverlay(_StaticBase): self._confirmed = False self._selected_actor = None self._visible = True - self._render() + self._refresh_display() def hide(self) -> None: """Hide the overlay and clear its content.""" @@ -161,14 +161,14 @@ class ActorSelectionOverlay(_StaticBase): if not self._filtered_actors: return self._selected_index = (self._selected_index - 1) % len(self._filtered_actors) - self._render() + self._refresh_display() def move_down(self) -> None: """Move the selection cursor down by one position (wraps).""" if not self._filtered_actors: return self._selected_index = (self._selected_index + 1) % len(self._filtered_actors) - self._render() + self._refresh_display() # ------------------------------------------------------------------ # Search / filter @@ -191,7 +191,7 @@ class ActorSelectionOverlay(_StaticBase): else: self._filtered_actors = list(self._actors) self._selected_index = 0 - self._render() + self._refresh_display() # ------------------------------------------------------------------ # Confirmation @@ -215,10 +215,10 @@ class ActorSelectionOverlay(_StaticBase): return actor # ------------------------------------------------------------------ - # Internal rendering + # Internal display refresh # ------------------------------------------------------------------ - def _render(self) -> None: + def _refresh_display(self) -> None: content = render_actor_selection( self._filtered_actors, self._selected_index,