tools(mutation-teeth): a misnamed tooth says so, and the ledger places the seven rules no row claimed - #73
Merged
Merged
Conversation
…of surviving A tooth names the case that must fail, and a sweep filters a suite by that name so one tooth costs one case instead of a whole suite. When the name matches no case, the filtered run passes with no case in it - and that pass was reported as a surviving mutant. The two are different defects: one is a rule nothing checks, the other is evidence whose name went stale. This is how two teeth were read as broken while they were only misnamed, and the tool had no way to say which had happened. - `ranACase` (tools/mutation-anchor.ts, pure, no filesystem) reads the run's own report: a marked line that is not the suite file is a case, a suite line alone means the filter matched nothing, and an unrecognized reporter answers unknown - a tooth is not accused on evidence the harness cannot parse. The suite file's own line is what makes the answer possible: it runs whatever the filter did. - The runner asks it before it believes a pass, reports the tooth as `misnamed` with the name it wanted, and counts it as a problem (non-zero exit). The whole-suite fallback is not run for it: the defect is the name, not the coverage. - `tests/tools/mutation-anchor.test.ts`: one case covering the file line alone, a matched case, a failed case, two suites where nothing matched, and the unknown reporter - 35 cases in the file now. - The record's own failure-mode note moves from "open" to answered, in the same commit. Measured: the whole register 110 of 110 caught by the named test, all 110 by the case each expect names, 22 of 22 targets restored byte-identically, exit 0 in 162 s - so the new check raises no false alarm anywhere in the register. A deliberately misnamed tooth reads `misnamed (no case in this target's suites is named "...")`, the file is restored byte-identically, and the run exits non-zero.
The retirement pass left seven teeth whose rules no row named. The reading was "a case but no row"; the rules themselves were recovered from the register before the retirement, each replacement case was located and its assertion read, and the answer is not seven new rows - most of these rules were already carried by a row that simply did not name the case: - `round-publication-opens-its-own-transaction` is B3's rule. Its replacement case lives in B3's own suite and asserts the transition's rollback for the publication half, saying in the assertion what the alternative would mean. Named in B3. - `round-never-releases-its-pin` is the other side of B4's retention rule. The case asserts the pins held while a round runs, then cancels and asserts the retention list is empty, because both kinds of pin go with the values they protected. Added to B4. - `ordered-mode-becomes-any-topological-order` had no row at all: the design's sentence about publication order had never been given one. It is A6 now, evidenced by the case that asserts the exact declared order, one ordered plan, and that the baseline never gains order freedom. Row counts: A 5 -> 6. - The four judge-loop rules are F2b-slot's and F2c's: the batch rule and the duplicated dispatch share one case, `a unit's check is outstanding while an independent unit's worker runs`, and the unit with no checks and the parent check are the two cases F2c's row now names. So the readings line no longer calls them orphans, and the record no longer leaves the question open - what remains open is only whether "a check but no row" is a defect at all, and here the defect was in the ledger rather than in the register. Both languages in this commit. Readings: `docs:check` 304 files, 0 errors, 0 warnings; `rtm:check` exit 0; `test:product` 1581 pass, 0 fail, exit 0.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes the two tails the derived-mutants arc left open, from
main(818228ae).1.
tools(mutation-teeth): anexpectthat names no case says soA tooth names the case that must fail, and the sweep filters a suite by that name so one tooth costs one case instead of a whole suite. When the name matches no case the filtered run passes with nothing in it, and that pass was reported as a surviving mutant - which is how two teeth were read as broken while they were only misnamed.
ranACase(tools/mutation-anchor.ts, pure, no filesystem) reads the run's own report: a marked line that is not the suite file is a case; a suite line alone means the filter matched nothing; an unrecognized reporter answers unknown, so a tooth is never accused on evidence the harness cannot parse. The suite file's own line is what makes the answer possible - it runs whatever the filter did.misnamedwith the name it wanted, counts it as a problem (non-zero exit), and skips the whole-suite fallback for it: the defect is the name, not the coverage.tests/tools/mutation-anchor.test.tsgained the case covering the file line alone, a matched case, a failed case, two suites where nothing matched, and the unknown reporter (35 cases in the file now).2.
docs(ledger): the seven rules no row claimed get one home eachThe retirement pass left seven teeth whose rules no row named. Each rule was recovered from the register before the retirement, each replacement case was located and its assertion read, and the answer is not seven new rows:
round-publication-opens-its-own-transactionround-never-releases-its-pinordered-mode-becomes-any-topological-orderthe-loop-awaits-each-unit-instead-of-the-batch,a-unit-is-dispatched-twice-in-one-batcha-unit-nothing-checks-is-still-a-unit,the-parent-check-ignores-its-own-verdictThe readings line no longer calls them orphans, and the record no longer leaves the question open: what remains open is only whether "a check but no row" is a defect at all - it was one here, but the defect was in the ledger, not in the register.
Verification
mutants: 110 of 110 caught by the named test, all 110 by the case eachexpectnames, 22 of 22 targets restored byte-identically, exit 0 in 162 s - i.e. the check raises no false alarm anywhere in the registermisnamed (no case in this target's suites is named "..."), the file is restored byte-identically, exit non-zeronpm run verify:staticexit 0;anchors: 110 of 110 resolve, over 22 targets;docs:check304 files, 0 errors, 0 warnings; lint 0 findings; complexity gate oknpm run test:product1581 pass, 0 fail, exit 0 (1580 + the new case)