Versioning policy¶
jzap's version applies to more than the jar. Four things are public contracts, and each has its own answer to "what happens when it changes".
The project model schema¶
The document a build-tool adapter hands the engine. It carries an explicit schemaVersion.
- Adding a field is not a breaking change. An older engine ignores it with a warning, which is deliberate: a tolerant reader that silently dropped a field the user meant to set would be worse than one that complains.
- Changing or removing a field increments
schemaVersion. An engine that does not recognise the version refuses to run and says which version it understands, rather than guessing at a document it may misread. - A plugin and an engine may therefore differ in version, which is the point: the engine version is configurable precisely so it can move independently.
The cache format¶
Plain text, with a format string in its first line.
- Any change to the format or to the meaning of a key changes the format string, and an older or newer file is discarded rather than misread. A cache that half-parses is worse than no cache.
- The header also carries the engine id and version, the mutator set, the filter set and the toolchain fingerprint. Any mismatch discards the file, because verdicts recorded under one of those say nothing about another.
- Cache files are not portable between machines with different JDKs. Bytecode differs between
javacversions and platforms; the toolchain fingerprint enforces this rather than trusting it.
Mutator ids¶
MATH, NEGATE_CONDITIONALS and the rest are public.
- They appear in mutant keys, which appear in the cache, in every report, and in the parity mapping against PIT. Renaming one is a breaking change: it invalidates caches and turns every mutant of that kind into an unexplained difference against the correctness oracle.
- Adding a mutator changes the default inventory and therefore scores. New mutators go in the default set only on a minor version, and the release notes say what the inventory change is.
Mutant keys¶
class::method+descriptor::line::mutator#ordinal.
- Stable across recompilation when the enclosing method is unchanged. That is what makes the cache and the parity baseline work.
- Keys shift when a method's mutation points change, which includes adding a filter. That is why the enabled filter set is part of the cache key rather than a detail.
The daemon protocol¶
Not yet versioned. An incompatible daemon left running after an upgrade is not detected; stop it
with jzap daemon --stop after upgrading. This is a known gap rather than a design.
Version numbers¶
Ordinary semantic versioning, with the above as the definition of "breaking":
| Change | Version |
|---|---|
| Model schema version increment | major |
| Mutator id rename or removal | major |
| Mutator added to the default set | minor |
| Cache format change | minor (caches are discarded, not misread) |
| New filter, off by default | minor |
| Filter turned on by default | minor, with the inventory change in the notes |
| Bug fix that changes a verdict | patch, with the verdict change in the notes |
The last row is the awkward one and is stated deliberately: a fix that makes a wrong verdict right changes scores, and pretending otherwise would make every such fix look like a regression.