Two moments in the life of a change: the edit, where somebody — human or agent — needs to know what a file touches, and the pull request, where the question is whether the architecture just changed shape. Both are answered from the same recovered model.
diff_impactHand it the changed file list (git diff --name-only does fine) and it returns the entities inside them, the recovered components they sit in, the transitive reverse-dependency closure up to max_depth hops, and the changed entities something outside the diff actually depends on.
arcade-arch-diffA CI job parses the branch, recovers its architecture, diffs it against the baseline committed in the repo, and posts the markdown report as a pull-request comment.
--update-baselineA second job re-runs the same recovery on the default branch and overwrites .arcade/baseline.json, so the baseline always describes what actually merged — versioned by git like any other file.
A captured diff_impact run against a shallow clone of pallets/click. The full run, the field-by-field return table and a second example are on the diff_impact page.
→ diff_impact(dep_graph="fe538dededcc",
changed_files=["src/click/exceptions.py"],
architecture="7abc279063c7", max_depth=2)
{
"changed_files": ["src/click/exceptions.py"],
"matched_files": ["src/click/exceptions.py"],
"unmatched_files": [],
"num_changed_entities": 35,
"changed_entities": [ /* 35 entities in click/exceptions.py */ ],
"affected_components": ["Exceptions"],
"downstream_dependents": [],
"num_downstream": 0,
"broken_contracts": []
}An empty downstream_dependents is an answer, not a failure: on this graph nothing imports or extends the changed entities. The signal is only as rich as the edges the parsers extracted — unmatched_files tells you which of your changed paths the graph didn't recognize at all.
The four fields that carry a review are:
affected_components — the recovered components the diff lands in. A one-line change spanning three components is worth a second look; it needs an architecture session to be populated at all.num_downstream / downstream_dependents — who transitively depends on the changed entities, each node carrying its distance and the via_relation it was reached through.broken_contracts — changed entities with incoming edges from outside the changed-file set: the part of the diff someone else is calling.unmatched_files — changed paths with no entity behind them; usually non-code files, sometimes a sign you parsed the wrong tree.For a version-to-version view rather than a file-set view, compare takes two recovered architectures and reports components added, removed, split or merged, matching them with the Hungarian algorithm — the same comparison arcade-arch-diff automates against the committed baseline.
It is a report, not a gate. arcade-arch-diff doesn't exit non-zero on drift, and arcade-self-analysis only exits non-zero when ingestion finds no source files at all. Nothing here fails your build unless you decide to make it — which is deliberate: architectural change isn't automatically wrong, it just shouldn't be invisible.
Two jobs in one workflow — a pull-request job that runs arcade-arch-diff --source . and upserts the report as a comment, and a push-to-default-branch job that runs the same command with --update-baseline and commits the result. The copy-paste workflow, the flag table and the exit-code notes are on the drift baseline in CI page; arcade-agent runs exactly this workflow on itself, and publishes the output as its self x-ray.
pip install "arcade-agent[languages,mcp]", point your MCP client at arcade-mcp, and run the first analysis — the getting-started page walks a real captured transcript end to end.