Skip to content

docs(evidence): correct S5 — the semver-parse survivor is an equivalent mutant, not a weak witness - #325

Merged
IanFrelinger merged 2 commits into
masterfrom
docs/s5-equivalent-mutant
Aug 16, 2026
Merged

docs(evidence): correct S5 — the semver-parse survivor is an equivalent mutant, not a weak witness#325
IanFrelinger merged 2 commits into
masterfrom
docs/s5-equivalent-mutant

Conversation

@IanFrelinger

Copy link
Copy Markdown
Owner

Corrects S5. The claim that semver-parse's mutation survivor was a weak witness was wrong, and running it down produced the more interesting result.

What the survivor actually is

Survivor ids are mutate-int-literal-{line} (AstMutationCatalog), so mutate-int-literal-41 is line 41 of the candidate:

if(version.Length>0)// catalog rewrites 0 => 2, giving: version.Length > 2

The original and the mutant differ only for inputs of length 1 or 2. No such input can be a valid semver: isValid is set only when corePart.Split('.') yields three parts that each pass IsValidNumericPart, and the sole length-≤2 string containing two dots is "..", whose parts are empty and rejected. On every input that distinguishes them, both return isValid=false, 0, 0, 0, "".

The guard is redundant. The mutant is semantically equivalent, so no witness case can ever kill it — and since CertificationGate rejects on EscapeRate > 0, this candidate could not have certified regardless of what was added to the witness or how many repair attempts it got.

BrickMutationEngine already discounts three classes of unkillable mutant — source-identical, non-compiling, and analyzer-dead. Semantic equivalence is a fourth that it does not model, and is undecidable in general.

This is the first time a dogfood campaign has caught the trust machinery being wrong rather than the proposer, which makes it the substantive finding of S5.

Knock-on correction to the repair claim

S5 said repair re-emission held at both sizes. It does not follow at 27B: 2 of that model's 4 repair attempts were semver-parse, where no edit could have helped — so identical re-emission there was the correct response, not a failure to read the feedback. That leaves text-slug as the only valid test at 27B, where it did edit once in two attempts. One objective is not a measurement, so this is now recorded as untested rather than answered.

The 7B evidence is unaffected and stands: qwen2.5-coder:7b re-emitted byte-identical source on 6/6 repair attempts across three objectives that all had genuine, fixable defects.

Docs only — no behaviour change. The gate fix, if any, is a separate decision: EscapeRate > 0 as a hard reject is unsound in the presence of equivalent mutants, but every remedy has real trade-offs.

…nt mutant, a gate soundness hole
Ran the survivor down instead of trusting the first reading. Survivor ids are
mutate-int-literal-{line}, so mutate-int-literal-41 is line 41 of the candidate,
'if (version.Length > 0)', and AstMutationCatalog rewrites 0 => 2. The original
and the mutant differ only for inputs of length 1 or 2, and no such input can be
a valid semver (isValid requires three dot-separated numeric parts; the only
length-<=2 string with two dots is '..', whose parts are empty). The mutant is
semantically equivalent, so NO witness case can kill it, and since
CertificationGate rejects on EscapeRate > 0 the candidate could never certify.
This reverses the earlier claim that the survivor was a weak witness. It is the
first time a campaign has caught the trust machinery being wrong rather than the
proposer. BrickMutationEngine already discounts source-identical, non-compiling
and analyzer-dead mutants; semantic equivalence is a fourth class it does not
model.
Consequently corrects the repair claim too: 2 of the 27B's 4 repair attempts were
semver-parse, where no edit could have helped, so identical re-emission there was
correct rather than a failure to read feedback. That leaves one objective at 27B,
which is not a measurement. The 7B evidence (byte-identical on 6/6, all genuine
defects) is unaffected.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@cursor

cursorBot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

…utant reproduces on a different candidate
Re-ran both proposers end to end with identical dials to test whether 2/5 vs 3/5
was a capability difference or a lucky draw. Every objective reproduced its exact
verdict and failure stage for both models, so the gap is real.
The mechanisms differ. qwen2.5-coder:7b is near-deterministic at temperature 0.2 -
4 of 5 candidates byte-identical across independent runs - so repeat runs at these
dials do not measure sampling variance, and S4's 'results swing between runs' is
not a property of the harness at 0.2. qwen3.8:27b is NOT deterministic (3 of 5
candidates differ) and reached identical verdicts anyway, which is the stronger
result.
The equivalent-mutant finding replicated on a structurally different candidate:
the second semver-parse proposal uses IndexOf + TryParseNumericPart rather than a
hand-rolled scan, and its survivor is mutate-int-literal-47,
'if (prereleaseIndex >= 0)' -> '>= 2'. Equivalent for the same class of reason -
the two differ only when '-' sits at index 0 or 1, and then the mutant's corePart
retains the '-' so TryParseNumericPart rejects it while the original's corePart is
too short to split into three parts; both return isValid=false with defaults.
Two independent candidates, two different redundant guards, both unkillable. This
is systematic: EscapeRate > 0 as a hard reject refuses correct implementations that
carry a redundant guard.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@IanFrelinger
IanFrelinger merged commit 25b5c77 into masterAug 16, 2026
3 checks passed
@IanFrelinger
IanFrelinger deleted the docs/s5-equivalent-mutant branch August 16, 2026 23:21
IanFrelinger pushed a commit that referenced this pull request Aug 17, 2026
….md stops citing a release that does not exist
CHANGELOG.md carried a single generic [Unreleased] block untouched by ~50
merges (119 conventional commits) since the file was added on 2026-08-13.
The block is now Keep-a-Changelog grouped (Added / Changed / Fixed /
Security) from `git log e668215..master`, with PR numbers where a change
landed as one PR, and names the wave-1/2 readiness PRs #325-#337. No version
is cut and the header sentence the docs/repo-map-refresh branch edits is
untouched.
SECURITY.md said "only the most recent release and master are supported"
while no release has been tagged; it now says master is the only supported
line until one is.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@IanFrelinger@PlzTouchGrass