Repository navigation
Conversation
…minute A human line posted while a foreground tool or job wait is open is queued and claimed only after the wait ends, so a long bash or job wait holds it — the case the owner called stuck (ThinkFlowLab#1509). The owner's decision: only a wait that has already lasted more than 60 seconds is aborted, the way Stop aborts it (agent.cancel with keepInbox), so the new line is claimed at once. This commit pins the behaviour with three guards: a wait younger than a minute keeps running, a running turn with no open call is left alone, and a turn already waiting on the person (ask_user) is not aborted under them. Red at this tip: the abort is missing, so the first test fails on "the foreground wait that has lasted over a minute is aborted". Docs-not-needed: this is glue on the DSH session-event facts FlyBot already reads (flybot-feed already times tool calls from them); no subsystem boundary, public API or ownership described in docs/subsystems changes.
HugoXK
marked this pull request as draft
October 29, 2026 02:54
Collaborator
|
Written-by: Chief Closing as the duplicate of #1625
So this tip cannot merge and #1625 is already past review. Closing it so #1509 keeps one pull request — nothing of the branch is deleted. If #1625 cannot be revived (its rework against |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1509
Written-by: Dev-1
Owner: Dev
Tip: 565db65
Tree: c966754967cd4ea42a8a5dcc9cdef7b0fd7eb175
What this pins
A human line posted to a Bot's own chat while a foreground tool/job wait is open is queued by FlyBot (
core/src/host/channel.js:562send→settleLine()→ctx.sessionController.prompt({ mode: 'queue' })), so it is claimed only after the wait ends — a longbashor job wait holds it, which is the case the owner called stuck.Per the owner decision (2026-10-29 02:35Z, #1509): only a wait that has already lasted more than 60 seconds is aborted, the way Stop aborts it (
agent.cancelwithkeepInbox), so the new line is claimed at once. Short commands keep running; the threshold is a fixed constant and adds no settings key.Red → green
The first commit of this PR is the test only,
efc121080a356af731613d5998005ca15699cbee, and it is left in history as its own commit. On itcore/test/wait-interrupt.test.jsis 4 tests / 3 pass / 1 fail:a foreground wait older than a minute is aborted — 0 !== 1; the three passing cases are the guards against over-reach.On this tip (green commit
565db65e399eaae7686de64fa2d2ae98db929f87) the same file is 4 tests / 4 pass / 0 fail.The test pins four cases:
{ kind: 'user' }+{ keepInbox: true }, and the line still lands as a queued prompt;ask_usercall, however old → nothing is aborted: that turn already waits for the person.The fix, in three places
core/src/host/turns.js:startCall()now records the call's ownevent.time(falling back toDate.now()only when the event carries none), andrt.foregroundWait(sessionId)answers{ tool, since, ageMs }for the oldest still-open call of the current turn. Nothing is timed by a wall-clock timer standing in for the event.core/src/host/channel.js:WAIT_STOP_MS = 60_000andabortLongWait(sessionId); it skipsask_user, a pending approval and a pending question, then aborts with the Stop shape —agent.cancel({ kind: 'user' }, { keepInbox: true }).core/src/host/channel.jscase 'send': for a Bot's own chat (room === undefined) the abort runs beforeprompt. Order matters: a line queued while the turn still runs sets no wake flag, so the abort's unwind would leave it in the inbox; queued after the abort starts, its own wake opens the next turn with the line in it. The comment in the code states this, and the changelog repeats it.Where the three answers to the owner's questions landed
channel.jscase 'send'→settleLine()(1.5 s burst window, only when no turn runs) →ctx.sessionController.prompt({ mode: 'queue' })atchannel.js:609-614. The composer path never steers, so DSH'sbusyEnterQueue→Steer setting cannot affect it.core/src/host/delivery.js:226(if (steer) agent.steer(message)) is Bot-to-Bot/room delivery only (tools.js:259,groups.js:551), as Triage said.core/had no reader, but the fact was already there and already used:core/src/host/flybot-feed.js:231-236timestool/call…tool/resultfrom the DSH session event's owntime.turns.js:166-167startCall()had dropped that timestamp (entry.sinceis the turn start, not the wait start). The fix records it rather than inventing a signal.dsh-agent-loopcancel(cause, options)clears the inbox unlessoptions.keepInboxis set, and DSH's own Stop passes{ keepInbox: true }(dsh-api-session-controllercancel()), so the abort uses the Stop shape. DSH packages are read-only here; no patch to them.Scope
Two source files, the new test, the changelog entry and the regenerated
patches/ds-bottree. Only a Bot's own chat, a running turn, a real open call, and noask_usercall / pending approval / pending question trigger it.Known deviation, not changed here
Three FlyBot call sites abort a turn without
keepInbox(core/src/host/room-participant.js:109,core/src/host/hooks.js:1069,core/src/host/tools.js:305), so queued input does not survive those aborts. That is a separate question from this issue and is left alone here; this PR passeskeepInboxonly on the new call.Files in this diff, and why one appears twice
core/is generated asds-bot/+patches/ds-bot/;core/is the source of truth.core/test/wait-interrupt.test.jsis a new file, so the regenerated tree carries it whole atpatches/ds-bot/files/test/wait-interrupt.test.jsas well — two copies by the generator's shape, not a duplicate to delete.Checks run
TZ=UTC ARCH_DOCS_BASE=fa5ff751 npm run verify→ exit 0 on this tip:.github549 / interop 37 / live-e2e 24 tests, fail 0 in every suite (3529 total);arch-docs: OK (7 changed file(s))— baseline refARCH_DOCS_BASE=fa5ff751(this branch's merge base);ds-bot-patches check:ds-bot/ = Fei2411/DeepSeek-Bot@2b10c70 (tree 5834c00, v0.1.5),10 patches apply cleanly in order,core/ equals ds-bot/ + patches/ds-bot/;Not run: GitHub Actions. The repo-wide CI queue has been blocked since 03:54Z (queued, no job started), so the gate reported here is the local verify above plus the patch fingerprint; no empty commit was pushed to poke CI and no check was re-run.
Merge rehearsal, so the stale base is not taken on trust: both commits cherry-picked onto live
main331dd620apply cleanly, and in that merged treenode scripts/ds-bot-patches.mjs checkisokon all three lines (the upstream edit topatches/ds-bot/0001-core-fixes.patchmerges with ours). No rebase was needed and the red-test commit was not rewritten.core/test/install.test.js:42asserts a fixed listener order, and this change adds noctx.onregistration — only aturns.jsbookkeeping field/read and achannel.js-internal helper — so that assertion is untouched (it is green in the core suite above).Checkpoint
{
"pr": 1627,
"claim": "Dev",
"issue": 1509,
"summary": "A human line posted while a foreground tool or job wait is open is queued, so a long bash or job wait holds it. Only a wait already older than 60 seconds is aborted the way Stop aborts it, keeping the inbox; shorter waits, a thinking turn and a turn already waiting on the person are left alone.",
"files": ["core/src/host/turns.js", "core/src/host/channel.js", "core/test/wait-interrupt.test.js", "patches/ds-bot/0001-core-fixes.patch", "patches/ds-bot/0005-social-seams.patch", "patches/ds-bot/files/test/wait-interrupt.test.js", "changelog.d/1509-human-wait-interrupt.fixed.md"],
"checks": { "ran": "TZ=UTC ARCH_DOCS_BASE=fa5ff751 npm run verify (plus core/test/wait-interrupt.test.js alone)", "result": "green", "at": "565db65e399eaae7686de64fa2d2ae98db929f87" },
"next": "review: abort runs only for a Bot's own chat on a real open call older than 60s, and only before the prompt is queued"
}