Rewrite-storm Resume copy validation — 2026-09-24¶
The native S89 run found an acceptance failure after the shared hold had successfully stopped note publication for five minutes. With both stamping fixtures disabled, both devices resumed and converged on the full main note, but each had two sibling copies: an older published answer and that same device's newer locally held rewrite.
The former automated test checked the number of copies before Resume and then checked that the newer held text was present in one copy. It did not count all siblings after Resume. The test now counts the final siblings and keeps both stampers active through a five-minute hold.
A second two-engine regression pins the native ordering: one answer is
already being uploaded when the detector persists its hold, the other device
receives the encrypted pause control, and the old upload finishes. Stamping
continues locally for five minutes while the editor completes twenty
characters. After both fixtures stop, both Resume orders must produce the
same main note containing all twenty characters and exactly one shared copy.
The old code fails both orders with 2 !== 1. The copy's encrypted version
history must contain both the old published answer and the latest held text.
Fix and refusal boundary¶
The detector's Resume uses the existing deterministic conflict-file identity for its recorded source version. It first ensures the baseline is preserved, then advances that same copy with its newer held bytes. This changes neither the manifest schema nor the server API. No timestamp or front matter is stripped, and independent content is never treated as noise.
Advancement requires one readable remote head at the same copy path, with chunk identity matching either the known baseline or the exact held snapshot. The local copy must likewise match one of those snapshots and remain unchanged in both content and metadata while its replacement is prepared. A changed path record is also refused. The parent lookup and write run inside that copy's existing publication queue, after any earlier upload acknowledges. A concurrent remote fork, interrupted publication, or disappearing copy keeps the original note paused. A retry of an already-published snapshot adds no extra version.
resume-copy.test.mjs covers independent local and remote copy edits, split
heads, unavailable or moved history, the one-chunk budget, same-metadata saves,
path-record changes, a remote head racing publication, a growing/disappearing
copy, and an older upload still in flight. It verifies that ordinary newer
body edits are preserved too, without depending on front-matter parsing.
The explicit current.deleted refusal has a redundant content precondition:
record validation binds every deleted manifest to an empty chunk list, while
both acceptable snapshots here contain exactly one chunk. Removing only that
deletion disjunct cannot admit a deleted record through the remaining chunk
identity test. It is retained for clarity and is not counted as a separate
behavioral mutation.
Verification scope¶
The copied composed baseline had 1,047 tests; its parked-note fixture observed a retry summary while a manual verification upload was still draining and asserted idle too early. The fixture now waits, within its existing bounded wait, for the actual drain and queue to finish. It still asserts exact idle, zero active publications, all expected content, and the original notice counts. No parked-note product behavior changed.
The complete unmutated suite with this fix passes 1,068/1,068 tests. Commands use the pinned Node 26.8.2 and TypeScript 5.9.3:
npm --prefix plugin run build
node --test --test-reporter=tap plugin/test/*.test.mjs
sh plugin/test/mutants/run.sh plugin/test/mutants/M620.diff
Every probe M620–M639 compiled and failed relevant tests through the full-suite runner. That audit exposed two fixture defects: the deleted-copy fixture used an API that always creates a live record, and the growing-copy fixture injected its edit by read count. The final fixtures use the tombstone API and the write/upload lifecycle. The local-identity fixture now returns one stable replacement record, and checks preserve the specific refusal diagnostic.
All twenty probes were then rerun against the corrected nineteen-test
resume-copy.test.mjs suite; the table reports those final focused failure
counts, not the earlier full-suite counts. Earlier collateral co-typing,
stamper, and upgrade-fixture failures are not used as mutation proof. The
coordinator's final composed matrix supplies the final full-suite receipt.
| Probe | Final focused failures |
|---|---|
| M620 | 18 | | M621 | 1 | | M622 | 1 | | M623 | 1 | | M624 | 1 | | M625 | 1 | | M626 | 1 | | M627 | 1 | | M628 | 1 | | M629 | 12 | | M630 | 3 | | M631 | 1 | | M632 | 1 | | M633 | 1 | | M634 | 1 | | M635 | 1 | | M636 | 1 | | M637 | 5 | | M638 | 1 | | M639 | 2 |
Inherited probes M496, M566, M568, M569, M570 and M571 were recut only for the new Resume context; their original mutations are unchanged. All 69 prior
179 probes pass strict patch -F0 applicability. Their final composed kill¶
counts are intentionally left to the coordinator's full matrix.
This is automated evidence for the native failure. The coordinator must rerun native S89 with the repaired bundle before claiming native acceptance.