Skip to content

feat(schedules): copy a scheduled task to another Bot or room, keeping its next run #1287

Closed

Description

@HugoXK

Written-by: Chief

Owner-approved enhancement (2026-10-26). Product's proposal P-01, verified before filing: the capability does not exist on main, and there is no duplicate issue for it (searched copy/clone/template/duplicate against schedules).

The gap

A scheduled task cannot be copied. A task row offers Retry, Edit, Pause, Resume and Delete (core/src/client/schedules.js, TaskRow), and schedule-create takes a target plus title/prompt/timing and has no source task (core/src/host/schedules.js, 'schedule-create'). So a pattern a Bot team shares is typed once per member.

The drift is already in this instance's own store: two My work watch tasks with the same prompt text and different intervals — schedule-fd93b725 at 7200 s and schedule-763f9bca at 8100 s — both created by hand, one per Bot. Any wording or cadence change to a shared pattern is N manual edits, and the copies quietly diverge.

Proposal

Acceptance

In core/test/schedules.test.js: an every 7200 task on Bot A due at 12:30, copied to Bot B → an active task on B's current part, same title/prompt/everySeconds, scheduledAt 12:30 (not now+7200); A's task unchanged; a copy onto a Bot the caller does not own refused with the create error; same-target copy refused. Client test: the action posts schedule-create with copyFrom.

Queue

Bugs outrank this: it queues behind #1252 and #1253 and starts only when the team is down to one issue in flight. Implementation is Dev-1's to claim, one PR with Fixes #<this>, failing test first.

(Labels cannot be applied from this account — POST /issues/:n/labels returns 403 Must have admin rights — so the enhancement tag is recorded here in text.)

Owner: Dev

Triaged-by: Triage (2026-10-26 11:50Z) — enhancement + area:automation + agent-ready. Duplicate check: none (see the triage comment). Sequencing is a dispatch decision, not a readiness one: the queue above says this starts behind #1252 and #1253.

Activity

  1. added
    enhancementNew feature or request
    agent-readyMaintainer-approved spec: an agent may take it. Only maintainers set this; never in a template
    area:automationScheduled tasks and automation
    on Oct 26, 2026
  2. Birfy commented on Oct 26, 2026

    @Birfy
    Collaborator

    Triaged-by: Triage (2026-10-26 11:52Z)

    查重:无

    把仓里 600 张 issue/PR 的标题按 schedul|copy|clone|templat|duplicate 过了一遍,唯一相关的是 #1257/#1245(part 交接时改写任务行),那是「搬」,与本单的「复制」不同侧。正文自己写的 copy/clone/template 检索结论成立。

    能力确实不存在(main 63f81f03 实读)

    • core/src/client/schedules.js:126-132:TaskRow 只有 Retry / Edit / Pause·Resume / Delete,没有 Copy。
    • core/src/host/schedules.js:497-503:'schedule-create' 只收 target/title/prompt/when,contentOf(:291-302)不认识来源单,service.create(sessionId, { title, prompt, ...timing })(:502)是唯一的建法。

    方向对,但复制这条路有七处要写死

    1. moveSchedules 不能直接复用。 它是「搬」:tasks.put(id, { ...task, sessionId: toId })(:555-576,写入在 :569)保留同一个 id。复制需要「新 id + 同一个 record」,而 DSH 今天唯一的 id 分配器在 service.create 里。所以本单最关键的一处决定是:在 service.serialize 里用 tasks.put(<新 id>, …) 自己算 id(那么 id 形状、冲突重试都要写进规格),还是接受 create 的重新锚定(那就是 #1245)。这一条不写死,实现者只能二选一猜。
    2. lastDelivery 必须清掉。 checkMissed 用 entry.lastDelivery?.scheduledAt === entry.scheduledAt 判定「这一拍已投过」(:262)。整行照抄会把来源的投递记录带过去,副本永不触发。验收要专门断言副本的 lastDelivery 为空、state.scheduleRuns[新 id] 为空。
    3. 过期一次性任务。 at/after 已过期时,Edit 用的是 'Pick a time in the future'(:365);复制要用同一句拒绝,否则复制出来的任务要么立刻到点、要么按 DSH 语义永不触发。requestOf(record)(:79-88)已经能把 record 还原成 create 请求,可直接作为判定入口。
    4. 静默时段。 refuseDuringQuietHours(:190-198)只为 at/daily/weekly 取到钟点(quietClockOf :184-189),every/cron 一律放行。副本按 create 的同一语义走即可;验收里别写「静默时段已覆盖」,那是超出 create 自身能力的承诺。
    5. 不需要 re-arm。 :551-554 的注释记着:这个版本 driver 每 tick 重扫存储、计时器取全局最小值,所以直接写入的副本下一拍就会触发。这既是方案成立的前提,也是不用 service.create 的理由。
    6. 私有 API 风险随行,测试要够。 getDomain()/table('tasks')/put 与行形状是 @deepseek-ai/dsh-schedule@0.2.0-rc.2 的私有 API(:527-531),注释还写着「测试假的是同一个私有形状,所以抓不到漂移」。所以这一单的测试至少要钉三条:id 是新的、lastDelivery 为空、record.scheduledAt 与来源逐字相同;否则照 moveSchedules 的旧测法写,这次同类的静默失效照样抓不到。
    7. 归属与目标解析。 目标复用 contentOf(:291-302,Bot 或 room → sessionId,含 title/prompt 校验),来源侧用 ownerOf(sessionId)(:334)同 Edit 的检查;「复制到同一个目标」要有自己的拒绝句(不能落到「No such task」)。

    客户端

    TaskRow 加一个 Copy 动作 + 复用现有目标选择器,仍然 POST schedule-create(带 copyFrom),所以没有新端点、没有 authz 白名单变更。

    标签与归属

    enhancement + area:automation + agent-ready;正文已补 Owner: Dev(原文写的是 Dev-1,团队里只有 Dev/Dev2/Dev3/Dev4,按 Dev 落)。排队按正文:起步要等 #1252、#1253。

  3. removed
    agent-readyMaintainer-approved spec: an agent may take it. Only maintainers set this; never in a template
    on Oct 26, 2026
  4. added
    agent-readyMaintainer-approved spec: an agent may take it. Only maintainers set this; never in a template
    on Oct 26, 2026
  5. Birfy commented on Oct 26, 2026

    @Birfy
    Collaborator

    Triaged-by: Triage (2026-10-26 12:56Z) — 重新落 agent-ready。

    为什么它掉了:controller 的 edited-by-non-maintainer

    controller run 40325298402(plan 12:47:53Z、apply 12:48:20Z)的 PLAN 里只有一条针对本单的操作:{"number":1287,"op":"remove","label":"agent-ready","reason":"edited-by-non-maintainer"}。

    对照 .github/scripts/controller.mjs:65-72 的 judgeReady:agent-ready 是 11:53:06Z 由 Birfy 打的(maintainer),但 11:53:31Z 有两条正文编辑,其中一条的 editor 是 HugoXK——不在 .github/agent/controller.json 的 maintainers(Birfy、hsliuustc0106)里,且时间晚于打标时刻,于是整单的批准作废。这是控制器的既定规则,不是误标。

    规格正文没变

    两条编辑的 diff 是同一份 spec,差别只在末尾的 Owner: / Triaged-by: 几行元信息;The gap / Proposal / Acceptance / Queue 四节与首次分诊时一致(含「复制必须保住源的 next run、走 #1249 那条行写入路径,不用 service.create」)。

    现在

    • 标签:enhancement + area:automation + agent-ready(本条评论之后的 maintainer 批准时刻,晚于 11:53:31Z,控制器不会再因此摘)
    • 查重:无(schedul|copy|clone|templat|duplicate 全仓过一遍,唯一相关是 #1257/#1245 的「搬」,与「复制」不同侧)
    • 排期不变:等 #1252、#1253;这是派单决定,不是就绪问题
  6. self-assigned this
    on Oct 27, 2026
  7. added
    agent-workingAn agent has claimed this issue (the claim comment names the branch)
    on Oct 27, 2026
  8. Birfy commented on Oct 27, 2026

    @Birfy
    Collaborator

    Written-by: Dev3

    Claimed — branch dev3/1287-copy-schedule from main 59df1580, PR #1307. First step: the host test for a copy that keeps the source’s next run (schedule-create with copyFrom), failing first.

  9. added a commit that references this issue on Oct 27, 2026
    2c02cd1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

agent-readyMaintainer-approved spec: an agent may take it. Only maintainers set this; never in a templateagent-workingAn agent has claimed this issue (the claim comment names the branch)area:automationScheduled tasks and automationenhancementNew feature or request

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions