Exploit-Strategy Subtree Collapse: Five Simulator Nodes → EvaluateExploitStrategy
Implemented by issue #1309 (task/1309-evaluate-exploit-strategy).
Context and Problem Statement
The simulator BT for exploit acquisition (AcquireExploit) encodes a single
policy-driven question — "should we acquire an exploit for this vulnerability?"
— as a sequence of five granular nodes: HaveExploit (Retriever), ExploitPrioritySet
(ProtocolInternal flag check), EvaluateExploitPriority (Evaluator), ExploitDeferred
(ProtocolInternal), ExploitDesired (ProtocolInternal). In production this granularity
is unnecessary: the BT needs a structured decision, not a flag-by-flag reconstruction
of what would have been one deliberate evaluation.
How should the five simulator nodes collapse in the production BT?
Decision Drivers
- Minimize the number of external call-out point seams for what is conceptually a single evaluation
- Keep individual seams independently swappable (Retriever-feeds-Evaluator pattern)
- Produce a typed, structured output that downstream BT nodes can read directly
Considered Options
- Single
EvaluateExploitStrategyEvaluator (queries exploit repo internally) HaveExploitRetriever feedsEvaluateExploitStrategyEvaluator (two seams)- Keep all five nodes (no collapse)
Decision Outcome
Chosen option: Option 2 — HaveExploit Retriever feeds EvaluateExploitStrategy
Evaluator. The exploit-repo query is kept as a separate Retriever seam (independently
swappable) while collapsing the three ProtocolInternal flag nodes into the Evaluator's
output record. The exploit-repo query is a distinct
external data dependency from the strategy evaluation; keeping them as separate
injection seams allows callers to swap only the repository query (e.g., to a
different threat-intel platform) without touching the evaluation logic, and
vice versa. Collapsing to a single Evaluator (Option 1) would force the
Evaluator implementation to embed the repository query, reducing composability.
Consequences
- Good, because the three ProtocolInternal flag nodes (
ExploitPrioritySet,ExploitDeferred,ExploitDesired) disappear as separate BT leaves — they become internal decision reads on the Evaluator's output record - Good, because
EvaluateExploitStrategyhas a clean typed output contract - Neutral, because retaining
HaveExploitas a Retriever means two call-out points remain instead of one; this is acceptable given the independent swapability benefit
More Information
- Planning issue: #1200; implementation issue: #1309
- Simulator nodes:
HaveExploit,ExploitPrioritySet,EvaluateExploitPriority,ExploitDeferred,ExploitDesired(seenotes/bt-fuzzer-nodes-report-management.md§ "Exploit Acquisition" and "Production Collapse 1") - Output schema:
ExploitStrategyDecision(have_exploit, acquire, rationale)(Pydantic BaseModel) invultron/core/behaviors/report/acquire_exploit_strategy_tree.py - Fuzzer backend:
EvaluateExploitStrategyinvultron/demo/fuzzer/report_management/acquire_exploit.py
Generated spec requirements: behavior-tree-integration.yaml BT-20-001