fix(drift-trio): phase E — serialized fiber queue (#10a) + fiber-busy probes

runOnFiber now runs bodies strictly one-at-a-time through a park-safe FIFO
(collab_common.h): the per-body fire-and-forget coroutine interleaved under
load — an asyncify park inside commit.Push let the event loop start the next
body, so a local commit and a remote apply ran interleaved on shared state
(s_applyingRemote is one global), silently losing applies on the actively-
editing receiver (fuzz finding #10a; B now fuzzes clean; 39-test suite green).

kicadCollabFiberBusy embind probe (merged + standalone registrations): a
bare-embind-stack scratch save during a parked fiber mis-dispatches (table
index OOB) — trio.ts modelText/drift and production drift-detect now defer
while fiber work is in flight (#10b hardening; the trap's root cause is still
open and needs a symbolized stack — fuzz stays fixme'd).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G5cAM9M6q34n5X4dbrfVvi
This commit is contained in:
Gergő Törcsvári 2026-07-21 12:22:09 +02:00
commit 3fc90e8fe2
No known key found for this signature in database
GPG key ID: 8E75F2CDE64E5322
6 changed files with 91 additions and 9 deletions

View file

@ -125,6 +125,11 @@ export function startDriftDetection(opts: DriftDetectOptions): DriftDetector {
// unchanged since the last report, or the session cap is spent). Being fully
// synchronous is what lets the session-end check finish during page unload.
function computeDrift(): DriftReportBody | null {
// Defer while collab fiber work is in flight (0008 finding #10b): a save
// on the bare embind stack during a parked apply fiber mis-dispatches
// (table index OOB). The next Y-update trigger retries.
const busy = (opts.mod as { kicadCollabFiberBusy?: () => boolean }).kicadCollabFiberBusy;
if (busy?.()) return null;
save(scratchPath);
let text: unknown;
try {