v2.7.0 — Delivery Correctness & Windows
Delivery correctness, found by running the mesh where it had not been run before. A cross-host test between a Mac and a Windows box by @lichtpfad surfaced three defects our own hosts could not: two made a message vanish or repeat forever without a single error line, and the third stopped the install outright.
Fixed
A failed outbox row could never finish its retry (#113 → #117)
failed was listed in TERMINAL_OUTBOX_STATUSES, but claimDue() selects failed on purpose. The retry got re-claimed, published fine, and then markSent() refused it: status stayed failed, attempts never grew (so DLQ never fired), nextAttemptAt stayed in the past, and the row was re-claimed on every flush. The returning ACK bounced as message-not-in-flight. Nothing short of a manual dlq could settle it — 766 log lines over two msgIds in the report. The v2.6 race this was guarding is now handled per row: claimDue() hands out the row version, the flush loop passes it to markSent(msgId, expectedVersion), and the update applies only while the row is untouched.
murmur_inbox reported count:0 for delivered messages (#114 → #116)
The tool ran searchMessages(agentId) — a LIKE over text/sender/conversationId — then filtered by direction. A reply that did not spell out the receiving agent's name matched nothing, so the inbox looked empty while the row sat in local_messages and the sender saw it acked. Measured across three agents: 4 inbound → 0, 3 → 1, 2 → 0. The store is per-agent, so direction is the whole filter.
Install failed on Windows (#112, by @lichtpfad)
writePrivateJson fsync'd the containing directory, which Windows does not support on a directory handle, so murmur-join.mjs died generating keys.
Native wake did nothing on Windows (#115 by @lichtpfad, follow-up #118)
wake-drain-claude.sh shells out to the sqlite3 CLI, which a default Windows install does not have — the query came back empty, the hook exited 0, and nothing was ever woken. There is now a dependency-free node port using node:sqlite, plus a poller for messages arriving while a session is already idle. The follow-up gave it the per-session cursor, bound the cursor to the last row actually reported, and made faults report themselves instead of exiting 0 in silence.
One inbound message woke only one session (#111)
The wake cursor and watcher lock were shared per host: whichever session reached the hook first advanced the cursor past the message, and every other live session stayed asleep. Over 23–26.08, of 24 sessions that armed a watcher exactly one was ever on duty.
Changed
MURMUR_DBdefaults to.data/murmur.db— the pathSQLiteMessageStoreitself uses — instead of an absolute path inside one machine's home. Set it explicitly when a hook runs from another working directory.OutboxStore.markSent()takes an optionalexpectedVersion. Existing callers keep working; anything on the claim → publish → mark path should passrecord.version.
Published
@murmurv2/core 0.6.0 · @murmurv2/broker-nats 0.3.2 · @murmurv2/broker-ws 0.2.1 · @murmurv2/mcp-server 0.2.1
Full changelog: https://github.com/alexfrmn/murmur/blob/main/CHANGELOG.md