Repository navigation
Description
Symptom
A schedule that the owner can see in the UI is not visible to the Bot that owns it: schedule_list answers for the session the call is made from, not for the Bot, and an empty answer is indistinguishable from "this Bot has no schedules at all".
On 2026-10-21 this produced a wrong conclusion in both directions:
- The Chief asked the team in a group chat who had scheduled rounds. Several Bots answered "0 timers", and the Chief concluded that the "every hour at :07 / :10 / :20 / :40" rounds had never existed. The owner then sent a screenshot of the UI showing scheduled tasks under Dev and Triage.
- Earlier the same day the reverse happened in this session:
schedule_listreturned one entry here, while a schedule the owner had created for this Bot lived in a different session of the same Bot and was invisible from this one. We came close to deleting and recreating a live schedule on the strength of "my list is empty".
Evidence
schedule_listcalled from this session returns exactly one entry (schedule-10f8d340-8c0a-4e0e-a03b-57ce3c7d482c, cron10 * * * *, Asia/Shanghai), while the owner's UI shows schedules under Dev and Triage.schedule_listfrom the Chief's session returns[]— correct for the Chief, but it was read as "the team has no timers".- The same call from a group turn and from the Bot's own-chat turn are not equivalent: the group turn is treated as
otherorigin, so the whole turn runs on a degraded view (same family as Secrets:$DSH_SECRET_*can be empty on an ordinary turn of a shared Bot's own chat — per-session/turn context, not only scheduled turns (extends #581) #601 —$DSH_SECRET_*present at 12:04Z, absent at 11:49Z in the same group chat). - Owner's UI screenshot (2026-10-21) showing scheduled tasks for Dev and Triage.
Impact
A Bot cannot introspect its own scheduling. Because the failure mode is a plain [] rather than an error, the model rationalises it — "schedule must have been lost when the session rolled over" — and reports something the owner has to correct. In this case it nearly caused live timers to be cleaned up and rebuilt, and it produced a written-in-the-group claim that a schedule that exists does not.
Expected behaviour
One of:
schedule_listlists every schedule that belongs to the Bot's workspace (id, title, next occurrence, state, and owning session), regardless of which session the call runs in; or- it keeps session scoping but says so: the response names the session it answered for and states that schedules in other sessions of the same Bot are not included — so an empty list can never be read as "nothing is scheduled"; or
- it refuses with an explicit "schedules are managed by the UI scheduler and are not visible to a Bot" instead of returning the same empty array as a genuinely empty list.
schedule_delete / schedule_update should follow the same scoping rule, so a Bot cannot "clean up" a schedule it cannot see.
Scope
The fix is on the DSH/harness side (schedule_list and its session scoping). Inside this repository the only actionable part is a rule for the Bots themselves: an empty schedule_list is not evidence that a schedule does not exist; never delete or recreate a schedule from it, and never report "no timers" as a finding — that belongs in AGENTS.md and the maintenance skill.
Status
needs-human: the real fix is outside the repository, and the repo-side half cannot be tested in CI beyond a documentation change. The owner/DSH side has to decide between the three options above.
Related: #601 (the same "degraded turn view" family), #591 (documented the secret-injection boundary for scheduled turns).
Activity
Birfy commentedon Oct 21, 2026
Owner decision (2026-10-21), relayed by Chief: option 2 — keep the session scoping, but make the response say which session it answered for and that schedules of the same Bot living in another session are not included.
Checked where the fix would land:
schedule_listis a DSH runtime tool; this repository only wraps the schedule service incore/src/host/schedules.js("DSH's schedule service stores each task with the Session it belongs to"), so options 1 and 2 are both outside the repository. That half staysneeds-human.The repository-side half lands now: the rule "an empty
schedule_listis not evidence that a schedule does not exist" goes intoAGENTS.mdand the maintenance skill.docs: a schedule is per session, not per Bot (#628)
Birfy commentedon Oct 21, 2026
Repo-side half is in review: #632. It documents the boundary in
AGENTS.md(Routines → "A schedule is per session, not per Bot", plus hard rule 6 for agents) with the owner-approved wording: an emptyschedule_listis not evidence that a schedule does not exist; never delete or recreate a schedule from it, never report "no timers" as a finding.Only
AGENTS.mdis touched: this repository has no maintenance skill to update (.claude/skills/holdsfix-issueandreview-pronly), so the rule lives in the authoritative doc instead of a skill file — say the word if you want amaintainskill created and the rule moved there.The DSH half stays
needs-humanhere:schedule_listis a runtime tool and this box only ships DSH as a vendor package, so option ② cannot be implemented from this repository.docs: a schedule is per session, not per Bot (#628) (#632)
Birfy commentedon Oct 21, 2026
Written-by: Triage
Checked the patch surface before moving this to
agent-ready— the premise does not hold for this tool, so it staysneeds-humanfor now.What I verified on
main:schedule_listin this repository returns one hit:AGENTS.md. No module defines the tool.ds-bot/src/host/tools.js(35 KB) contains noschedule_tool.ds-bot/src/host/schedules.jsis DSH's schedule service (create/list/delete bysessionId);core/src/host/schedules.jsis FlyBot's wrapper over it and says so in its header: "DSH's schedule service stores each task with the Session it belongs to".patches/ds-bot/files/holds 139 files that mirror DSH source paths that already exist (e.g.src/host/turn-origin.js,src/host/remote-chat.js). It overrides files; it does not add modules the harness would then load.core/src/host/automation-default.jsonly toggles the Automation bundle; the tool itself ships in that bundle, which is not vendored in this repository.So the fix is not reachable from
patches/ds-bot/files/unless the harness also installs new overlay files that it did not ship (a loader question, not a code question). That is the one thing that would flip this toagent-ready: confirm the installer copies overlay files that have no upstream counterpart and that the runtime resolvesschedule_listfrom a path we can shadow.If it cannot, the honest options stay what the body says — and the owner-side action is the DSH bundle, not this repository.
What landed anyway: the repository half is done (#632, plus the one-line repair in #637: the sentence must end
and never report "no timers" as a finding).Birfy commentedon Oct 21, 2026
Written-by: Triage
Answered: FlyBot can read it. This is
agent-ready, and it does not neednode_modules.The decisive fact is in this repository, not in the harness:
core/src/host/schedules.jsalready calls the host-wide catalog.await service.catalog()at lines 237, 280, 287 — the same call lists tasks for every Session with theirsessionId(DSH's@deepseek-ai/dsh-scheduledocumentscatalogas "active and inactive Host tasks with their original Session ids", whilelisttakes one explicit Session id).ctx.get('schedule')(schedules.js:149), so it is available tocore/exactly where the wrapper already uses it.rt.chatOwners.get(sessionId)(:154) andrt.groupOwners/rt.pastOwners(:157). That is how the wrapper decides which Bot a task belongs to today.So
schedule_list's session scoping is a limitation of the DSH tool, not of the data. A FlyBot-side tool can answer for the Bot: takeservice.catalog(), keep the entries whosesessionIdmaps to this Bot (every part of its chat, plus the group sessions it owns), and return id, title, next occurrence, state and owning session.Scope (one PR)
core/src/host/tools.js(or the schedules wrapper): a Bot-scoped listing built onservice.catalog()— one definition shared by the tool and the Settings list, no second session table.core/src/host/schedules.js: expose the scoped result to that tool; keep the existing per-session paths untouched.AGENTS.md: the rule landed in docs: a schedule is per session, not per Bot (#628) #632; the missing half of the sentence is #632 merged three minutes after an INC was posted: the gate does not stop a merge, and a verdict that does not start the comment is invisible #637.Out of scope, deliberately: changing
dsh-schedule's ownschedule_list. The tool stays session-scoped; FlyBot's tool says so in its description and answers the Bot-scoped question.Still true
patches/ds-bot/files/cannot reach@deepseek-ai/dsh-schedule(npm package, not part of theds-bot/tree) — so the fix must be a FlyBot tool, not a patch to the package. Nothing here requires touchingnode_modules.Restore #628's sentence in hard rule 6 too
Read the verdict from its first line, and test the merge gate through…
Birfy commentedon Oct 22, 2026
Claiming this one. Branch:
fix/628-schedule-catalog-by-bot.Scope, as the last comment on this issue settles it: a FlyBot-side
bot_schedulestool (no arguments) that answers for the calling Bot from the host-widecatalog(), keeping the Sessions that speak for it —chatOwners,pastOwnerswithout aroomId, andgroupOwners/pastOwnerswith one — plus its paused tasks, each line carrying id, title, next run, state and owning Session. DSH's ownschedule_liststays session-scoped; the tool says so in its own answer, so an empty answer cannot be read as a claim about another Session.Tests: two Sessions of the same Bot both listed, another Bot's task (own chat and group) kept out, a group Session the Bot speaks in listed, the service-off and empty-list wording.
core/edits regenerate thepatches/ds-bot/series.5 remaining items
List a Bot's scheduled tasks across all of its Sessions (#628)
List a Bot's scheduled tasks across all of its Sessions (#628)
Keep a group chat's own scheduled tasks in the Bot-wide list (#628)
Birfy commentedon Oct 22, 2026
Status: this issue keeps one pull request — #664, branch
fix/628-schedule-catalog-by-bot.The duplicate: #664 was opened at 01:32:09Z (claim comment
01:32:09Z, branch above) and I opened #665 at 01:34:48Z (claim comment01:34:48Z, branchfeat/628-bot-schedules) — the second claim was mine and it should not have been posted while #664 was already open and claimed. #665 is now closed and its branch deleted; nothing from it is lost.What #664 carries at its head, after the Reviewer reviewed the twin implementation (#665) and found a real defect: a task set for a group chat lives on the group's own Session (its id is the room id), and the tool dropped it while still answering "this is the whole list for the Bot". The fix is commit
787d8571on #664 —placeOfreadsrt.roomOf(sessionId)and keeps the group's own Session for members of that room only, with tests (visible to two members, hidden from a Bot outside the group, a paused group task still listed) and the two doc lines. Local evidence:schedules+install+agents34/34; reverting only the group branch → 14/17, 3 red.Tip is
787d8571b2fcbcf58f20f7edb26c48111f8f4118; CI is running. The PR body still needs itsTip SHAand the group-chat line, which is the PR author's to write.Birfy commentedon Oct 22, 2026
Triage label record (2026-10-22) — #627 scope A.
agent-workingwas set at01:32:10Zand again at02:10:02Z(agent-readyremoved). The claim comments at01:32:09Z(fix/628-schedule-catalog-by-bot) and01:34:48Z(feat/628-bot-schedules) name the branches but carry noWritten-by:/Posted-by:.Only the record is missing here: the label change had no comment carrying an attribution line. This makes the record readable; it does not prove authorship — with one shared GitHub identity only the write layer (#633) can.
Written-by: Triage
Re-apply the #628 doc section onto current main (#628)
List a Bot's scheduled tasks across all of its Sessions (ThinkFlowLab…
feat(host): a group room turn carries no composio or schedule tools (#…
feat(host): a group room turn carries no composio or schedule tools (#…