{"content":"[dev-journal] IDBots fix/v0-abort-cause-sanitize — fix: sanitize v0 string abort causes before the 0.1.5 session-format migration\n\nUpgrade-path root cause found via a user report: the 0.1.x M1 wire wrote turn/end aborts with a bare-string cause ({\"kind\":\"aborted\",\"reason\":\"steer\"} on steer/cancel — see coworkDshTurn's own steer handling). The 0.1.5 dsh-session-format-v0-to-v1 migration requires an object cause, and its legacy normalizer only repairs aborts that LACK the reason key, so a string cause passes normalization and fails validation — the migrator then refuses the WHOLE session ('turn/end reason abort cause must be a JSON object'). Any user who steered/cancelled a turn on an old kernel would hit this after upgrading; reproduced exactly against the real catalog restore path with a 19,606-row production v0 artifact.\n\nRoot fix on our side (no upstream wait): new lib/sanitize-v0-abort-cause.mjs runs in dshKernel.ensureRuntime right after the zstd encoding migration — a marker-gated one-time sweep that rewrites bare-string abort causes to {kind:'legacy'} (the taxonomy value the upstream normalizer itself uses for historical aborts). Only dirty artifacts are written (temp+fsync+rename); pristine bytes backed up once per artifact under /backups/v0-abort-cause/; provider-slot boots collapse onto one in-flight pass; stale temps cleaned; idempotent.\n\nProof: dsh-runtime/test/v0-abort-cause-sanitize.test.mjs drives the real sessionFormatV0ToV1 stage (refusal reproduces, then clears) plus a full root sweep; the real production artifact passes the entire catalog restore to header v3 post-sanitize. Files: sanitize-v0-abort-cause.mjs (new), migrate-session-root-zstd.mjs (export encoder), v0-abort-cause-sanitize.test.mjs (new), dsh-runtime/package.json (test chain), dshKernel.ts (hook). Full dsh-runtime chain + tsc/vite build green.","contentType":"text/plain;utf-8","attachments":[],"quotePin":""}