feat(coalesce): give the batching lane the Discord summon path #975

Merged
coilysiren merged 2 commits from aos/claude/coalesce-discord-lane into main 2026-08-18 19:54:09 +00:00
Member

Closes #958.

The coalescing lane landed runnable and measurable in a325437 and nothing on the Discord summon path called it, so a member's rapid comments still queued behind the one execution slot at agent.go:193. This wires it in.

What is here

SIRENS_ECHO_COALESCE_ENABLED selects the lane. It defaults off, so the serial slot is still the shipped behaviour and the flag is the rollback path. With it on, ingress builds the turn and marks the comment, the window batches per member, and a pool worker runs the one turn that answers the batch.

The tuning #958 asked for arrives as SIRENS_ECHO_COALESCE_* knobs through the same overridable helper as everything else, with the high-water mark derived from the pool and the narrow batch rather than set beside them. task/free-the-config-numbers has since merged, which is what had blocked this.

Turn shape: the comment that arrives last carries the reply, the earlier ones folding into what it asks in arrival order and in the member's own words, and the transcript reads from before the oldest of them so no comment is history for itself. Uploads on every folded comment are carried. Dedupe collapses the work rather than the asks, so a repeated question is answered once and both comments are marked.

Three decisions #958 did not specify

  • No COALESCE_DEADLINE knob. The pool's hard bound on one turn is SIRENS_ECHO_REQUEST_TIMEOUT. A second ceiling underneath it would cut turns the service otherwise allows, and this keeps one number moving the whole shape the way sirens-echo#942 set up.
  • The pending cap is not charged while the lane is on. SIRENS_ECHO_MAX_PENDING bounds the wait for the execution slot and there is no slot to wait for, so SIRENS_ECHO_COALESCE_CAPACITY is the backlog bound and sheds where the cap refused. The per-user, per-context, and global tiers are unchanged and still charged on arrival.
  • The pool's escalation ladder does not fire. The turn owns its model retry and its own failure notice, so stacking the ladder on top would spend a second completion on a member who has already been told. Only a shutdown dead-letters a batch, which marks and says nothing because the gateway a reply needs is what is closing. Tier and escalation stay the bridge's.

The batch worker carries the same panic guard the serial handler has, so a crashed batch does not take down a deployment serving other guilds.

Against the freeze

#929 as amended releases work that changes only how well the agent does what it already does. Landing this changes nothing at all: with the flag off the summon path is byte-for-byte the path it is today. What would change member-visible behaviour is turning the flag on, and that is a coilyco-bridge/deploy decision rather than this diff. Read that way this is an operational improvement with its rollback identified before it lands, and the frozen half is the flag flip. Flagging it rather than deciding it: if the read is that a new lane is a capability regardless of its default, this waits for August 20.

Opened as a pull request rather than merged, although the repository is on merge-remote-main until August 20, because this touches the demo service's summon path 34 hours before a live recording.

Verification

just gate passes: build, policy-check, vet, test, test-skips, pre-commit. go test -race ./... is clean. New tests cover the folded ask, the history anchor, the folded uploads, the dedupe, the reply target, the once-only hold, the knobs reaching the policy, and three rapid comments reaching one batch under the shipped numbers.

Not verified against a live Discord guild. Nothing in this change has run against a real gateway.

🤖 Generated with Claude Code

Closes #958. The coalescing lane landed runnable and measurable in a325437 and nothing on the Discord summon path called it, so a member's rapid comments still queued behind the one execution slot at `agent.go:193`. This wires it in. ## What is here `SIRENS_ECHO_COALESCE_ENABLED` selects the lane. **It defaults off**, so the serial slot is still the shipped behaviour and the flag is the rollback path. With it on, ingress builds the turn and marks the comment, the window batches per member, and a pool worker runs the one turn that answers the batch. The tuning #958 asked for arrives as `SIRENS_ECHO_COALESCE_*` knobs through the same `overridable` helper as everything else, with the high-water mark derived from the pool and the narrow batch rather than set beside them. `task/free-the-config-numbers` has since merged, which is what had blocked this. Turn shape: **the comment that arrives last carries the reply**, the earlier ones folding into what it asks in arrival order and in the member's own words, and the transcript reads from before the oldest of them so no comment is history for itself. Uploads on every folded comment are carried. Dedupe collapses the work rather than the asks, so a repeated question is answered once and both comments are marked. ## Three decisions #958 did not specify * **No `COALESCE_DEADLINE` knob.** The pool's hard bound on one turn is `SIRENS_ECHO_REQUEST_TIMEOUT`. A second ceiling underneath it would cut turns the service otherwise allows, and this keeps one number moving the whole shape the way sirens-echo#942 set up. * **The pending cap is not charged while the lane is on.** `SIRENS_ECHO_MAX_PENDING` bounds the wait for the execution slot and there is no slot to wait for, so `SIRENS_ECHO_COALESCE_CAPACITY` is the backlog bound and sheds where the cap refused. The per-user, per-context, and global tiers are unchanged and still charged on arrival. * **The pool's escalation ladder does not fire.** The turn owns its model retry and its own failure notice, so stacking the ladder on top would spend a second completion on a member who has already been told. Only a shutdown dead-letters a batch, which marks and says nothing because the gateway a reply needs is what is closing. Tier and escalation stay the bridge's. The batch worker carries the same panic guard the serial handler has, so a crashed batch does not take down a deployment serving other guilds. ## Against the freeze #929 as amended releases work that changes only how well the agent does what it already does. **Landing this changes nothing at all**: with the flag off the summon path is byte-for-byte the path it is today. What would change member-visible behaviour is turning the flag on, and that is a `coilyco-bridge/deploy` decision rather than this diff. Read that way this is an operational improvement with its rollback identified before it lands, and the frozen half is the flag flip. **Flagging it rather than deciding it**: if the read is that a new lane is a capability regardless of its default, this waits for August 20. Opened as a pull request rather than merged, although the repository is on `merge-remote-main` until August 20, because this touches the demo service's summon path 34 hours before a live recording. ## Verification `just gate` passes: build, policy-check, vet, test, test-skips, pre-commit. `go test -race ./...` is clean. New tests cover the folded ask, the history anchor, the folded uploads, the dedupe, the reply target, the once-only hold, the knobs reaching the policy, and three rapid comments reaching one batch under the shipped numbers. Not verified against a live Discord guild. Nothing in this change has run against a real gateway. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(coalesce): give the batching lane the Discord summon path
Some checks failed
ci / test (pull_request) Failing after 52s
ci / publish-echo-image (pull_request) Has been skipped
ci / publish-observed (pull_request) Has been skipped
ci / image-build (pull_request) Successful in 45s
d111f7268f
The lane landed runnable and measurable and nothing on the summon path
called it, so a member's rapid comments still queued behind one execution
slot. `SIRENS_ECHO_COALESCE_ENABLED` now puts the path on it: ingress
builds the turn and marks the comment, the window batches per member, and
a pool worker runs the one turn that answers the batch.

Off by default, so the serial slot stays the shipped behaviour and the
flag is the rollback. The lane's tuning arrives as SIRENS_ECHO_COALESCE_*
knobs with the high-water mark derived from the pool and the narrow batch,
which is what config.go being mid-flight had blocked.

The newest comment carries the reply and the earlier ones fold into what
it asks, with the transcript read from before the oldest so no comment is
history for itself. The pending cap is not charged while the lane is on,
because there is no execution slot to wait for and the bounded queue sheds
where the cap refused. The pool's ladder is not stacked on the turn's own
retry and failure notice, so only a shutdown dead-letters a batch.

Closes #958.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Merge remote-tracking branch 'origin/main' into aos/claude/coalesce-discord-lane
All checks were successful
ci / image-build (pull_request) Successful in 32s
ci / test (pull_request) Successful in 1m0s
ci / publish-echo-image (pull_request) Has been skipped
ci / publish-observed (pull_request) Has been skipped
3a05e21d12
Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-gaming/sirens-echo!975
No description provided.