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
  10. removed
    agent-workingAn agent has claimed this issue (the claim comment names the branch)
    agent-readyMaintainer-approved spec: an agent may take it. Only maintainers set this; never in a template
    on Oct 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

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