v0.57.0

feder-cr/invisible_dotsv0.57.0Sep 14, 2026by github-actions[bot]

Upgrading?

AI Summary

Fixes a critical bug where the `/chat/fresh` command caused queued messages to be lost during stream reconnections or server restarts. It also corrects the handling of state (such as `fresh` and `busy`) to ensure they are treated as ephemeral state rather than conversation history.

Key Highlights

  • Fixes data loss where queued messages were deleted when a stream reconnected from a position before the stored `fresh` event.
  • Corrects the logic to treat `fresh` as state (like `busy`) rather than conversation history, preventing it from being written into the transcript.
  • Ensures the live path remains untouched to maintain consistency between browser tabs.
  • Restores the filtering logic to properly handle state transitions.

New Features

  • Improved stability of the `/chat/fresh` command to prevent message loss during reconnection.

Full Release Notes

Found by reading a real saved file, not by a test. The developer's default
conversation held exactly one event in its transcript, and it was `fresh` - the
word that tells every open tab to drop what it is showing.

/chat/fresh clears the history and then emits `fresh` so that two tabs on one
conversation agree. `emit` wrote everything but `busy` into the history, so that
word landed in the transcript it had just emptied and became the only thing a
cleared conversation had written down.

What it costs is the one thing this interface says everywhere it must not do. A
replayed `fresh` runs wipe() in the page, and wipe() calls setQueued(null). So
somebody who typed a follow-up while the agent was working, on a conversation
cleared at any point in its past, lost that sentence the moment the stream
reconnected from a position before the stored event - which is exactly what a
server restart produces. Nothing said so, and the queued message is the one copy
of what they wrote.

`fresh` is state, not conversation, the same as `busy`: it is told to whoever is
listening NOW and does not belong in what is written down. Both are named
together in one place instead of one being a special case beside the other.

The live path is untouched, which is what makes two tabs still agree: the route
emits it and every current listener wipes. A page that arrives LATER needs no
command, because what it is handed is already the empty transcript the command
would have produced.

Suite 602 green. Two known-bad inputs, two killed: `fresh` allowed back into
what is recorded, and the filter dropped entirely so state is written down.

Related Repositories