MAY 30 2026 / ONE STUCK SESSION, SIX CONDITIONS

Hugging Face new models or GitHub trending AI, May 30 2026. The shipment worth reading was a session that got stuck on “Compacting...” forever, and the six checks that freed it.

A trending feed will tell you which models existed at the end of May 30. It cannot tell you that one open-source agent spent the afternoon chasing a chat that resumed, printed “Compacting...”, and then never replied. This is that day told from the commit log: the exact log signature of the bug, the six conditions that separate a poisoned short-circuit from a model that simply said nothing, and why a recovery that was deleted two weeks earlier was safe to add back in this one narrow case.

M
Matthew Diakonov
9 min read

Direct answer, verified 2026-05-31

No platform publishes an official “May 30, 2026” list of new AI. Both Hugging Face and GitHub order discovery by a rolling trending score, not by calendar date. New work surfaces continuously across three live feeds: huggingface.co/models sorted by trending, huggingface.co/papers, and github.com/trending.

The record that genuinely carries the exact date is the commit log. The notable one for 2026-05-30: the open-source macOS agent Fazm cut two patch releases, v2.9.56 and v2.9.57, recorded in CHANGELOG.json. The headline change in v2.9.57 was a recovery for a resumed session that short-circuits and loops on “Compacting...” forever. The rest of this page opens that one fix.

What the log actually showed

The bug had a single, reproducible signature. A pop-out chat in session 0ea67ea0 resumed after a prior heavy turn had unwound a live subagent mid-flight. From then on, every resume of that session did the same four things and then stopped. This is the trace, condensed from fazm.log on 2026-05-30.

fazm.log — 2026-05-30, session 0ea67ea0

Read the fourth line carefully. The prompt resolved with stop reason end_turn in zero milliseconds, with zero output tokens and zero assistant text. That combination is not a model deciding to stay quiet. It is the Claude Code SDK underneath short-circuiting the turn without ever calling the model, and then reporting the dead turn as an ordinary success. The placeholder chunk had already streamed to the window, so the UI sat on “Compacting...” with nothing coming after it.

Why a tool that does not auto-compact still printed “Compacting...”

Fazm wraps Claude Code in a native macOS interface, and one of its design promises is that it does not compact a running conversation: while a chat window is open, the full history stays live in context for the lifetime of that window. So where did “Compacting...” come from?

From a different moment entirely. Persistent sessions survive a restart, and a chat can be popped out into its own window. Both of those are resumes, and on resume the conversation is handed back to the underlying SDK, which can choose to compact the restored transcript before it continues. That is normal and usually invisible. The May 30 failure was a narrow case where the resume path did not compact and continue; it compacted into nothing, returned an instant empty success, and stranded the window.

This is the honest version of the “no auto-compacting” story. The live window genuinely keeps everything. The seam is the handoff at resume, and the work on May 30 was hardening exactly that seam.

The hard part: an empty success that is real, versus one that is poison

You cannot just retry every empty end_turn. Per the Agent Client Protocol, end_turn is a success: a model is allowed to finish a turn without saying anything. Retrying that case is wrong, and worse, the retry replays prior context, which can destroy live tool, browser, and subagent state. So the recovery has to fire only on the one signature that proves the model was never called. That is six conditions, all true at once, in acp-bridge/src/index.ts.

acp-bridge/src/index.ts — [COMPACTION-POISON-RECOVERY]

Each condition is carrying weight. Remove any one and the guard either misses the bug or starts eating legitimate empty answers.

!isNewSession

A brand-new session that returns empty is a real empty answer. Only a resumed session can be poisoned by state the SDK carried over.

_retryDepth < 1

One-shot. If the fresh session also comes back empty, the recovery does not fire again. It falls through and delivers the empty result honestly.

stopReason === "end_turn"

The SDK reported success. Per ACP spec, end_turn means the model finished. That is exactly why a blanket recovery here is dangerous, and why the other five conditions exist.

fullText.length === 0

Not one character of assistant text streamed back. A model that actually ran almost always says something.

promptDurationMs < 50

The tell. A real API round-trip to a model takes longer than 50ms. A 0ms resolve means nothing was ever asked of the model.

outputTokens === 0

And it billed nothing. A legitimate empty turn that ran the model still reports output tokens. Zero confirms the short-circuit.

The two that do the real separating are promptDurationMs < 50 and outputTokens === 0. A genuine empty turn that actually ran the model needs a real API round-trip, which takes longer than 50ms and bills at least one token. A short-circuit resolves in zero and bills nothing. The clock and the meter are what make the distinction provable rather than a guess.

Why the same recovery was deleted two weeks earlier

This is the part the commit log tells you and a trending page never could: the May 30 fix is a re-add. A blanket version of empty-turn recovery existed before and was removed on 2026-05-13 (commit fad9af4f) for two good reasons. It was lossy, because replaying prior context tears down whatever MCP, browser, or subagent state is still live. And it was out-of-spec, because it retried a case the protocol defines as success.

So what changed to make it safe again? Nothing about the danger; only the precision of when it fires. At a 0ms, zero-token resolve, the session is already inert. The heavy turn that mattered ended long ago, and its subagent and tool state went with it. There is nothing live left to destroy by forcing a fresh session and replaying the context, because the thing the blanket version used to break is no longer running. The narrow signature is not a smaller version of the old fix. It is the one window in which the old fix's failure mode cannot occur.

The arc reads cleanly across three dates. On May 13 the blanket recovery came out. On May 29, v2.9.54 shipped a first attempt at the stuck-on-“Compacting...” symptom. On May 30, v2.9.57 added the signature-gated recovery for the resume short-circuit the earlier attempt missed. Three moves on one bug, each visible only because someone read the diff, not the leaderboard.

The rest of May 30, briefly

The stuck-session recovery was the headline, but it shared the day with five other changes across v2.9.56 and v2.9.57. They are worth a line each because they show where an open-source desktop agent actually spends its time.

  • Pop-out New Chat purge. A new chat opened from a popped-out window sometimes appeared already in a thinking or spinner state after a stuck turn. A helper now purges the stale streaming state on new-chat handoff (roughly +43 lines in ChatProvider.swift).
  • Phantom stall indicator cleared. A “tool not responding” indicator could reappear on the next prompt and show a healthy session as hung for thousands of seconds. A clearStallIndicator helper resets that stale state on stream error or timeout.
  • Knowledge graph went local. The Memory page had a dead no-op call to a remote knowledge-graph API. It was removed so a refresh re-reads local storage and recovers a stale database handle instead of doing nothing.
  • Gemini failover released. The transparent Claude-to-Gemini failover built the evening before reached users in v2.9.56, so a dead or rate-limited built-in key continues the chat instead of erroring.
  • Honest analytics. Empty or dropped replies are no longer counted as successful answers, which is the measurement that made the stuck-session bug visible in the first place.

How to read any project's real May 30 yourself

The method generalizes past Fazm. A trending feed tells you what existed at the end of a day; the diff tells you what someone decided, and why. Three artifacts, in order:

  1. Open the project's CHANGELOG.json or CHANGELOG.md at the root and read the entries dated 2026-05-30.
  2. Run git log --since=2026-05-30 --until=2026-05-31 --no-merges and read the messages, skipping the release-changelog commits.
  3. Pick one commit whose subject sounds load-bearing (here, “Add recovery for poisoned resume compaction stalls”) and run git show 3e4fb0cd to read the diff and the comment the author left for the next reader.

The comment block above the guard is the whole story in one place: the field-case session id, the deleted blanket version, and the reasoning for why this narrow re-add is safe. That is the kind of record a leaderboard cannot hold.

Resuming sessions and fighting empty turns in your own agent?

In twenty-five minutes we open the recovery commit, your resume path, and the line between a real empty answer and a poisoned one, and decide whether your stack needs the same signature gate.

Questions about May 30, 2026

Frequently asked questions

What new AI appeared on Hugging Face or GitHub on May 30, 2026?

Neither platform publishes a dated release list. Models, datasets, papers, and repositories surface continuously, ordered by a rolling trending score rather than by calendar date. Around that day the trending feeds leaned on the Gemma 4 and Qwen 3.6 open-weight families and continued momentum for DeepSeek-V4. But the record that genuinely carries the exact date is a tagged release or a commit log. The notable one for 2026-05-30: the open-source macOS agent Fazm cut two patch releases, v2.9.56 (16:21 Pacific) and v2.9.57 (17:50 Pacific). The headline change in v2.9.57 was a recovery for a resumed session that gets stuck on a "Compacting..." placeholder forever and never replies.

What was the "Compacting... forever" bug exactly?

A resumed chat would show the placeholder text "Compacting..." and then never produce a reply. The field case in fazm.log on 2026-05-30 was session 0ea67ea0: a prior heavy turn had unwound a live subagent mid-flight, and after that, every resume of the session emitted a status_change of "compacting", streamed the "Compacting..." placeholder chunk, then resolved the prompt with stopReason end_turn in roughly zero milliseconds, zero output tokens, and zero assistant text. The pop-out window looped on "Compacting..." with no reply and no way out. The Claude Code SDK underneath was short-circuiting the turn without ever calling the model, and reporting it as a normal successful end_turn.

Why does a tool that says it never auto-compacts still show "Compacting..."?

There is a real distinction. While a chat window is live, Fazm keeps the full history in context for the lifetime of that window; it does not compact a running conversation out from under you. The "Compacting..." status comes from a different moment: resuming a session that was persisted across a restart or popped out into a new window. On resume, the conversation is handed back to the underlying SDK, which can decide to compact the restored transcript before continuing. Normally that is fine. The May 30 bug was a narrow failure where that resume path short-circuited into a dead loop instead of compacting and replying.

How does the fix tell a poisoned short-circuit apart from a model that simply said nothing?

With six conditions that must all be true at once, in acp-bridge/src/index.ts under the comment [COMPACTION-POISON-RECOVERY]: the session is not new (!isNewSession), the recovery has not already run this turn (_retryDepth < 1), the stop reason is end_turn, the assistant text length is zero, the prompt resolved in under 50ms (promptDurationMs < 50), and output tokens are zero. The 50ms and zero-token checks are the load-bearing ones: a real model turn needs an API round-trip that takes longer than 50ms and emits at least one token, so a legitimate empty answer can never match. Only the SDK short-circuiting without calling the model resolves that fast with nothing billed.

Why is it safe to retry here when an earlier blanket version of this was removed?

A blanket empty-turn recovery was removed on 2026-05-13 (commit fad9af4f) because it was lossy and out-of-spec: replaying prior context destroys live MCP, browser, and subagent state, and ACP defines end_turn as a success, so retrying a legitimate empty answer is wrong. The May 30 re-add is safe precisely because of the 0ms, 0-token signature. At zero duration with zero output, the session is already inert: the heavy turn and its subagent or tool state ended long ago, so there is nothing live left to destroy by forcing a fresh session and replaying the context. The narrow signature is what lets the recovery exist without reintroducing the data loss that got the blanket version deleted.

Was this the first attempt at fixing the "Compacting..." stall?

No, it was the third move in a sequence. On 2026-05-13 a blanket recovery was removed for being lossy. On 2026-05-29, v2.9.54 shipped a first fix described as stopping pop-out chats from getting stuck on "Compacting..." and never replying when the conversation auto-compacted. The 2026-05-30 work, released as v2.9.57, was the narrow, signature-gated recovery for the specific resume short-circuit that the earlier fix did not cover, plus a separate fix for pop-out New Chat opening already in a spinner state after a stuck turn.

What else shipped on May 30, 2026?

v2.9.56 carried four other changes from the same day's commits: the Claude-to-Gemini failover built the evening before was released to users, scheduled routines that previously never ran now fire on time while the app is open, a phantom "tool not responding" indicator that showed a healthy session as hung for thousands of seconds was cleared (a clearStallIndicator helper, roughly +33 lines in ChatProvider.swift), and the Memory page's dead no-op knowledge-graph API path was removed so a refresh re-reads local storage and recovers a stale database handle instead of doing nothing. Analytics were also corrected so empty or dropped replies are no longer counted as successful answers.

Where do I find the actual files this page cites?

github.com/mediar-ai/fazm is the public repo. The recovery lives in acp-bridge/src/index.ts, added in commit 3e4fb0cd ("Add recovery for poisoned resume compaction stalls", +80 lines) under the [COMPACTION-POISON-RECOVERY] comment, near the matching DEBUG_POISON_EMPTY_RESUME_FILE test hook. The user-facing notes are in CHANGELOG.json at the repo root under versions 2.9.56 and 2.9.57. The pop-out New Chat purge and the clearStallIndicator helper are in Desktop/Sources/Providers/ChatProvider.swift.

How did this page land for you?

React to reveal totals

Comments ()

Leave a comment to see what others are saying.

Public and anonymous. No signup.