Skip to content

feat(coding-agents)!: drop retainEveryTurns — batching belongs on the server - #3415

Merged
nicoloboschi merged 1 commit into
mainfrom
fix/coding-agents-drop-retain-every-turns
Aug 12, 2026
Merged

feat(coding-agents)!: drop retainEveryTurns — batching belongs on the server#3415
nicoloboschi merged 1 commit into
mainfrom
fix/coding-agents-drop-retain-every-turns

Conversation

@nicoloboschi

Copy link
Copy Markdown
Collaborator

Removes the write-back cadence. The persistent-plugin harnesses (opencode, Kilo, Cline CLI) now write back every turn — which the default of 1 already did — and the seven hook harnesses never consulted it at all.

Why remove rather than document

I documented the asymmetry two days ago (#3380) and it still reads as a half-working setting: honoured by three of eleven harnesses. The reason it can't be made whole is now measured rather than assumed.

A client-side cadence holds turns in a process the host can close at any moment, and there is no reliable signal on the way out. #2869 measured zero SessionEnd retains across 36 hours, because Claude Code cancels that hook at shutdown. The flush a cadence needs would have to ride exactly that event, so extending the setting to the hook harnesses was never actually available — a cadence there would strand every session that ended below the threshold.

What replaced it

The batching it approximated now happens server-side, where nothing can be stranded. Queued retains for one document fold into a single execution (engine.retain.fold, #3395), on top of a claim predicate that serialises same-document work:

a client that buffers 50 turns offline and flushes them would run 50 sequential retains, each re-reading and reprocessing the document. Folding collapses that burst into one execution over the concatenated turns.

with the property a client-side cadence can't offer:

folding is a pure optimization: delete it and the system is still correct, only slower. […] it cannot lose a turn.

So submitting every turn costs one extraction over the concatenated turns, not one per turn. That is the burst control #2143 asked for, in the only place that can do it without risking a turn — and it supersedes what I told that reporter when I closed it, which was to reach for the cadence knob.

Scope

retainSessions stays — opting out of write-back entirely is a different question from how often it fires.

Removed: the config field, the resolved field, the default, HINDSIGHT_RETAIN_EVERY_TURNS, its ENV_NUMBERS entry, the runtime.ts cadence check, the retainedUsers bookkeeping that had no reader left, the settings-table row, and the tests that pinned the old behaviour.

The other integrations' retainEveryNTurns is a different setting in different packages (openclaw, opencode, codex, cursor, omo, zcode, copilot-cli, claude-code, hermes) and is deliberately untouched, as are the historical blog and changelog entries that mention it.

Test

455 passed, 21 skipped; tsc, lint and check-unused clean. The cadence test became its inverse — a single-turn session now writes back immediately instead of being suppressed — and the env-parsing test moved to another numeric field. Docs regenerated from the README through sync-coding-agents-doc.mjs plus the skill mirror.

Marked ! because a config key disappears: a config that still sets it is ignored rather than rejected, so nothing breaks, but the behaviour changes for anyone who had raised it above 1.

…server

The write-back cadence is removed. The persistent-plugin harnesses (opencode,
Kilo, Cline CLI) now write back every turn, which is what the default of 1
already did; the hook harnesses never consulted it at all.

Two reasons, and the second is what makes it a removal rather than a
documentation fix.

A client-side cadence holds turns in a process the host can close at any moment,
and there is no reliable signal on the way out: #2869 measured ZERO SessionEnd
retains across 36 hours because Claude Code cancels that hook at shutdown. The
flush a cadence needs cannot be built on the only event that would carry it, so
extending the setting to the seven hook harnesses was never available — and the
asymmetry that left (honoured by three of eleven) was itself the complaint.

The batching it approximated now happens server-side, where nothing can be
stranded: queued retains for one document fold into a single execution
(`engine.retain.fold`, #3395), on top of a claim predicate that serialises
same-document work. Submitting every turn therefore costs one extraction over
the concatenated turns rather than one per turn — the burst control #2143 asked
for, in the place that can do it without risking a turn.

`retainSessions` stays: opting out of write-back entirely is a different
question from how often it fires.

Removed from the config type, the resolver, HINDSIGHT_RETAIN_EVERY_TURNS, the
runtime check and its now-unread retainedUsers bookkeeping, the settings table,
and the tests. The other integrations' `retainEveryNTurns` is a separate setting
in separate packages and is untouched.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant