Reading a semantic diff, line by line

What each section of tovio semantic diff output means.

Written By Dustin

Last updated About 3 hours ago

tovio semantic diff prints a small, fixed set of sections. Knowing which ones are verdicts and which are context makes the output much faster to act on.

The header

It opens with the two commits being compared, abbreviated. If either side has no symbol index, that is called out immediately — because a side with no index reads as empty, and without the note an unindexed base looks exactly like "you added everything".

Common reasons a side has no index: it predates the feature in that repository, it was committed by a build without the semantic layer, or it arrived on a partial clone whose symbol attachments were not fetched.

The breaking sections

  • Removed (breaking) — an exported symbol that no longer exists.
  • Changed (breaking) — an exported symbol whose interface moved. Each entry names the reason: signature, supertype, or signature + supertype. A supertype change also lists the specific supertypes that were dropped, which is usually the actionable detail.

The non-breaking section

  • Added — new exported symbols. Never breaking; listed so you can see the shape of the change.

The two advisory sections

These are kept separate on purpose, so they cannot be mistaken for interface breaks:

  • Dependencies changed — a symbol's signature held, but what it calls or references moved. Useful for spotting a rewritten implementation hiding inside an unchanged interface.
  • Test coverage changed — which tests exercise a symbol gained or lost an edge. Read "no longer covered by" as a prompt to check, not as proof a test was deleted.

Neither ever contributes to the breaking verdict.

The last line states the conclusion, and names exactly which axes moved — it will not claim a dependency shift when only coverage moved, or report "additions only" when advisory edges also changed. If the interface is genuinely unchanged and nothing advisory moved either, it says so in one line and stops.

Scripting it

tovio semantic diff --json

The JSON carries breaking as a boolean, plus added, removed, changed, dependency_deltas and coverage_deltas as arrays, and a_indexed / b_indexed so a script can tell "no changes" apart from "nothing was indexed". Gate on the breaking field — not on the exit code, which is 0 either way.

One shape to guard against: when there is nothing at all to compare, such as a freshly initialised repository with no commit, the output is the short form { "breaking": false, "note": … } and none of the other keys are present. Read every field but breaking defensively.

What it never contains

No source lines. Semantic findings are plaintext-free by design: monikers, reasons and counts only. That is what makes it safe to paste a semantic diff into a ticket when the underlying patch would not be.