Skip to content

patch-cc 0.2.3 — repair the 2.1.226 reducer drift

Choose a tag to compare

@anfreire anfreire released this 09 Aug 23:29
· 30 commits to main since this release

Repairs live-thinking on Claude 2.1.226. On that build the patch was
dropped at bake time, so a patched binary silently lost live thinking. Re-run
patch-cc (or patch-cc apply --from-cache) to get it back.

What broke

2.1.226 threaded a new progress flag through the stream reducer: a second
declarator appended to the head's let (let{...}=t,d=...;) and five arm
bodies rewritten from stmt1,stmt2; into if(stmt1,stmt2,d)call;. The
handler matcher hard-required }=t;, so the reducer was never recognised and
every required step reported nothing — while all four anchor strings sat
healthy in the bundle, which is exactly what the release-watch ledger saw. The
arm rewrites had separately, and silently, killed the message_stop literal
pair.

The fix

The reducer rewrites no longer model anything the minifier owns — the same
doctrine as 0.2.2's ARRAY_CALL repair, applied to control flow:

  • The head is bounded at the grammar's declarator edge ((?=[;,])): after
    let{…}=t only ; or , can follow in a minified bundle, and which one is
    noise.
  • reducer-destructured and reducer-inner collapse into one
    reducer-options step — the options bag carrying onStreamingThinking or
    not is the same shape with the prop present or absent, reused or threaded on
    one code path.
  • Every arm-body literal (~15 enumerated spellings) is gone. Each state update
    is an insertion at the dispatch point: after a case label chain, or
    wrapping the dispatch test itself as (test&&((update),!0))
    value-preserving, so any surrounding composition survives unread. A
    2.1.226-style body reshape is invisible to the patch now.
  • Each dispatch point is its own named step (request-start, message-stop,
    text-clear, message-delta-clear, thinking-start, thinking-append):
    a folded-away arm reads as that point's absence by name, and
    live-thinking's counts are uniform across every supported build —
    deviation is signal, not noise.

The playbook records the rule: rewrite at the dispatch point; never model
the arm.

Housekeeping: the codebase conforms to ruff 0.16's widened default rule set,
and the lockfile picks up the refreshed dev toolchain.

Verification

doctor green against all ten pristine backups, 2.1.216 → 2.1.226, with
uniform counts on every build; the fully patched 2.1.226 bundle passes
node --check; and the rewritten reducer from every build was executed
against a synthetic stream and passes the state-machine checks — clear on
request start, virtual message on block start, delta accumulation, redacted
data, end timestamp on stop.

No new options; upgrading matters if you are on 2.1.226 or later.

Full changelog: v0.2.2...v0.2.3