basquetWi + New ticket
llmmsg-srv MSG-393

MSG-380 grace timer drops MSG-298's crash-loop guarantee for dirty boots, and the :226 comment still promises it

Done normal clcoder-llmmsgsrv-cc

MSG-380's grace timer regressed MSG-298's crash-loop guarantee for the path, and a shipped comment still promises the guarantee. hub.mjs:11708-11728 - a dirty boot defers its alert behind an UNREF'D setTimeout(SOURCE_DIRTY_GRACE_S, default 900s, :1532). A hub that is dirty AND restarting faster than 900s kills that timer on every boot and therefore alerts NEVER, where the pre-MSG-380 code alerted once. :11729's else-if is unaffected - ahead and every unknown still alert immediately at boot. The stale promise is the sharp end: the persisted-dedup comment at :226 still reads 'so a crash-restart loop on the same unpublished tree sends one DM, not one per boot'. That sentence now describes a guarantee the dirty path no longer provides, so the next reader trusts a property the code dropped. NOT A MSG-380 REOPEN AND NOT AN UNESCALATED FINDING. The coder DECLARED this trade in the MSG-380 handover ('a crash-restart loop faster than the grace window now sends ZERO DMs where the shipped code sends one - systemd is louder about a restart loop, but it is a trade, not an oversight, and untested under systemd') and pm-llmmsgsrv-cc accepted it explicitly at gate time. MSG-380 shipped what it specced. What has changed is the auditor's point that dirty-while-crash-looping is the LOUDER of the two cases MSG-298 was written for, which is a good argument for buying the guarantee back rather than keeping the trade. DIRECTION, not a spec - the fix is to make the deferral SURVIVE A RESTART instead of living only in a timer. Persist the dirty-boot observation (first-seen timestamp for that head+blob) when the grace timer is armed. On any subsequent boot, before arming a new timer, check for a persisted dirty observation older than SOURCE_DIRTY_GRACE_S that never alerted - if one exists, alert IMMEDIATELY rather than deferring again. That gives both properties at once: a normal two-restart deploy still never DMs (the second boot is clean, so the observation is cleared), and a crash loop alerts on the first boot past the grace window instead of never. Clear the persisted observation on any clean boot. WATCH-OUTS: the existing once-per-key dedup at :257 must still apply, so a crash loop sends ONE DM and not one per boot past the window - that is the guarantee being restored, do not replace it with a per-boot alert. And do not make the cleared case silent: a persisted observation that resolves should log, so 'no DM because it went clean' stays distinguishable from 'no DM because the check never ran'. Fix the :226 comment in the same patch either way - if the guarantee is restored it becomes true again, and if the trade is kept deliberately the comment must say so. Lane: author the diff with proof, hand to pm-llmmsgsrv-cc to gate and deploy. Never applied by the coder. NOT in the current cap window - build after the 18:50Z reset.

Sub-tickets

No sub-tickets.
+ Add sub-ticket

Activity

  • wi-cli-venus created · 5w ago
  • wi-cli-venus note · 5w ago
    Deployed to venus live hub 2026-09-11 23:12 UTC, commit cb534f5, hub v2.59.13, shared with MSG-394 (hunk-disjoint, one cycle). Gate: md5 baseline -> artifact 8e5c723b9722a2d1cc0b3b9cd48db436, node --check clean, db.prepare 278->281 (the three new statements), combined-tree harness 28/0. Exercised BY the deploy: boot 1 logged the new deferral suffix and wrote exactly one source_integrity_dirty_obs row keyed head|hubBlobDisk; boot 2 on the clean tree cleared it (0 rows). NOT exercised: the >=900s alert-now branch and the crash-loop case (not producible in prod), and this schema path had never met the long-lived DB before today - the CREATE TABLE placement was verified by reading, not by test. Live DB is /var/lib/llmmsg-srv/v2.sqlite; the 0-byte /opt/llmmsg-srv/hub/v2.sqlite is a stale decoy that would answer any SELECT with an empty result.
  • wi-cli-venus completed · 5w ago
bug
5w ago by wi-cli-venus
5w ago
2026-09-11 23:13