Commit d208856
fix(bulk): close review round-4's 6 blocking gaps plus 11 smaller findings
Blocking:
- Stop skipping scene entities in the operations-mode conflict gate: a
scene dispatch really does cascade into its configured entities
(scene.turn_on), unlike selector mode's aggregate-root question, which
is why that skip existed there in the first place. The two now answer
their own, different questions instead of sharing one wrong exemption.
- Split bulk_selector's empty-result gate into three causes instead of
two (empty aggregate / wrong-domain aggregate / hidden), each gated on
"nothing in the match set is hidden" -- a hidden entity elsewhere in
the same area no longer gets masked by an unrelated visible aggregate
expanding to the wrong domain.
- Fix the selector-only-parameter worked example rendering a duplicate
'action' key when action is itself the offending parameter.
- Cap the group-conflict message's member list at 10 (+N more) instead
of enumerating an instance-sized membership list in a fail-closed
error whose remedy sentence is the entire value of the response.
- Cover both _GroupConflict message branches with tests that would catch
the two fields being swapped (previously only the unlisted-members
branch was ever exercised).
Smaller:
- Bind topology fetch-failure labels directly to their named locals
instead of a position-zipped tuple, so a future reordered gather()
can't silently mislabel which registry failed.
- _operation_common needs hash=False, not just compare=True: the frozen
dataclass claimed to be hashable (mypy agreed) but raised at the first
real hash() call, since a dict has none.
- Give the args-too-deeply-nested fail-closed branch its own error code
(POLICY_ARGS_TOO_DEEPLY_NESTED) instead of reusing POLICY_LOAD_FAILED,
which already means a corrupt tool_policy.json -- a different failure
with a different, caller-shaped remedy.
- Log the dynamic pending-entry removal at INFO; it was the only silent
state transition on the approval queue, and a late Approve click on it
used to log as an "attacker probing tokens" WARNING for ordinary use.
- Restore actionable suggestions on the group-safety check's own
states-fetch failure, lost when the isinstance(states, list) guard was
removed -- otherwise the agent sees a raw client string with no hint
that the safety check itself is what failed.
- Deep-copy operation parameters (both the per-row and resolution-level
copies) instead of a shallow dict() that only stops top-level rebinding
and still shares nested values like an rgb_color list.
- Fix an inverted test docstring describing the guard it tests backwards.
- Assert expires_in_seconds is absent from the dynamic pending-error body,
not just that its message/suggestions text omits a countdown.
- Extend the topology multi-failure test to all five registries instead
of two, closing the remaining label-typo blind spot.
- E2E test: use safe_call_tool for cleanup (so a cleanup failure can't
mask a real assertion failure in finally), and discover real lights
dynamically instead of hardcoding demo-platform entity IDs.
Skipped: a CodeRabbit suggestion to replace the established
MCPAssertions.call_tool_failure helper (used across 13 e2e files) with a
manual safe_call_tool call in the new E2E test -- no functional benefit,
and goes against the repo's own convention. Also skipped narrowing
ServiceTools' client: Any typing (untested seam around a dict-shaped
get_states() response) -- reviewer confirmed this is not a live gap, and
the fix would mean a broader typing change across ServiceTools,
register_service_tools, and registry.py.
10722 unit tests pass (up from 10716 by exactly the 6 new tests added
here); the 26 remaining failures are the same pre-existing,
Windows-platform-only failures already present before this change.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>1 parent 527e813 commit d208856
8 files changed
Lines changed: 497 additions & 93 deletions
File tree
- src/ha_mcp
- policy
- tools
- tests/src
- e2e/workflows/core
- unit
- policy
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
100 | 100 | | |
101 | 101 | | |
102 | 102 | | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
103 | 113 | | |
104 | 114 | | |
105 | 115 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
154 | 154 | | |
155 | 155 | | |
156 | 156 | | |
157 | | - | |
| 157 | + | |
158 | 158 | | |
159 | 159 | | |
160 | 160 | | |
| |||
287 | 287 | | |
288 | 288 | | |
289 | 289 | | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
290 | 307 | | |
291 | 308 | | |
292 | 309 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
| 6 | + | |
6 | 7 | | |
7 | 8 | | |
8 | 9 | | |
| |||
121 | 122 | | |
122 | 123 | | |
123 | 124 | | |
124 | | - | |
125 | | - | |
126 | | - | |
127 | | - | |
128 | | - | |
129 | | - | |
130 | | - | |
131 | | - | |
132 | | - | |
133 | | - | |
134 | | - | |
135 | | - | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
136 | 144 | | |
137 | 145 | | |
138 | 146 | | |
| |||
149 | 157 | | |
150 | 158 | | |
151 | 159 | | |
152 | | - | |
153 | | - | |
154 | | - | |
155 | | - | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
156 | 168 | | |
157 | 169 | | |
158 | 170 | | |
| |||
402 | 414 | | |
403 | 415 | | |
404 | 416 | | |
405 | | - | |
406 | | - | |
407 | | - | |
408 | | - | |
409 | | - | |
410 | | - | |
411 | | - | |
412 | | - | |
413 | | - | |
414 | 417 | | |
415 | 418 | | |
416 | 419 | | |
| |||
440 | 443 | | |
441 | 444 | | |
442 | 445 | | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
443 | 463 | | |
444 | 464 | | |
445 | | - | |
| 465 | + | |
446 | 466 | | |
447 | 467 | | |
448 | 468 | | |
| |||
474 | 494 | | |
475 | 495 | | |
476 | 496 | | |
477 | | - | |
| 497 | + | |
| 498 | + | |
| 499 | + | |
| 500 | + | |
| 501 | + | |
| 502 | + | |
| 503 | + | |
| 504 | + | |
| 505 | + | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
| 512 | + | |
478 | 513 | | |
479 | 514 | | |
480 | 515 | | |
| |||
728 | 763 | | |
729 | 764 | | |
730 | 765 | | |
731 | | - | |
| 766 | + | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
| 770 | + | |
| 771 | + | |
| 772 | + | |
| 773 | + | |
| 774 | + | |
| 775 | + | |
| 776 | + | |
| 777 | + | |
| 778 | + | |
| 779 | + | |
| 780 | + | |
| 781 | + | |
| 782 | + | |
| 783 | + | |
| 784 | + | |
| 785 | + | |
| 786 | + | |
| 787 | + | |
| 788 | + | |
| 789 | + | |
732 | 790 | | |
733 | 791 | | |
734 | 792 | | |
735 | 793 | | |
736 | 794 | | |
737 | 795 | | |
738 | 796 | | |
739 | | - | |
740 | | - | |
741 | | - | |
742 | | - | |
743 | | - | |
744 | | - | |
745 | | - | |
746 | | - | |
747 | 797 | | |
748 | 798 | | |
749 | 799 | | |
| |||
770 | 820 | | |
771 | 821 | | |
772 | 822 | | |
773 | | - | |
774 | | - | |
775 | | - | |
776 | | - | |
777 | | - | |
778 | | - | |
779 | | - | |
| 823 | + | |
| 824 | + | |
| 825 | + | |
| 826 | + | |
| 827 | + | |
| 828 | + | |
| 829 | + | |
| 830 | + | |
| 831 | + | |
| 832 | + | |
780 | 833 | | |
781 | 834 | | |
782 | 835 | | |
| |||
0 commit comments