Track specification change
ess verify diff describes changes between two compiled models. ess verify impact follows their
dependencies to identify conformance scenarios owed another run and generated artifacts owed
regeneration. Neither command establishes that an earlier conformance result still holds.
Compare revisions
ess verify diff --from examples/revision-pair/before --to examples/revision-pair/after
ess verify diff --from examples/revision-pair/before --to examples/revision-pair/after --format json
The committed example pair changes currency variants, an entity invariant, an outcome condition and actor grants while also moving files and reordering declarations. The comparison uses the compiled models, so comments and source-file layout do not themselves produce changes.
The report follows these rules:
- Ten typed construct families are compared: system header, types, entities, commands, events,
errors, views, actors, components and bindings. Residual model changes outside those typed
comparisons produce
unclassified-changed; they are not silently treated as equality. - Every part of a command outcome is compared on its own, one change per outcome.
ess-diff/12adds the kinds for an error'spayload:sources (outcome-error-payload-added,outcome-error-payload-removed,outcome-error-payload-changed),accepts: nothing(outcome-accepts-nothing-changed),returns:(outcome-returns-changed) and a refusal the caller decides (outcome-decided-by-caller-changed). - Changes carry stable content-derived ids and a relation: widening, narrowing or changed. Predicate comparison uses canonical equality, not a proof that one predicate implies another.
- Renames are not inferred. A removed declaration and an added declaration remain two changes.
- Inputs must describe revisions of the same system. A different system identity is refused.
--format accepts text or json. JSON output is ess-diff/2, as it is for this pair,
unless the delta carries a change kind introduced later; it then takes the newest version any of its
changes needs, up to ess-diff/12 (see the
format history). The
library retains the frozen /1 vocabulary and reader support; explicit legacy writing refuses
changes outside that vocabulary. The endpoint digests identify compact compiled models, not raw YAML
or the pretty JSON shown by ess specify compile.
Delta writer,
comparison.
Fail on a breaking change
A relation says which way a set moved, not who is broken by it. --compatibility classifies each
change for three readers of the model: callers written against --from invoking --to,
readers written against --from reading what --to produces, and history, --to reading
the entity state and events --from already wrote. Each answer is compatible, unknown or
breaking, and the change's verdict is the worst of the three.
ess verify diff --from before --to after --compatibility
ess verify diff --from before --to after --fail-on breaking
ess verify diff --from before --to after --fail-on breaking --acknowledgements reviewed.json
- A type change is read through where the type is used, nested inside structs, newtypes, unions,
lists, maps or optionals: a command input or view parameter is an
input, a response, event, error or view row anoutput, an entity field or event astoredvalue. A component setting and an external channel's or periodic host's context fields areinputtoo. A removed variant breaks callers and history and no reader; an added variant breaks readers of an output and nobody else. Any other mention of the type isunmodelled: a change to the type, other than documentation or adding or removing it, is thenunknownin every dimension. - A grant or command removed breaks callers, a view removed breaks readers, an event or entity removed breaks history. Additions and display-name, summary or example changes are compatible.
- Everything else, such as a wire rename, an added field or a predicate rewrite, is
unknown: the answer depends on how consumers treat it, and the model does not say.
--fail-on breaking exits 4 when an unacknowledged change is breaking in a considered
dimension; --fail-on breaking-or-unknown also fails on unknown. --dimension callers (repeatable)
limits the dimensions considered. Without --compatibility or --fail-on, the output and the exit
status are unchanged. With either, JSON output is ess-diff/14, and every change carries
compatibility.
An acknowledgements file lets reviewed changes pass. It is bound to the exact pair compared: take both digests from the delta, and list change ids from it.
{
"format": "ess-diff-acknowledgements/1",
"before": "<before.spec_digest>",
"after": "<after.spec_digest>",
"acknowledged": ["type/demo.calls.Channel/variant-removed/Chat"]
}
A file naming other digests, an id the delta does not hold or an id twice is refused with exit 1. Classification and gate.
Find the work owed again
Without --suite, impact reports construct dependencies and generated-artifact obligations:
ess verify impact --from examples/revision-pair/before --to examples/revision-pair/after
To include scenarios, supply a suite for the before revision. For example, generate one from the committed pair and then compare:
ess verify conform synthesize --path examples/revision-pair/before --out before-suite.json
ess verify impact --from examples/revision-pair/before --to examples/revision-pair/after \
--suite before-suite.json
The report starts with the delta and explains each reached construct, scenario and artifact.
A scenario about a price list can be affected by a currency change through the price list's money
field. The dependency path explains why it is owed even when the scenario does not mention the
currency type directly. Adding --format json writes ess-impact/3, with its embedded /2
delta and current dependency-relation vocabulary.
Impact implementation,
dependency graph.
The CLI computes artifact obligations from the generators' output for the compared models. It
does not read your committed generated directory, and there is no --generated CLI option.
Library callers can supply a GeneratedTree to ess_diff::impact for the separate committed-stamp
check. An unreadable, mismatching or obsolete slice-profile claim then owes regeneration. A command
that runs without that input has not performed that check.
CLI entry point.
When narrowing is unavailable
| Situation | Result |
|---|---|
| A system-wide change has no construct from which to start a dependency walk | Whole obligations apply. |
| Residual model content changes outside the typed comparisons | unclassified-changed makes whole obligations apply. |
| A scenario or artifact depends on a construct absent from both dependency graphs | The answer stays whole rather than silently omitting that dependency. |
| The supplied suite belongs to another system or does not match the before model/contract digest | The comparison is refused. |
More columns: swipe horizontally, or focus the table and use the arrow keys.
An item absent from the narrowed answer was not reached by this analysis. That is not a claim that its prior evidence remains valid or that the suite has complete coverage. Suite/4 carries model and whole-contract identities; it does not carry an exact digest of the complete suite bytes.
Design documents, runbooks and prose references outside the compiled model are not part of the dependency walk. Their owner must track their freshness separately.
See Formats and digests for current version markers, reader boundaries and the distinct compiled-model, whole-contract and sliced-contract digest profiles.