diff --git a/apps/website/src/data/blog/bodies/nobodys-example.ts b/apps/website/src/data/blog/bodies/nobodys-example.ts new file mode 100644 index 0000000000..361ff12a15 --- /dev/null +++ b/apps/website/src/data/blog/bodies/nobodys-example.ts @@ -0,0 +1,273 @@ +import type { Block } from '../types' + +export const body: Block[] = [ + { + "kind": "p", + "text": "A gate's negative control is written by someone who plants the fault it is meant to catch. That single sentence explains almost everything the boundary operator found." + }, + { + "kind": "p", + "text": "The mutation line is closed. Thirteen gates, four operators, 111 mutants, two survivors — and both survivors are proven equivalences that now carry the proof in the output beside them. What follows is not the score. It is the one structural fact the last operator exposed, which the first three could not." + }, + { + "kind": "h", + "text": "Four questions, not one" + }, + { + "kind": "p", + "text": "Each operator breaks a gate on purpose and asks whether the gate's own control notices. They differ in what they break." + }, + { + "kind": "ul", + "items": [ + "Silent — `return 1` becomes `return 0`. Can the gate still fail at all?", + "Loud — `return 0` becomes `return 1`. Does anything require it to be quiet?", + "Invert — `if C:` becomes `if not (C):` where the body carries a verdict. Does it reach the RIGHT verdict?", + "Boundary — `>` becomes `>=`, `<` becomes `<=`. Does it reach the verdict at the right PLACE?" + ] + }, + { + "kind": "p", + "text": "The first three found gaps and then stopped finding them: 36, 21 and 33 mutants, all killed. The fourth found twelve survivors on its first honest run, in five of thirteen gates, on a suite the other three had already scoured." + }, + { + "kind": "h", + "text": "Every one of them was a degenerate input" + }, + { + "kind": "p", + "text": "Six of those twelve closed in a single pass, and they rhymed. Each needed an input no existing case had a reason to build, and in each the missing input was the degenerate one." + }, + { + "kind": "table", + "head": ["the boundary", "the input nobody planted"], + "rows": [ + ["`v[0] > 0` in a census of prose-only files", "a file with **zero** cases"], + ["`total > 0 and data == 0` for a new file", "a **new** file with zero cases"], + ["`total == 0 and old[0] > 0`", "a file **already empty when the ledger was written**"], + ["`len(parts) > 1` parsing a ledger line", "a line with **no separator at all**"], + ["`len(fixed) > 5` guarding a continuation line", "**exactly five** repaired entries"], + ["`n_ssot < MIN_ROWS`, a floor", "**exactly** the floor"] + ] + }, + { + "kind": "p", + "text": "Nothing there is exotic. Every one is the kind of input a reader would call trivial, and that is precisely why none of them existed." + }, + { + "kind": "quote", + "text": "A control author plants the fault they are testing for, which is by construction a non-degenerate example: a file with the wrong contents, not a file with no contents." + }, + { + "kind": "p", + "text": "To test that a gate catches lost data, you write a file that lost data. To test that it catches an emptied file, you empty one. Both are examples OF something. The empty case, the equal case and the one-off-the-edge case are examples of nothing — they are the inputs that do not illustrate any fault, so no author reaches for them, so no control contains them, so every comparison in the gate is free to sit one place off and pass." + }, + { + "kind": "p", + "text": "That is the boundary operator's entire yield, and it is not a gap in anyone's diligence. It is a consequence of how controls are written." + }, + { + "kind": "h", + "text": "One of them would have cried wolf forever" + }, + { + "kind": "p", + "text": "The third row deserves its own paragraph, because it is the one with teeth." + }, + { + "kind": "p", + "text": "`total == 0 and old[0] > 0` reports a file that has been EMPTIED. Emptying is a transition: it was not empty, now it is. Change the guard to `old[0] >= 0` and a file that was already empty when the ledger was written — that never made the transition — is announced as newly emptied. On every run. Forever." + }, + { + "kind": "p", + "text": "Not a missed failure, then. A permanent false alarm, which is the failure mode that gets a gate switched off, and after that the gate misses everything. Every case in that control planted its fault AFTER the ledger was written, so the baseline value was never zero and the boundary was never approached from below. Closing it needed a fixture where the fault is present at RECORD time, which is a different question about when, not about what." + }, + { + "kind": "h", + "text": "One planted tree can close two boundaries" + }, + { + "kind": "p", + "text": "The count of prose-only files appears twice in the same gate: in the header the ledger writer emits, and again in the census line the verify path prints. Same expression, both sides of the ledger. A single fixture carrying a zero-case file at record time pins both, because they are one question asked twice." + }, + { + "kind": "p", + "text": "Worth looking for. When a boundary survives in two places, check whether it is two defects or one expression with two readers." + }, + { + "kind": "h", + "text": "Cosmetic was closed rather than declared, twice" + }, + { + "kind": "p", + "text": "Two of the twelve guard a `\"(+N more)\"` continuation line. At the boundary they print `(+0 more)`, which harms nobody, and the honest classification is cosmetic." + }, + { + "kind": "p", + "text": "Both were closed with a case anyway. This campaign has twice found a limitation that was written down, sounded mechanical, and was invented — a justification nobody had measured, which read as considered and therefore stopped anyone checking. Against that record, a declared exception costs every future reader more than a case costs to write once." + }, + { + "kind": "h", + "text": "Two survivors, and they are theorems" + }, + { + "kind": "p", + "text": "What remains is `math.isinf(dec) and (inp > 0) == (dec > 0)`, twice. The branch is guarded by `elif math.isinf(inp):` one line above, so both values are infinite by construction, and for a value in {+inf, −inf} the two forms agree — the only input separating them is zero, and neither can be zero." + }, + { + "kind": "p", + "text": "It is worth saying that this was first classified as a CANDIDATE theorem resting on an unchecked property of the codec. That caveat was written after reading the comparison and not the guard above it. The proof is two lines long and was sitting in the file the whole time." + }, + { + "kind": "p", + "text": "The line now carries a marker naming itself a known equivalence with the reason. The marker is PRINTED beside the surviving row and never acted on: the row still reads SURVIVED and still counts. Suppressing a row on the strength of a comment is exactly how a declared exception stands for a week while being false." + }, + { + "kind": "h", + "text": "What 111 mutants and two survivors does not say" + }, + { + "kind": "p", + "text": "It does not say the gates are correct. It does not say they check the right properties. It says no mutant in four narrow families survives its control, and the families are narrow by construction — a fifth operator is a fifth question." + }, + { + "kind": "p", + "text": "The prior after this week is that a new question finds something. Three of the four operators found a defect in the tool asking the question rather than in the code being asked about. That is the least comfortable number in this post and the most useful one." + } +] + +export const ruBody: Block[] = [ + { + "kind": "p", + "text": "Негативный контроль гейта пишет тот, кто сажает дефект, который контроль должен поймать. Эта одна фраза объясняет почти всё, что нашёл граничный оператор." + }, + { + "kind": "p", + "text": "Мутационная линия закрыта. Тринадцать гейтов, четыре оператора, 111 мутантов, двое выживших — и оба выживших суть доказанные эквивалентности, которые теперь несут доказательство прямо в выводе рядом с собой. Дальше — не счёт. Дальше один структурный факт, который вскрыл последний оператор и не могли вскрыть первые три." + }, + { + "kind": "h", + "text": "Четыре вопроса, а не один" + }, + { + "kind": "p", + "text": "Каждый оператор ломает гейт нарочно и спрашивает, заметит ли это собственный контроль гейта. Различаются они тем, что ломают." + }, + { + "kind": "ul", + "items": [ + "Тихий — `return 1` становится `return 0`. Способен ли гейт вообще ещё упасть?", + "Громкий — `return 0` становится `return 1`. Требует ли хоть что-нибудь от него молчания?", + "Инверсия — `if C:` становится `if not (C):` там, где тело несёт вердикт. Доходит ли он до ВЕРНОГО вердикта?", + "Граница — `>` становится `>=`, `<` становится `<=`. Доходит ли он до вердикта в верном МЕСТЕ?" + ] + }, + { + "kind": "p", + "text": "Первые три нашли пробелы и перестали их находить: 36, 21 и 33 мутанта, убиты все. Четвёртый на первом же честном прогоне нашёл двенадцать выживших в пяти гейтах из тринадцати — на наборе, который трое предыдущих уже вычистили." + }, + { + "kind": "h", + "text": "И каждый из них был вырожденным входом" + }, + { + "kind": "p", + "text": "Шесть из этих двенадцати закрылись одним заходом, и они рифмуются. Каждому нужен вход, который ни одному существующему случаю не было повода построить, и всякий раз недостающим оказывался вырожденный." + }, + { + "kind": "table", + "head": ["граница", "вход, которого никто не сажал"], + "rows": [ + ["`v[0] > 0` в переписи файлов-без-данных", "файл с **нулём** случаев"], + ["`total > 0 and data == 0` для нового файла", "**новый** файл с нулём случаев"], + ["`total == 0 and old[0] > 0`", "файл, **уже пустой к моменту записи реестра**"], + ["`len(parts) > 1` при разборе строки реестра", "строка **без разделителя вовсе**"], + ["`len(fixed) > 5` перед строкой-продолжением", "**ровно пять** починенных записей"], + ["`n_ssot < MIN_ROWS`, пол", "**ровно** пол"] + ] + }, + { + "kind": "p", + "text": "Ничего экзотического. Каждый — вход, который читатель назовёт тривиальным, и ровно поэтому ни одного из них не существовало." + }, + { + "kind": "quote", + "text": "Автор контроля сажает тот дефект, который проверяет, — а это по построению невырожденный пример: файл с неверным содержимым, а не файл без содержимого." + }, + { + "kind": "p", + "text": "Чтобы проверить, что гейт ловит потерю данных, вы пишете файл, потерявший данные. Чтобы проверить, что он ловит опустошение, вы опустошаете файл. И то и другое — примеры ЧЕГО-ТО. Пустой случай, равный случай и случай на волосок от края — примеры ничего: они не иллюстрируют никакого дефекта, поэтому ни один автор к ним не тянется, поэтому ни один контроль их не содержит, поэтому каждое сравнение в гейте вольно стоять на одно место в сторону и проходить." + }, + { + "kind": "p", + "text": "Это и есть весь урожай граничного оператора, и это не пробел в чьём-то усердии. Это следствие того, как пишутся контроли." + }, + { + "kind": "h", + "text": "Один из них кричал бы «волки» вечно" + }, + { + "kind": "p", + "text": "Третья строка заслуживает отдельного абзаца — она с зубами." + }, + { + "kind": "p", + "text": "`total == 0 and old[0] > 0` сообщает о файле, который ОПУСТОШЁН. Опустошение есть переход: был непустым, стал пустым. Замените охранник на `old[0] >= 0` — и файл, уже бывший пустым к моменту записи реестра, никогда этого перехода не совершавший, объявляется свежеопустошённым. На каждом прогоне. Вечно." + }, + { + "kind": "p", + "text": "Значит, не пропущенный отказ. Постоянная ложная тревога — тот самый режим отказа, из-за которого гейт выключают, а после этого он пропускает всё. Каждый случай в том контроле сажал свой дефект ПОСЛЕ записи реестра, так что базовое значение никогда не было нулём и к границе снизу никто не подходил. Закрыть это потребовало фикстуры, где дефект присутствует в момент ЗАПИСИ, — другой вопрос: о том, когда, а не о том, что." + }, + { + "kind": "h", + "text": "Одна планта может закрыть две границы" + }, + { + "kind": "p", + "text": "Счёт файлов-без-данных встречается в одном гейте дважды: в заголовке, который пишет регистратор реестра, и снова в строке переписи, которую печатает проверочный путь. Одно выражение, обе стороны реестра. Единственная фикстура с файлом в ноль случаев на момент записи прижимает обе, потому что это один вопрос, заданный дважды." + }, + { + "kind": "p", + "text": "Стоит искать. Когда граница выживает в двух местах, проверьте, два ли это дефекта или одно выражение с двумя читателями." + }, + { + "kind": "h", + "text": "«Косметику» дважды закрыли, а не объявили" + }, + { + "kind": "p", + "text": "Двое из двенадцати охраняют строку-продолжение «… и ещё N». На границе они печатают «(+0 ещё)», что не вредит никому, и честная классификация — косметика." + }, + { + "kind": "p", + "text": "Оба всё равно закрыты случаем. Эта кампания дважды поймала ограничение, которое было записано, звучало механически и оказалось выдуманным, — обоснование, которого никто не измерял и которое читалось как продуманное, а потому останавливало проверку. Против такого послужного списка объявленное исключение стоит каждому будущему читателю дороже, чем случай стоит написать однажды." + }, + { + "kind": "h", + "text": "Два выживших, и это теоремы" + }, + { + "kind": "p", + "text": "Остаётся `math.isinf(dec) and (inp > 0) == (dec > 0)`, дважды. Ветка стоит под `elif math.isinf(inp):` строкой выше, так что оба значения бесконечны по построению, а для значения из {+inf, −inf} обе формы совпадают: единственный вход, который их разделяет, — ноль, и ни одно из них нулём быть не может." + }, + { + "kind": "p", + "text": "Стоит сказать, что сперва это было классифицировано как КАНДИДАТ в теоремы, опирающийся на непроверенное свойство кодека. Оговорку я написал, прочитав сравнение и не прочитав охранник над ним. Доказательство длиной в две строки лежало в том же файле всё это время." + }, + { + "kind": "p", + "text": "Теперь строка несёт маркер, называющий себя известной эквивалентностью с причиной. Маркер ПЕЧАТАЕТСЯ рядом с выжившей строкой и ни на что не влияет: строка по-прежнему читается SURVIVED и по-прежнему считается. Гасить строку по силе комментария — это ровно то, как объявленное исключение стоит неделю, будучи ложным." + }, + { + "kind": "h", + "text": "Чего 111 мутантов и двое выживших не говорят" + }, + { + "kind": "p", + "text": "Они не говорят, что гейты верны. Не говорят, что они проверяют нужные свойства. Они говорят, что ни один мутант четырёх узких семейств не переживает свой контроль, а семейства узки по построению: пятый оператор — пятый вопрос." + }, + { + "kind": "p", + "text": "Априорная оценка после этой недели: новый вопрос что-нибудь находит. Три из четырёх операторов нашли дефект в самом задающем вопрос инструменте, а не в коде, о котором спрашивали. Это самое неуютное число в этом посте и самое полезное." + } +] diff --git a/apps/website/src/data/blog/index.ts b/apps/website/src/data/blog/index.ts index 650e9bfaef..6cd92193f3 100644 --- a/apps/website/src/data/blog/index.ts +++ b/apps/website/src/data/blog/index.ts @@ -2,6 +2,36 @@ import type { PostMeta } from './types' /** Индекс блога: список и метаданные без тяжёлых тел публикаций. */ export const postsIndex: PostMeta[] = [ + { + slug: 'nobodys-example', + title: "Nobody's example", + summary: 'A gate\'s negative control is written by someone who plants the fault it is meant to catch. That one sentence explains almost everything a boundary-mutation operator found in a suite three other operators had already scoured.', + date: '2026-08-23', + readingMinutes: 8, + tags: ['CI', 'Mutation testing', 'Test design', 'Measurement'], + receipts: [ + { label: 'gHashTag/t27 #2503 -- the boundary operator, and the first number that counted docstrings', href: 'https://github.com/gHashTag/t27/pull/2503' }, + { label: 'gHashTag/t27 #2504 -- three boundaries closed, one classification corrected', href: 'https://github.com/gHashTag/t27/pull/2504' }, + { label: 'gHashTag/t27 #2507 -- the last six, and what they had in common', href: 'https://github.com/gHashTag/t27/pull/2507' }, + ], + openQuestions: [ + 'Whether a fifth operator family finds more is not established. Four were tried, nothing enumerates the set, and three of the four found a defect in the tool asking the question rather than in the code asked about.', + 'The claim that degeneracy explains the yield is an argument from six cases in one repository, not a measurement across projects. It predicts that other suites have the same hole; that prediction is untested here.', + 'Two survivors are called proven equivalences on the strength of two enclosing guards. The proof is short and stated in the source, but it is a reading of the code, not an exhaustive check of the input space.', + '"No mutant survives" is not "the gates are correct". Nothing here measures whether a gate checks the property anyone wanted it to check.', + ], + published: true, + ru: { + title: 'Ничьи примеры', + summary: 'Негативный контроль гейта пишет тот, кто сажает дефект, который контроль должен поймать. Эта одна фраза объясняет почти всё, что граничный оператор мутаций нашёл в наборе, уже вычищенном тремя другими.', + openQuestions: [ + 'Найдёт ли что-нибудь пятое семейство операторов — не установлено. Испробованы четыре, множество ничем не перечислено, и три из четырёх нашли дефект в самом задающем вопрос инструменте, а не в коде, о котором спрашивали.', + 'Утверждение, что вырожденность объясняет урожай, — довод от шести случаев в одном репозитории, а не измерение по проектам. Оно предсказывает такую же дыру в других наборах; это предсказание здесь не проверено.', + 'Два выживших названы доказанными эквивалентностями на основании двух охранников. Доказательство коротко и записано в исходнике, но это чтение кода, а не исчерпывающая проверка пространства входов.', + '«Ни один мутант не выживает» — не то же, что «гейты верны». Ничто здесь не измеряет, проверяет ли гейт то свойство, которое от него хотели.', + ], + }, + }, { "slug": "the-silence-was-a-saturated-readout", "title": "A background loop broke for months, and no amount of watching could have caught it", diff --git a/apps/website/src/data/blog/posts.ts b/apps/website/src/data/blog/posts.ts index 19cf4ec96d..421b150e3e 100644 --- a/apps/website/src/data/blog/posts.ts +++ b/apps/website/src/data/blog/posts.ts @@ -1,6 +1,7 @@ import { postsIndex } from './index' import { body as body_a_health_snapshot_changed_its_denominator, ruBody as ruBody_a_health_snapshot_changed_its_denominator } from './bodies/a-health-snapshot-changed-its-denominator' import type { Post, PostBody } from './types' +import { body as body_nobodys_example, ruBody as ruBody_nobodys_example } from './bodies/nobodys-example' import { body as body_the_silence_was_a_saturated_readout, ruBody as ruBody_the_silence_was_a_saturated_readout } from './bodies/the-silence-was-a-saturated-readout' import { body as body_twenty_merged_in_three_days, ruBody as ruBody_twenty_merged_in_three_days } from './bodies/twenty-merged-in-three-days' import { body as body_energy_asymmetry_activations, ruBody as ruBody_energy_asymmetry_activations } from './bodies/energy-asymmetry-activations' @@ -54,6 +55,7 @@ import { body as body_the_scanner_scored_what_it_could_not_see, ruBody as ruBody import { body as body_i_wrote_the_post_then_did_the_thing, ruBody as ruBody_i_wrote_the_post_then_did_the_thing } from './bodies/i-wrote-the-post-then-did-the-thing' const bodies: Record = { + 'nobodys-example': { body: body_nobodys_example, ruBody: ruBody_nobodys_example }, 'the-silence-was-a-saturated-readout': { body: body_the_silence_was_a_saturated_readout, ruBody: ruBody_the_silence_was_a_saturated_readout }, 'twenty-merged-in-three-days': { body: body_twenty_merged_in_three_days, ruBody: ruBody_twenty_merged_in_three_days }, 'energy-asymmetry-activations': { body: body_energy_asymmetry_activations, ruBody: ruBody_energy_asymmetry_activations },