inspect-artifact
inspect-artifact reads the file as a container, hashes it, names its format, and returns one Evidence record that tells you which tool to run next.
You built ledger-arm64-O1 from ledger.c and ledger-main.c with clang. An agent is about to analyze it, and you want the first call to be cheap, offline, and honest about what it did not do. inspect-artifact is that call. It needs no Ghidra, it returns in about a second, and its record ends with the name of the next tool.
When you finish this section, you can run inspect-artifact on a file you built and read its manifest and its one occurrence. You can also say why the record names open_binary as the next probe.
One command, one record
$ rea inspect-artifact fixtures/ledger-arm64-O1 --format json
[exit 0] (…) -> 03-inspect-artifact.jsonThe record comes from the provider rea-artifact-graph, named "REA safe artifact graph provider", version 1. No analysis engine runs. The tool opens the file, hashes it, names the format from the header, and builds an inventory of the file as a container.
Artifact graph: the inventory rea builds of one file and the files inside it. A node is one distinct content, identified by its SHA-256. An occurrence is one place where that content appears, with a logical path. An edge joins a container to a member.
{
"evidence_id": "ev_0e878985…",
"subject": {
"name": "ledger-arm64-O1",
"digest": {
"sha256": "01b5d08b…"
},
"local_path": "$CAPTURE/fixtures/ledger-arm64-O1",
"format": "mach-o",
"architecture": null
},
"provider": {
"id": "rea-artifact-graph",
"name": "REA safe artifact graph provider",
"version": "1"
},
…
"operation": "inspect_artifact",
"parameters": {
"integrity_policy": "fail"
},
…
}The SHA-256 is the one 00-fixtures.txt lists for the file, and every later record about this file carries the same digest. The format is mach-o, read from the magic bytes. The architecture is null. This provider does not read cputype, and the next section shows the tool that does. The one parameter is integrity_policy, set to fail.
The manifest and the occurrence
The record has one substep, inventory_artifact, with status: "completed" and its own Evidence record nested inside. Its manifest counts the graph.
"manifest": {
"manifest_id": "agm_8e2e5c4c…",
…
"graph_sha256": "b6c8ab6f…",
"node_count": 1,
"occurrence_count": 1,
"edge_count": 0
},
"nodes": [
{
"artifact_id": "art_8906b5a7…",
"format": "mach-o",
"sha256": "01b5d08b…",
"size": 33872,
…
"content_state": "materialized",
"limitations": []
}
],
"occurrences": [
{
"occurrence_id": "occ_35a9bb48…",
…
"logical_path": ".",
"entry_kind": "file",
"artifact_kind": "executable",
"artifact_format": "mach-o",
"declared_size": 33872,
…
"executable": true,
"encrypted": false,
"hash_status": "verified",
…
}
],One node, one occurrence, no edges. The executable is its own container and has no members. The limitation "Artifact has no child container entries." says the same in words. The node reports size: 33872, the byte count in 00-fixtures.txt, and content_state: "materialized". The occurrence has logical_path: ".", the root, and artifact_kind: "executable". For an .asar or a .zip, this is where every member file would appear with its own node and path.
Branches and the next probe
"unexplored_branches": [
{
"branch_id": "aib_ff20889e…",
"reason": "format-specific-analysis-required",
"detail": "open_binary was not run by provider-neutral artifact inspection.",
"next_probe": {
"operation": "open_binary",
"rationale": "Bind one deep native provider before function-level analysis.",
"authority": "native-analysis-provider"
},
…
}
],
…
"confidence": "observed",
"authority": "shipped-artifact",
"environment": null,
"limitations": [
"Artifact has no child container entries.",
"Inspection derives bounded static hypotheses and next probes; it does not execute the artifact or claim format-specific semantics."
],rea builds one unexplored branch for every next probe it lists, with the reason format-specific-analysis-required. The second limitation is a constant in the same file. The record is observed with authority shipped-artifact: rea read the bytes of the file you gave it and derived nothing from another record. The coverage block reports complete-within-substeps with one substep, one observation, one branch, one probe, and nothing omitted.
What the record is not
The record is not a format parse. It holds no load commands, no sections, no symbols, and no entry point. For those, the next section runs inspect-macho. For a function, Part 4 binds Ghidra with open_binary, the tool the branch names. The whole record is 198 lines, and most of them repeat the subject digest. That repetition is the point: every nested record can stand alone and still name the same bytes.
rea (rea-agents) with the Ghidra provider rea-agents 6.7.0, Ghidra 12.1.4 · 27dc42d · 2026-10-18 · Edition 2026.10