Why Provider Choice Must Be Deterministic
When several engines can inspect the same binary, provider choice becomes part of the meaning of the result. REA treats this as a reproducibility problem, not a convenience preference. This chapter explains how request, environment, and automatic selectors are resolved; why ambiguity is reported instead of guessed through order or startup speed; and how a target remains bound to one provider and analysis profile through success, delay, failure, and recovery.
The danger of “whichever works first”
Suppose Hopper and Ghidra are both installed and both can analyze a native target. A naïve system could put their adapters in a list and use the first matching operation. That looks convenient until the list order changes. A different installation may then produce a different procedure inventory or pseudocode for the same target without any explicit decision by the caller.
Racing providers is not a better solution. The winner would depend on machine load, startup timing, storage, or a transient health response. It would also start analysis engines the operator did not select. Falling back after a provider error creates a deeper problem: one apparent session could first record observations from one engine and then continue with another whose analysis model, defaults, or unresolved relationships differ. The resulting Evidence would be difficult to interpret because the producer boundary had moved without a visible transition.
REA’s provider registry rejects those hidden policies. It discovers deep candidates, checks local availability, evaluates target support when a target is known, and resolves a provider-owned analysis profile before creating the deep client. Candidate order is deterministic for reporting, but it is not a priority rule. The product does not prefer the first registration, the fastest startup, or a particular engine merely because it is familiar.
Automatic selection is therefore narrow by design. If exactly one deep candidate is usable, auto can select it. If more than one is usable, the result is an ambiguity that names the candidates and asks the caller to choose. If no deep candidate is usable, an automatic open may still leave a target available for disjoint artifact or native operations, while deep operations explain why they are unavailable. A concrete provider request is stricter: if that provider cannot support the target or its options, REA fails rather than quietly changing the request.
This is a useful trade-off. A user may prefer an automatic system that always returns something, but “something” is not neutral when the producer changes the semantics of the result. REA spends a little convenience to preserve a stronger property: the investigator can explain why this engine produced this evidence.
The decision is also made at the right time. Candidate discovery can report configuration and declared capabilities without importing a target or starting a long-lived analysis process. Once a target is known, support is evaluated against its actual kind, format, architecture, and options. That prevents a provider’s presence on the host from being mistaken for a promise that it can answer the current question.