What REA Actually Knows

The central question in REA is not whether a tool returned an answer, but what that answer entitles an investigator to claim. A native decompiler, JavaScript graph, managed-code parser, or process capture can all produce useful material, yet each observes a different part of the target under different conditions. This chapter explains how REA keeps those differences visible. The practical result is a reading discipline: identify the target and producer, separate observation from interpretation, and treat incomplete coverage as a boundary on the claim rather than as an invitation to guess.

What travels with a result

A reverse-engineering result without context is easy to overread. “This function calls a database routine” sounds precise, but the statement leaves several questions unanswered. Which file was inspected? Which architecture and provider produced the result? Was the call direct, inferred, or merely a candidate? Did the analysis cover the relevant code? Was the result taken from static bytes or from an observed run? Could another engine or profile have produced a different representation?

REA’s Evidence model is designed to keep those questions attached to the result. Evidence-producing MCP tools return the ordinary result together with an Evidence ID and the complete canonical Evidence record. That record is also retained in the session ledger so a later trace or comparison can use the same material without silently rerunning the original producer. The record carries the identity of the artifact or target, the provider and locations involved, the authority under which the result was obtained, confidence, coverage, limitations, and normalized result data.

This is more than metadata around a payload. It determines whether the payload can be reused. If a result refers to an authenticated application graph, a later feature trace can operate on that graph rather than rereading a mutable directory. If two captures are compared, the comparison can check that their scenario and normalization commitments are compatible. If a native observation comes from one selected deep provider, its provenance remains that provider’s, even when an application workflow presents the result through a common interface.

The model also separates the identity of the thing observed from the meaning assigned to it. A file digest, address, metadata row, or captured event is evidence about a particular artifact or run. A relationship derived from several such observations is a further claim. A source-like reconstruction is another layer again. Keeping those layers distinct makes it possible to ask whether a conclusion survived a change of build, provider, target, or observation window instead of relying on a familiar name or plausible-looking text.

A useful REA result should therefore answer four questions:

  1. What was examined? The target, artifact, component, address, module, page, process, or scenario must be identifiable.
  2. Who produced the observation? The provider, version, and relevant analysis context determine what kind of authority the result has.
  3. What was actually found? The result should expose the observed value, relationship, or event rather than forcing an agent to dereference an opaque record.
  4. What limits the finding? Coverage, ambiguity, truncation, unsupported forms, timing, and cleanup conditions belong to the answer when they affect interpretation.

These questions are especially important when different providers answer related questions. A native provider may return pseudocode, while an artifact reader may identify a resource and a browser observer may record a page event. A shared result shape makes them composable, but it does not make their observations interchangeable. Provider-neutral contracts are useful precisely because they can express common identity and evidence fields while preserving facet-level unavailability and provider-specific limitations.

flowchart LR F["Target-bound fact"] --> E["Evidence record"] I["Derived relationship"] --> E U["Unknown or unavailable facet"] --> E E --> C["Reader-facing claim"] C -.-> L["Claim boundary"] L -.-> U

The diagram’s important direction is not simply from data to conclusion. A claim also points back to the boundary that qualifies it. If a relationship was inferred from static structure, that authority remains visible. If an event came from a bounded capture, the observation window remains relevant. If a facet was unavailable, the final claim cannot honestly imply that the facet was checked and found absent.

Observation is not inference

The distinction becomes clearer when the same question is approached through different target families. Native analysis can establish that bytes decode as particular instructions, that a named or unnamed procedure contains a reference, or that a call target is direct, resolved-indirect, ambiguous, or unresolved. Those are observations about the analyzed representation. A workflow may then infer a possible route from a feature clue through those relationships. The route is useful, but it is not automatically evidence that a user executed it.

The same boundary appears in JavaScript analysis. REA can recover a structural graph and a separate semantic relation graph from an application directory or ASAR. A literal string, route, IPC channel, module, or native export can seed a trace. The graph may contain a unique statically resolved call or a relationship between an event registration and a handler. In REA’s terminology, “resolved” means that the static target was unique within the admitted analysis. It does not mean the target ran. Dynamic names, computed properties, unsupported mutation channels, duplicate fingerprints, and parser recovery can leave the real path uncertain.

Managed-code analysis makes the layers even more visible because readable reconstruction is tempting. REA reads PE/CLI metadata and CIL without loading or executing the assembly. It can identify members, compare builds, inspect declared native boundaries, and import decompiler output as analyst inference when the relevant static identities are verified. But a decompiled C# method is still a source-like representation of cited observations, not the original source. A metadata token is a precise coordinate within one build, not a durable cross-build identity. A digest over a decoded instruction tuple can support structural comparison, but it is not a complete semantic proof.

A process capture has a different authority again. It can observe the terminal behavior, scheduled interactions, exit reason, sampled process tree, settlement, and selected before-and-after filesystem state of a declared run. That is an observation of the run under its scenario and permissions. It is not a syscall trace, and it does not prove which internal method produced a result. If a capture shows that two commands ended with similar terminal output, that similarity can be useful; it does not by itself establish that every hidden dependency or short-lived descendant behaved identically.

These distinctions prevent a common failure in agent-assisted analysis: allowing a derived label to become the premise for the next step without preserving how it was derived. An agent might summarize a static graph as “the application uses this path,” then build a feature around an execution claim that was never observed. Or it might describe a decompiler’s guessed name as if the binary contained that semantic concept. REA’s contract model pushes in the opposite direction. An important relationship should carry the observations that support it, and unresolved alternatives should remain visible.

This does not make inference useless. Inference is how reverse engineering becomes understanding. The point is to label it accurately so that its confidence and next verification step can be chosen intelligently. A static call graph may be enough to decide which routine deserves closer inspection. A managed member comparison may identify a strong cross-build candidate. A browser capture may show that a page emitted a particular request during a selected observation window. Each can guide the next experiment or implementation decision without pretending to answer a stronger question than it does.

Unknown is a result, not an empty space

REA treats missing evidence as unknown rather than as an empty result or a negative fact. That rule is easy to state and difficult to maintain because software analysis often produces convincing partial views. A parser may cover all admitted nodes while dynamic behavior remains outside its scope. A browser observer may attach after earlier activity has already happened. A process snapshot may miss a short-lived file change between its before and after observations. A native analysis may not resolve an indirect target. A comparison may have one-sided coverage that is insufficient to establish removal.

Consider a version comparison. If an entity appears only on one side, the natural temptation is to call it added or removed. REA’s application-graph comparison uses those labels only when the opposite inventory has complete coverage. With partial, unavailable, or truncated input, the same absence becomes unknown. That is not pedantry. It distinguishes “the item was not present in a complete inventory” from “this particular observation did not expose it.” The first can support a bounded change claim; the second cannot.

Coverage has several dimensions. There is the coverage of the input itself: which files, frames, modules, or target components were admitted. There is the coverage of the producer: which structures, fields, bodies, or events the provider could decode. There is the coverage of time: which events occurred after attachment or within a capture window. There is also the coverage of interpretation: whether a relationship was uniquely resolved, ambiguous, inferred, or unsupported. A result may be complete within one dimension and limited in another.

That is why words such as complete, partial, truncated, unavailable, and unknown should not be treated as interchangeable warnings. A complete static graph can still contain unresolved dynamic edges. A partial extraction can still contain verified sibling files and hashes. An unavailable provider can leave an artifact identity intact while preventing a deep operation. A cleanup-incomplete outcome can preserve the primary observation while warning that owned resources could not be fully verified. The right conclusion depends on which facet is incomplete and whether that facet is material to the question.

For an agent, explicit unknowns also create a better next action. If the missing fact is dynamic reachability, a static trace may need a separately authorized runtime observation. If the ambiguity comes from two candidate functions, more discriminating evidence may be required rather than a guessed tie-break. If a comparison is limited by truncated input, the appropriate response is to broaden or repair the capture, not to write a confident migration note. The system’s usefulness comes partly from making the gap actionable.

Why the distinction matters for building

The point of this evidence model is not to produce cautious prose for its own sake. It changes the quality of the code an agent writes after an investigation. A reconstruction built from observed facts can lock those facts into tests and isolate assumptions that still need confirmation. A reconstruction built from unmarked inference may bake a provider’s guess into an API, data model, or compatibility promise.

Suppose the available evidence shows a stable serialized field name, a unique static caller, and a process capture that records a particular output for one input. Those facts may justify reproducing the field, testing the caller’s apparent path, and matching the observed output under the same scenario. They do not automatically justify claiming that all inputs use that field, that the caller is always reached, or that the original application has no other implementation. The boundary tells the agent where to write a test and where to write an assumption.

The same discipline supports disagreement. Different providers may produce different pseudocode or coverage without one result being a simple replacement for the other. A static and runtime record may correlate without one proving the other’s causal explanation. A source-like reconstruction may be readable while the canonical bytes remain the stronger identity. REA’s model allows these records to coexist because it does not force every useful artifact into the same epistemic category.

The next practical question is how an agent moves among these categories without losing the thread. That requires more than an Evidence schema: it requires a workflow that starts with a feature question, chooses reusable actions, carries records into follow-ups, and keeps the authority of each step intact. REA’s value is realized when that workflow turns a result’s boundaries into the next investigation decision rather than hiding them in the background.

References