OverviewFilesCommitsIssuesDocsReleasesPeers

keet-daemon commits / a978fb8

CPP-PORT-DESIGN: R4c-4d design (facade first: E0 frontier scopes … E5 one-commit storage switch, E6 hops)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
a978fb86a019aba7edcc844c2aef4e085975721b
by plankatron <fleeky@gmail.com> · 2026-10-07T22:03:54.000Z

Changed files (1) +54 -0

docs/CPP-PORT-DESIGN.md +54 -0
……@@ -4267,6 +4267,60 @@ injected per layer:
42674267 Stopped, moves on (a loop starts the next set beside it: two drills on one tree), and SIGHUPs it on
42684268 exit. Drills run under a Python `subprocess.run` runner, and sets pause between runs via a pause file.
42694269 - A `ps | grep "[d]rill.py"` inside a shell whose own command line contains "drill.py" self-matches.
4270- **R4c-4d DESIGN (2026-10-07; path chosen by the user 2026-10-07: facade first).** Core moves from l2 onto the
4271 async hc::storage in JS's async shape: the Promise mutex, the async open, and every JS await a co_await. The
4272 `Sync` frontier moves up to core's callers (store, repl, bee, blobs, wakeup, tools, tests).
4273 - **Research record:** `docs/research/r4c4d-inv.md` (keet-daemon f2b4bf1). Its sections: A (core's remaining l2
4274 uses, with hc::storage signatures), B (every async JS function: its awaits in order and the coroutine it
4275 becomes), C (the frontier, each caller classed wait / scope / chain / net) and D (hazards D1–D11), all at
4276 keetd bb707dd. It corrects the R4c-4 inventory's mark-bitfield line numbers (off by +161).
4277 - **Order** (every sub-step builds, ctest green, every gate identical to the previous commit):
4278 - **E0. Frontier scopes first; core is unchanged.** Each frontier call gets a `Sync`: `wait` where the result
4279 is used at once, a bare scope around callback calls whose result is read inline, and nothing around network
4280 waits. While core still completes inline, these scopes are no-ops. They make E2's first delayed hop safe.
4281 A drill set removes a frontier scope and expects red.
4282 - **E1. An async facade over l2, with hc::storage's exact API** (temporary; widens hc/merkle_l2.h). CoreRX
4283 getters queue and resolve at `tryFlush`; `CoreTX::flush`, the session ops, close, `resumeCore`,
4284 `createCore`, `createGroup`, compact and `Atom::flush` / `flushed` return `js::Promise`. With it, E2–E4
4285 compile against the final API without touching store/.
4286 - **E2. The Promise mutex** (lib/mutex.js literally, `_destroying` included). `locked_` and the callback
4287 users `co_await` the lock. The 8 "mutex held" throws become a `Sync` wait on the lock: unreachable while
4288 frontier entries are atomic, and a NoProgress, not a keetd throw, if one were reached. `lockExclusive`
4289 returns a promise. `Mutex::cancel` (no JS counterpart) is decided here (D1).
4290 - **E3. The async Core open:** `opening = _open()`, no I/O in the constructor, `ready()`, and JS's `opened`
4291 guard in `checkIfIdle`. `Session`'s open awaits `core.ready()` (ix:390). Constructor sites outside core
4292 `wait` on `ready()` in their E0 scope.
4293 - **E4. Per JS function group, bottom-up, each on the facade.** Each commit deletes the internal `Sync`
4294 scopes inside the functions it converts (D4: no coroutine may call a function that still waits, in an
4295 inner scope, on a mutex or flush the coroutine holds). The groups, in order:
4296 1. write primitives (`flush`, `storeBitfieldRange` in JS's batch shape, `_truncate`, `flushHints`);
4297 2. session-state.js ops;
4298 3. core.js (`_verifyExclusive` / `_verifyShared` with `_verifies` batching, `checkConflict` /
4299 `_repairTreeNodes`, audit.js, copy-prologue.js, `close` / `destroy`);
4300 4. mark-bitfield.js;
4301 5. index.js;
4302 6. fully-remote-proof.js.
4303
4304 As each group converts, its frontier sites move from a bare scope to `wait` or `.then`. Each group's drill
4305 set is re-anchored and run red in the same commit.
4306 - **E5. The storage-type switch, in ONE commit.** The facade and merkle_l2.h are deleted. The CoreRX→`merkle::Rx`
4307 bridge (tools/mt's `StorageRx` / `StorageTree`) moves into core. Streams are consumed as JS consumes them
4308 (`for await` with the body's awaits interleaved). store/, the r3c / m3c tests, core-fixture, core-ops,
4309 store-ops, keetd-replicate and m4d switch in the same commit: they share the store and its lock. The M4d
4310 hook moves into rn's write completion (`rn::native::write`); BOUNDARY stays valid on the new write
4311 numbering. Only `tools/l2-ops` and l2's own gates stay on l2 until R4c-4e.
4312 - **E6. The core gate's `hops` mode and the R4c-4b concurrency scripts,** compared line for line with Bare at
4313 pool = 1. Any difference is a finding, fixed in core.
4314 - **Rules carried from the hazards:**
4315 - **Timer-resumed continuations open their own `Sync`.** `waitForRecovery`'s tail holds the state mutex, and
4316 a timer callback is a frontier entry (D4).
4317 - **No by-reference parameters in coroutines.** Each suspended member coroutine pins its object
4318 (`shared_from_this` or an `alive_` check after each `co_await`) (D6).
4319 - **Storage close = JS's sites exactly.** Destructors close nothing. Every CoreRX ends in `tryFlush` or
4320 `destroy` (D3).
4321 - **The deviations that become observable are ported** (D10): markBlock's `Promise.all` under the mark
4322 mutex, the MarkPage inserted before its read, awaited `preappend` / `postappend`, `setManifest`'s
4323 lock-first order, `compact`'s `Promise.all`, the userData flush awaited before 'ready'.
42704324- **Then 4e-4** (`createProtocolStream` / `replicate`): the first gate that composes the stack
42714325 is a COMPOSED trace against JS (secret-stream + protomux + replicator), now meaningful.
42724326