fix(ad): fix _build_bh_index returning dict[Any|None, Node]#177
Merged
Merged
Conversation
props.get("bh_id") returns Any|None, so the dict comprehension keyed
on it produced dict[Any|None, Node] despite the declared return type of
dict[str, Node]. The truthiness guard also silently excluded any node
with bh_id=0 (falsy but valid integer ID).
Replace the comprehension with an explicit loop that:
- Uses an is not None guard (preserves bh_id=0 nodes)
- Casts the key to str to satisfy the declared return type
Fixes PurpleAILAB#166
PurpleCHOIms
added a commit
that referenced
this pull request
May 12, 2026
Merge upstream main (48 commits behind) into the long-running benchmark branch so the OCI loop runs against the current Decepticon code, not a stale fork. Resolves a single conflict in ``decepticon/middleware/opplan.py`` introduced by upstream PR #184 (``Refactor middleware tools and harden OPPLAN persistence``), which moved the OPPLAN ``@tool`` definitions out of the middleware module and into the new ``decepticon/tools/opplan.py``. Resolution - Drop the duplicate ``@tool`` definitions on the benchmark side (~970 lines) — they now live behind ``build_opplan_tools(backend)`` in ``decepticon/tools/opplan.py``. - Preserve the benchmark-only recon-first guard in ``OPPLANMiddleware.after_model`` (added by 13ff3b3 / be918cf / 08a98eb / d211c4e) — intercepts ``task('exploit'|'postexploit', ...)`` dispatches when neither an OPPLAN recon objective nor on-disk evidence (``recon/SUMMARY.md`` or ``findings/FIND-*.md``) is present. - Re-add the ``from pathlib import Path`` import that the auto-merge dropped (now needed only by the surviving guard, since the file- writing tools moved out). Verification - ``uv run ruff check decepticon/middleware/opplan.py`` — clean - ``uv run ruff format --check decepticon/middleware/opplan.py`` — clean - ``uv run pytest tests/unit/middleware/test_opplan_hierarchy.py tests/unit/middleware/test_opplan_persistence.py`` — 34 passed - File shrinks from 1451 → 483 lines, diff vs origin/main is exactly the import line and the recon-first guard block. Other upstream changes (LiteLLM OAuth refactor #187, workspace_path reducer #183, launcher slug #182, research fix #176, AD index fix #177, LLM kwargs typing #179) merged automatically without conflict.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #166
_build_bh_indexindecepticon/tools/ad/bloodhound.pyused a dict comprehension keyed onn.props.get("bh_id"), which returnsAny | None. This produces adict[Any | None, Node]at runtime despite the declared return type ofdict[str, Node], and the truthiness guard silently drops any node whosebh_idis0(falsy but a valid integer ID).Changes
Replace the comprehension with an explicit loop that:
is not Noneguard instead of truthiness — preserves nodes withbh_id = 0str— satisfies the declared return type and ensures consistent lookup behaviour for callersTest plan
uv run ruff check decepticon/tools/ad/bloodhound.py— passesuv run basedpyright decepticon/tools/ad/bloodhound.py— 0 errorsuv run pytest tests/unit/ad/— 15/15 passed