docs: retract an unfounded claim v2.4.1's notes made about v2.3.9 - #431
Merged
Conversation
v2.4.1's release notes carried a section headed "a claim v2.3.9 made that v2.3.9 did not ship", asserting that v2.3.9's published body described release_anchor_audit.rs while the tag did not contain it. That is false, and it was published. What the v2.3.9 body actually says, under the heading "The release anchors, and two documents that were wrong about more than the version", is that eight documents held six different answers about the current version and that "All now read v2.3.9". That describes a MANUAL re-synchronisation, and the manual re-synchronisation is in the v2.3.9 tag. Checked rather than re-asserted: the published body contains no occurrence of "release_anchor_audit", "anchor audit", "standing", "pins", "gate", or "15 anchors", and neither does the v2.3.9 CHANGELOG section. Both halves of the original claim were separately true, which is how they combined into something false. The file really is absent from the tag: $ git cat-file -e v2.3.9:crates/rustynes-test-harness/tests/release_anchor_audit.rs fatal: path '...' exists on disk, but not in 'v2.3.9' And v2.3.9 really is where the anchor drift was found. The step that was never performed was reading the v2.3.9 body to confirm it claimed the gate. It claimed the fix, which it shipped. A hand correction fixing the instance and a later commit adding the mechanism is ordinary sequencing, not a release note describing work its tag does not contain. The retraction is written into the notes rather than edited out of them. The claim was an accusation against a shipped release, it was published under a heading that made the accusation the section's subject, and deleting it would leave no record that the previous release had been wrongly impugned -- which is the shape of scrubbing this project has a standing rule against. AGENTS.md carried the same sentence, since that is where the v2.4.1 summary was drafted from, and is corrected the same way. The published GitHub release body for v2.4.1 is updated from this file, so the repo copy and what users read agree again.
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Antigravity review (Gemini via Ultra)This PR updates the v2.4.1 release notes and Blocking issuesNone found. Suggestions
Nitpicks
Automated first-pass review by |
doublegate
added a commit
that referenced
this pull request
Aug 20, 2026
…432) #431 retracted the claim. This records the cause, because the instance is the least interesting part of it. Both inputs to the false statement were real and each had been checked independently: release_anchor_audit.rs genuinely is absent from the v2.3.9 tag, and v2.3.9 genuinely is where the anchor drift was found. What was never checked was the conjunction -- that v2.3.9's release body therefore DESCRIBED the audit -- and checking it was one command: gh release view v2.3.9 --json body That body says the eight drifted documents "All now read v2.3.9", a manual re-synchronisation which is in its tag, and contains no occurrence of "release_anchor_audit", "standing", "gate", or "15 anchors". Verifying every premise is not verifying the conclusion drawn from them. Two propagation mechanisms matter more than the instance, and the bullet names both. The sentence was written into AGENTS.md during the v2.4.0 work, and the v2.4.1 release summary was then drafted FROM AGENTS.md. That is the laundering step: an unverified claim entering this file is indistinguishable from a verified one by the time the next release quotes it, and it then reaches a published release body, a commit body, a PR body and a report to the maintainer in a single pass. AGENTS.md is a notes file, not an oracle, and this is the first entry that says so about itself. The claim also had the shape this project rewards -- a recursive irony, "the same failure one level up". That shape actively suppresses the check, because it reads as an insight rather than as an assertion needing evidence. The house style's appetite for findings of that form is exactly why it needs a verification bar rather than less of one. The bar stated: before writing that a document, release, commit or person SAYS something, open it and grep for the words. Nothing else changes -- one bullet, inserted beside the sibling traps it belongs with (the reviewer-claim bullet it now precedes is the same failure with a different source).
doublegate
added a commit
that referenced
this pull request
Aug 22, 2026
* chore(release): cut v2.4.2 "Cairn" -- the rung-0 compare surface
Bumps the workspace to 2.4.2, promotes the `[Unreleased]` CHANGELOG content into
a dated section, moves all 15 release anchors across 10 documents, and adds the
maintainer-authored release-notes override that `release-auto.yml` prefers over
the CHANGELOG extract.
The release itself is scaffolding for the v2.4.1 -> v2.5.0 "Fabric" line. The
emulation core is untouched -- no behaviour change to
rustynes-{cpu,ppu,apu,mappers,core}, no new hot-path API, and rustynes-cosim
stays excluded from the workspace and absent from the default build.
## Why "Cairn"
A cairn is a marker set along a route so you can tell you are still on it. That
is what a rolling per-cycle hash checkpoint is, and the release's subject is
building that compare surface: 89,343 CPU cycles of AccuracyCoin is 5,372,427
bytes of irq.csv against 352 bytes of ckpt.bin, a factor of 15,263, so the first
mismatch names a 4096-cycle window and only that window is re-run with full
capture.
## What this commit contains
* Cargo.toml `[workspace.package] version` 2.4.1 -> 2.4.2, and the Cargo.lock
propagation across the ten workspace members that inherit it.
* CHANGELOG.md: `## [Unreleased]` stays permanent and empty at the top; its
content moves under
`## [2.4.2] - 2026-08-22 - "Cairn" (checkpoints, and what a device can actually
observe)`. The header is verified to parse the way release-auto.yml parses it
-- the ` - YYYY-MM-DD - ` prefix, a quoted codename, then a parenthesised
theme -- since a malformed header degrades the published release title.
* The 15 anchors in README.md (badge + Current Release), docs/STATUS.md,
AGENTS.md (x3, including the never-claim-a-later-version guard),
VERSION-PLAN.md, to-dos/ROADMAP.md, SUPPORT.md, SECURITY.md, ROADMAP.md (x2),
OVERVIEW.md (x3) and ARCHITECTURE.md. Each demotes the v2.4.1 text to "built
on" rather than overwriting it, so the release chain stays readable.
* VERSION-PLAN.md gains a v2.4.2 row and `(current)` moves off v2.4.1;
`the_version_plan_table_marks_exactly_the_current_release` checks this.
* .github/release-notes/v2.4.2.md, 198 lines.
## Two gates earned their place, both failing first
`release_anchor_audit` FAILED CLOSED on a defect this commit introduced. The
VERSION-PLAN edit produced `**Current release: **v2.4.2` -- a doubled bold marker
-- so the pinned marker `**Current release: v` no longer matched, and the audit
refused to report a pass for an anchor it could not find rather than silently
checking 14 of 15. That is the exact failure mode it was written after.
`cosim_manifest_audit` then caught the price of exclusion that AGENTS.md
documents: an excluded package cannot use `version.workspace = true`, so
crates/rustynes-cosim/Cargo.toml still said 2.4.1 after the workspace moved. Its
message says so directly -- "the crate is excluded, so nothing inherits this for
you". Bumped, and its own tracked lockfile regenerated.
`libretro_info_audit` required the LOCAL rustynes_libretro.info display_version
to move with the workspace. Bumped to v2.4.2. NO upstream PR is opened: the
cadence rule limits upstream syncs to vX.Y.0 boundaries (next: v2.5.0) and no
licence changed here, which is the one override. Keeping the local file current
is what makes that eventual sync a copy rather than a re-derivation.
## On v2.4.0, which is deliberately not tagged
Checked rather than assumed. The workspace version was NEVER 2.4.0 on any commit
on any branch -- `git log --all -S'version = "2.4.0"' -- Cargo.toml` is empty,
and PR #428's merge commit b67c4f9 still reads 2.3.9. There is also no
`## [2.4.0]` CHANGELOG section, so release-auto would fail loudly by design
rather than ship empty notes.
So no commit exists that a v2.4.0 tag could honestly point at: every candidate's
own manifest announces a different version. v2.4.0 "Concordance" shipped inside
v2.4.1, which that release's notes and VERSION-PLAN.md both record. A skipped
version number is permitted by SemVer; a tag pointing at a tree that calls itself
something else is not honest, and retroactively contradicting a shipped
release's notes is the same class of record corruption as the v2.3.9 claim this
project retracted in #431. The release notes state this explicitly so the
question is answered where a reader will ask it.
## Verification
* AccuracyCoin 141/141 (100.00%, RAM decoder) and nestest 0-diff -- run, not
assumed, even though the core is untouched by this commit.
* release_anchor_audit: 8/8 (after the doubled-marker fix).
* cosim_manifest_audit: 4/4. libretro_info_audit: 3/3.
* cargo fmt --all --check: clean.
* markdownlint via pre-commit (pinned v0.39.0, --files not --all-files): Passed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014qfTKi2M3swo7qnwvYCkDj
* docs: address the review -- and one finding is an arithmetic error, not a nit
Six CodeRabbit findings, every one verified against the code or the file before
being acted on rather than accepted on plausibility. All six were real.
## The one that matters: 244 KB is wrong by about 2x
The extrapolated checkpoint size has been 244 KB since the Fabric plan, and it
does not survive its own measurement:
ENCODED_LEN 16 bytes
measured 89,343 cycles -> 352 bytes ckpt.bin
352 / (89343/4096) 16.1 bytes per checkpoint
125,000,000 / 4096 * 16 477 KB
125,000,000 / 89,343 * 352 481 KB
244 KB == 30,518 * 8 an 8-BYTE record
244 KB is what you get from a checkpoint holding only the hash. The implemented
record holds the cycle AND the hash, so the figure predates the implementation
and nobody re-derived it. The 15,263x ratio is measured and unaffected; only the
absolute extrapolation was wrong.
Corrected in the live spec documents -- AGENTS.md (both occurrences),
docs/mister.md, to-dos/ROADMAP.md -- and explained in the v2.4.2 notes, which is
where a reader meets the number.
DELIBERATELY NOT corrected: .github/release-notes/v2.4.1.md (a shipped record is
not silently rewritten), docs/adr/0037 (a decision record), and the research
archive under to-dos/plans/research/. The v2.4.2 notes carry a block naming all
three, so the correction is discoverable from the wrong number rather than only
from the right one.
## The other five
* The obs.bin record count is 89,335 against 89,343 cycles, and the gap is
exactly the eight-cycle reset `Nes::from_rom` runs before the trace is armed.
Nothing is filtered. Both counts appear in the notes and the boundary between
them did not; it does now.
* The stream-length check was attributed to `Observable::decode`, which
validates ONE 16-byte record. `observables_from_bytes` is what rejects a
stream whose length is not a multiple of 16 (checkpoint.rs:302), before any
record is decoded. Reattributed.
* "No public-API change" was unqualified while rustynes-cosim adds public Rust
and C ABI surface. True for every shipped and default-build package, and now
says so.
* SECURITY.md declared v2.4.2 current in its prose while its table still labelled
2.3.x "The current line" with no 2.4.x row at all -- so the supported-version
table, which is the part a reporter actually reads, named the wrong line. Adds
a 2.4.x row and moves 2.3.x to Partial.
* to-dos/ROADMAP.md carried three stale status markers, two of them actively
misleading rather than merely old: line 59 announced "Next up -- v2.4.0
Concordance" for a release that shipped inside v2.4.1 and is deliberately
never tagged, and line 100 stated v2.2.6 "Almanac" as the latest release,
eleven releases behind. Line 84 still read "In development -- the v2.0.0 tag
itself" for a tag pushed on 2026-07-03. Corrected, with 100 and 84 relabelled
as historical snapshots rather than deleted.
That line-59 finding is worth naming: the same commit that documents why v2.4.0
has no tag left a bullet elsewhere in the tree announcing it as the next
release. The release anchors are gated; ordinary status prose is not.
## Verification
* release_anchor_audit 8/8, cosim_manifest_audit 4/4, libretro_info_audit 3/3.
* markdownlint via pre-commit (pinned v0.39.0): Passed.
* No emulation-core change; AccuracyCoin 141/141 (RAM decoder) and nestest
0-diff already verified on this branch and unaffected by a documentation edit.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014qfTKi2M3swo7qnwvYCkDj
* test(release): gate ordinary status prose, not just the pinned anchors
`release_anchor_audit` pins 15 fixed markers and fails closed when one goes
missing. That is the right shape for THE canonical current-release statement in
each document, and it is why a doubled bold marker on this very cut failed
loudly instead of silently checking 14 of 15.
It cannot cover prose that has no marker, and the review round found that **the
drift did not stop when the anchors were gated -- it moved into the prose beside
them**:
* `to-dos/ROADMAP.md` announced a "Next up" for v2.4.0, a release that shipped
inside v2.4.1 and is deliberately never tagged -- in the very change that
documents why it has no tag,
* the same file still described the v2.0.0 tag as in development, for a tag
pushed 2026-07-03,
* and `to-dos/README.md` described v1.8.9 the same way, roughly fifteen releases
stale, which nothing had flagged at all and which the review did not find
either. The gate did.
So this is a PATTERN check rather than a marker list: a status label (`Next up`,
`In development`, `Planned for`, `Upcoming`) naming a version at or below the
workspace version is a contradiction that needs no judgement to detect.
## Discovery needs no list of its own
`git ls-files` intersected with `.markdownlintignore`. Tracked files ARE the
definition of this project's own content -- the vendored `nesdev_wiki/` beside
this checkout is 2,655 untracked markdown files, and a first draft that walked
the directory tree examined 3,085 files instead of 225. The frozen-tree list is
READ from `.markdownlintignore` rather than duplicated, because a second copy of
"which prose is not policed" is precisely the drift this file exists to catch.
## A companion rule was measured and REJECTED
"A `latest release` or `the current line` claim must name the workspace version"
fires on `docs/ios.md`, which correctly says "The current line is v1.9.9
'Workshop'" -- scoped to the iOS TRAIN, not the project release. The phrase
legitimately scopes to a platform line, so the rule cannot separate a stale claim
from a correct one without judgement.
A gate with false positives gets switched off, which is worse than no gate --
the same sentence already written into `check_rtl_subset.py`. Recorded as a
measured rejection in the module docs rather than shipped and tuned.
## Mutation testing changed the design, twice
The escape hatch was first "any line containing the word historical". The very
first line written against it -- the `to-dos/README.md` fix -- said "this
paragraph is a historical snapshot" for unrelated reasons, so M1, the mutation
reintroducing the exact defect the gate exists for, came back **NOT CAUGHT**:
silently exempted by the prose beside it. An escape claimable by accident fails
in the direction of silence, which is the worst direction.
The marker became an HTML comment. Then the gate failed on its own CHANGELOG
entry, because documenting the defect requires QUOTING it -- the same recursion
that once made a commit body explaining the `Closes #N` anti-pattern close an
issue. A quotation is not a historical snapshot, so the marker is named
`not-a-claim`: it says the line is not asserting state, which is true of both
cases. Five such lines exist, all quotations, all printed and counted on every
run so growth stays visible.
Five mutations, all behaving:
M1 bare label on a shipped version FAIL (caught)
M1b same line, word "historical" incidentally present FAIL (the loose escape no longer rescues it)
M4b explicit `not-a-claim` marker PASS (exempts, on purpose only)
M3 label on a FUTURE version PASS (not yet shipped)
M6 predicate inverted, defect present PASS (gate inert -- the comparison is load-bearing)
Plus fail-closed on an unparseable `.markdownlintignore` and on a short file
list, since zero files examined means the discovery is wrong rather than that
every document is consistent.
## Also
* `to-dos/README.md` corrected -- v1.8.9 shipped 2026-06-25.
* Three unit tests pin the version parser, the 60-character window, and that the
scanner does not panic on a multi-byte line. That last one is not decorative:
these documents are full of em-dashes, and a byte-slicing implementation
panics while formatting its own diagnostic, replacing the message explaining
the failure with a char-boundary error about the reporting code.
## Verification
* release_state_prose_audit 4/4, release_anchor_audit 8/8,
cosim_manifest_audit 4/4, libretro_info_audit 3/3.
* `cargo fmt --all --check` clean; `cargo clippy -p rustynes-test-harness
--all-targets -- -D warnings` clean.
* markdownlint via pre-commit (pinned v0.39.0): Passed.
* 225 tracked, non-frozen markdown files examined; 5 exemptions, all listed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014qfTKi2M3swo7qnwvYCkDj
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
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.
v2.3.9's release notes are not wrong. The claim v2.4.1 made about them is, and it was published.
v2.4.1's notes carried a section headed "a claim v2.3.9 made that v2.3.9 did not ship", asserting that v2.3.9's published body described
release_anchor_audit.rswhile the tag did not contain it.What v2.3.9 actually says
Under "The release anchors, and two documents that were wrong about more than the version", it says eight documents held six different answers and "All now read v2.3.9." That describes a manual re-synchronisation — and the manual re-synchronisation is in the v2.3.9 tag.
Checked rather than re-asserted: the published body contains no occurrence of
release_anchor_audit, "anchor audit", "standing", "pins", "gate", or "15 anchors". Neither does the v2.3.9 CHANGELOG section.How two true facts made a false one
Both halves stood up separately. The file really is absent from the tag:
…and v2.3.9 really is where the anchor drift was found. The step never performed was reading the v2.3.9 body to confirm it claimed the gate. It claimed the fix, which it shipped. A hand correction fixing the instance, followed by a later commit adding the mechanism, is ordinary sequencing — not a release note describing work its tag does not contain.
Why it is retracted in place rather than deleted
The claim was an accusation against a shipped release, published under a heading that made the accusation the section's subject. Deleting it would leave no record that the previous release had been wrongly impugned — the shape of provenance scrubbing this project has a standing rule against. So the section is rewritten to say what is true and to state what it previously said and that it was wrong.
Changed
.github/release-notes/v2.4.1.md— section rewritten as "The release anchors, and the gate that arrived after them", with the retraction stated in it.AGENTS.md— carried the same sentence, since the v2.4.1 summary was drafted from it; corrected the same way.Already applied outside this branch: the published v2.4.1 GitHub release body has been updated from the corrected file, and #430's body now carries the retraction inline, so nothing a reader reaches still asserts it.
Docs only — no source, no manifests. AccuracyCoin and the workspace suites are untouched by construction.