| … | … | @@ -3976,6 +3976,28 @@ injected per layer: |
| 3976 | 3976 | - **Drill r4c3a +6: 18/19 red, 1 equivalent.** The `eagerOpen` survivor was a script gap, fixed |
| 3977 | 3977 | by the late-consumption script. |
| 3978 | 3978 | - ctest 87/87. |
| 3979 | - **R4c-3b-2 DONE 2026-10-06** (keetd d946866): migrations/0's oplog reading. |
| 3980 | - **Codecs:** messages.js's `oplog.header` / `oplog.entry` and every part they use. A version-0 |
| 3981 | header (the oldest hypercore 10) gets its manifest synthesized, as JS does. |
| 3982 | - **Oplog functions:** |
| 3983 | - `decodeOplogHeader` uses a SIGNED `l >> 2`; `decodeOplogEntry` uses `>>>`. |
| 3984 | - `readOplog`: header slots at 0 and 4096; the header bit; entries from 8192; trailing partial |
| 3985 | entries dropped; the external header file. |
| 3986 | - **Measured on Bare:** for an oplog shorter than 4104 bytes, the slot-2 `uint32` decode throws |
| 3987 | outside readOplog's try, inside `fs.readFile`'s callback. bare-fs calls that callback inside its |
| 3988 | own `async readFile`, so the result is an UNHANDLED REJECTION, and readOplog never settles. It is |
| 3989 | ported as such. Real hypercore-10 oplogs are always ≥ 8192 bytes. |
| 3990 | - **Vectors:** |
| 3991 | - `vectors/gen/legacy-cores.js` (node, hypercore 10.38.2) writes flushed, unflushed, truncated, |
| 3992 | read-only and empty cores. The unflushed ones keep oplog entries. |
| 3993 | - `vectors/gen/r4c-oplog.js` runs JS's own readOplog over them, loaded from a copy of |
| 3994 | migrations/0/index.js with only an export line appended and absolute requires, plus 18 |
| 3995 | hand-framed cases built with messages.js's encoders. v0 headers are framed by hand, since no |
| 3996 | encoder exists. |
| 3997 | - **Test `r4c_oplog`:** 23/23. |
| 3998 | - **Drill r4c3b2: 10/11 red, 1 equivalent.** The equivalent is an unsigned header-length shift: |
| 3999 | with bit 31 set, JS's negative length passes the bounds check and the decode throws (null), |
| 4000 | while the unsigned one fails the bounds check (null). The state is untouched either way. |
| 3979 | 4001 | - **Then 4e-4** (`createProtocolStream` / `replicate`): the first gate that composes the stack |
| 3980 | 4002 | is a COMPOSED trace against JS (secret-stream + protomux + replicator), now meaningful. |
| 3981 | 4003 | |