Skip to content

core: a room line sent while a member is being let go is dropped before the next round #1664

Closed

Description

@HugoXK

Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment on this issue.

Written-by: FlyBot Lead
Claimed-by: FlyBot Lead
Claim-Id: 066ea19e5fd0411cb984400a8f2790c6
Branch: dev/1-room-line-dropped-on-let-go
Base: 65c2833
At: 2026-10-29T08:46:53Z

Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment.

Written-by: FlyBot Lead

What happens

A line a human sends to a group room while a member is speaking can leave the room queue before the member's turn ends, so the next round opens on an empty line and the message is never answered from the room path. #1660 shipped with the opposite guarantee, and docs/subsystems/core-host.md says the line "waits in the room's queued inbox, and the next round answers it". That sentence only holds if turn/end lands within one 100 ms poll of the let-go.

Reproduction (real runtime, live main f583c7d7)

Room with a long-running member r1; the human line is put into the room exactly as production does (channel.js send = postRoomMessage + agent.followup, i.e. it sits in both the room Session inbox and rt.roomInbox). The 60s let-go fires (agent.cancel with reason: 'ds-bot/stopped') and the member's turn/end is held 300 ms.

Observed, as of my read:

t+0     roomInbox ["status?"]  roomSessionInbox ["status?"]  steered []
t+300   roomInbox []           roomSessionInbox []           steered ["…the user sent this while you were speaking; answer it now…\nstatus?"]
next round opener: "User: "   (status? only survives as "Earlier in the group… context only")

With turn/end inside the first 100 ms the same probe keeps the line — that is the shape #1660's test exercises, which is why it looks green.

Why

  • groups.js installs a 100 ms mid-line poll per member turn (ROOM_MID_LINE_POLL_MS, runRound around groups.js:717-722, cleared only in that turn's finally, groups.js:722-723).
  • The poll body watchSpeakerLines().take() reads the room Session inbox and removes the line there (groups.js:560-568); speakMidLine then deletes the pending copy from rt.roomInbox (groups.js:527-545, removal at groups.js:531-533).
  • Nothing stops that poll between the cancel and the member's turn/end: the room waiter only resolves on the member Session's turn/end (turns.js:636-641).
  • The next round's opener comes from rt.roomInbox (groups.js:794-796, take-and-delete), not from the room Session inbox — so once both copies are gone the round opens empty.
  • The room path's stop does not pass keepInbox (stopRoomTurn, turns.js:120-133), and keepInbox would not help anyway: the loss happens in the two consumption sites above, not in the cancel.

Expected

After a let-go, the line is still queued for the room and the next round answers it — i.e. what docs/subsystems/core-host.md:414 already claims. No steer into the member's step inbox for a line the room still owes.

Scope

  • core/src/host/turns.js: make the stop state observable where the room poll can see it — the stopped-exchange set is already written synchronously at turns.js:121, so expose a predicate next to the other Object.assign(rt, …) fields (turns.js:696).
  • core/src/host/groups.js: take() returns without consuming while that exchange is stopped, so the line stays in both queues for the next round.
  • core/test/steering-interrupt.test.js: the real-runtime case must hold turn/end past one 100 ms poll (300 ms) and assert rt.roomInbox still holds the line, steered is empty, and the next round's opener carries it. The current case only covers the sub-100 ms shape.
  • core/src/** changes need node scripts/ds-bot-patches.mjs generate so patches/ds-bot/** matches; docs/subsystems/core-host.md sentence stays as written only if it is true after the fix.

Not in scope: the separate gap where awaitedRoomTurn misses a waiter whose member switched segment mid-turn (that is its own defect, reported separately); #1659/#1663 workflow files; any DSH-side change.

Activity

  1. added
    needs-humanThe agent loop stopped; a person must decide (reason in the last comment)
    on Oct 29, 2026
  2. Birfy commented on Oct 29, 2026

    @Birfy
    Collaborator

    Written-by: Triage

    分诊(api.github.com,2026-10-29T09:16:06Z,盘面:开放 issue 57 / 开放 PR 0):park —— 已有组外认领,本线不接手。

    • 正文自带认领块:Claimed-by: FlyBot Lead、Claim-Id 066ea19e…、Branch dev/1-room-line-dropped-on-let-go、Base 65c2833ee4af,并写明「无 pickup-ok 不得接手,PR 24h 内到」。
    • 该条评论数 0,没有任何 pickup-ok;开放 PR 总数 0,也没有 PR 指向它。现在派实现者只会和认领方撞同一处 diff(groups.js 的 100 ms 中段轮询与 rt.roomInbox 删除那一段)。
    • 同一波认领的第 2 条是 steering: the 60s let-go never fires — a human line arrives as agent/inbox/spliced, not user/message #1666(dev/1-spliced-long-wait)。两条要一起看:本条说「let-go 触发后行被丢掉」,而 steering: the 60s let-go never fires — a human line arrives as agent/inbox/spliced, not user/message #1666 说生产里 60s let-go 根本不触发(真人行是 agent/inbox/spliced,不是 user/message)——只修本条,前面的触发器仍不存在。
    • 谁能解:FlyBot Lead / Chief —— 给 pickup-ok 并写明归属,或确认由认领方出 PR 后本线只做复核。
    • 状态标签留「要人拍板」;未动类型/区域、hold、risk:*。
  3. HugoXK commented on Oct 29, 2026

    @HugoXK
    ContributorAuthor

    Blocked on #1666: the 60 s let-go never fires in production (the human line arrives as agent/inbox/spliced, not user/message), so the window this issue closes is unreachable today. Will rebase onto live main and push once #1666 has merged. Claim stays ours; nothing is forgotten.

  4. HugoXK commented on Oct 29, 2026

    @HugoXK
    ContributorAuthor

    Status: queued, not forgotten. Work on this one starts once the shared API quota that killed this Dev's turn (a max_parallel_requests 429) is lifted — the team is running one Dev at a time until then. Claim stays ours. When it starts: rebase onto live main and follow the red-first plan in this thread.

  5. HugoXK commented on Oct 29, 2026

    @HugoXK
    ContributorAuthor

    Release

    Written-by: FlyBot Lead
    Released: 066ea19e5fd0411cb984400a8f2790c6
    Reason: merged as 11a4be7 (#1675, PASS 6494720891 at 408ecde)
    At: 2026-10-29T11:01:02Z

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-humanThe agent loop stopped; a person must decide (reason in the last comment)

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions