任务终止 —— 用户主动取消或任务到期时触发,调 `miloco-cli task delete --reason X` 一笔走完 backend(写 task_terminate_log + 删 task,FK CASCADE 同步清 rule / cron / task_record_* 主表/子表),顺序跑返回的 agent_pending 让 openclaw 老通路 external cron 一并下线。
85%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
任务终止 skill。整个流程 3 步:
task delete 前先确认;自动触发场景(termination_schedule / archive_maintenance / completed)跳过此步直接执行。miloco-cli task delete <task_id> --reason {completed|expired|abandoned}——backend 一笔事务写 task_terminate_log(30 天滚动审计)+ 删 task(FK CASCADE 同步清 rule / cron / task_record_* 主表/子表 / event 子表 / duration_session 子表)。agent_pending 顺序跑 OpenClaw cron tool action=remove(仅 kind:'cron' 一种,来自 dispatch_owner='external' 的老 cron;internal 已在 backend 事务内一并清理)。三种触发场景,prompt 中均含 调用 skill: miloco-terminate-task 和 task_id:
| 触发源 | 表现 |
|---|---|
| 用户主动取消 | 用户说"不喝了 / 不记药了 / 取消那个监控" → Layer 1 路由 → 调 skill |
| 重复任务的 termination at-schedule 到点 | recurring 任务带 valid_until 时建的一次性 schedule 自动调 |
| archive_maintenance 兜底 | 每天 3 点扫到 valid_until 已过期但任务仍存活时补一次 terminate |
prompt 应含 trigger_source 字段(user_cancel / termination_schedule / archive_maintenance),决定 --reason 入参。
trigger_source 为 user_cancel 时,不直接 task delete——先调
miloco-cli task get <task_id> 拿当前 description(禁止凭印象拼任务名),
然后反问用户:
确认永久删除「<description 原文>」吗?删除后所有历史记录(每天的喝水次数 /
累计时长 / 触发日志)都会一并清空且无法恢复。
如果只是暂时不想接收提醒,回「暂停」我帮你停用任务、历史记录保留;想彻底
删除回「确定」。按用户答复分支(不要硬解析,按语义路由):
| 用户答复语义 | 动作 |
|---|---|
| "确定 / 确认 / 删了 / 嗯 / 好 / 是的" | 继续第一步 task delete |
| "暂停 / 先停一下 / 不要提醒了" | 调 miloco-cli task disable <task_id> 改 status=paused;历史记录保留,rule disabled / cron disable pending;不删,status=disabled_instead 输出报告 |
| "算了 / 再想想 / 取消" | 不动任何东西,status=user_canceled 输出报告,回话"好的,保留任务" |
其他 trigger_source(termination_schedule / archive_maintenance / completed)跳过本步——系统自动触发不需要用户介入。
反例(禁踩):
- ❌ 反问时贴
task_id给用户看(drink_water)——按 SKILL §术语黑名单 task_id / 内部 id 禁外漏- ❌ 反问时列 "rule_id / cron jobId 都会清" 等技术细节——用户视角只关心"历史记录会消失"
- ❌ user_cancel 不反问直接 delete——历史数据是有价值的,误删不可恢复
按触发源映射 --reason:
| trigger_source | reason |
|---|---|
user_cancel(用户主动取消,第零步已确认) | abandoned |
termination_schedule(到期触发) | expired |
archive_maintenance(兜底触发) | expired |
| 任务自然达标后调(completed) | completed |
miloco-cli task deletemiloco-cli task delete <task_id> --reason <abandoned|expired|completed>backend 一笔事务:
task_terminate_log(kind / reason / description / final_snapshot / terminated_at)task_terminate_log 行DELETE FROM task WHERE task_id=? —— FK CASCADE 同步清 rule / cron / task_record_* 主表 + duration_session / event_entry 子表返回结构:
{
"task_id": "...",
"backend_synced": {
"rules_deleted": ["..."]
},
"agent_pending": [
{ "kind": "cron", "ref": "<cron_id>", "action": "remove", "source": "openclaw" }
// 只 external cron 会产 pending; internal 已在事务内一并清理
]
}404 处理:返回 code=2001 task_not_found 视同 noop(任务已删),跳过第三步。
逐项执行 agent_pending[],每条都是 {kind: "cron", ref: "<jobId>", action: "remove"}:
action=remove,jobId = refoperations[] + errors[] 一次性回话{
"skill": "miloco-terminate-task",
"task_id": "drink_water",
"trigger_source": "user_cancel | termination_schedule | archive_maintenance",
"status": "completed | partial | failed | disabled_instead | user_canceled",
"final_reason": "abandoned | expired | completed | null",
"operations": [
{ "type": "task.delete", "rules_deleted": ["rule_xyz"], "agent_pending_count": 2, "ok": true },
{ "type": "cron.remove", "jobId": "job_aaa", "ok": true },
{ "type": "cron.remove", "jobId": "job_bbb", "ok": true }
],
"errors": []
}status 含义:
completed:所有步骤成功partial:典型场景——task delete 成功但第三步某条 cron remove 失败(jobId 已不存在等)failed:task delete 调用本身失败(5xx 等)disabled_instead:用户在第零步选了"暂停",走 task disable,未 delete;operations 只有 task.disable 一项user_canceled:用户在第零步选了"算了",无任何 backend 调用task delete 返回 code=0(backend 部分已 commit)或 code=2001(task_not_found,视同已删 noop)errors[] 不中止后续status=completed| 异常 | 处理 |
|---|---|
task delete 返回 404 / code=2001 | 任务不存在,视同已删 noop,跳过第三步,status=completed、operations=[] |
task delete 5xx | status=failed;记错误,不继续 |
| 第三步单条 cron remove 失败 | 记到 errors[],继续后续,不回滚 |
报告 status=partial / failed | 调 system.failureAlert 让 archive_maintenance 第二天兜底再扫 |
task delete 单笔事务覆盖审计写入 + task 删(FK CASCADE 同步清 rule / cron / record),agent 不要拆步骤手工做agent_pending 已是权威清单agent_pending 仅 kind:'cron',没有其他 kind;若遇其他 kind 视作 backend 异常 failed输入(Layer 1 路由后):
调用 skill: miloco-terminate-task
trigger_source=user_cancel
task_id=drink_water执行(用户答"确定"分支):
miloco-cli task get drink_water 拿 description="每天喝 8 杯水",回话:
确认永久删除「每天喝 8 杯水」吗?删除后历史记录(每天的喝水次数)会一并清空且无法恢复。如果只是暂时不想接收提醒,回「暂停」;想彻底删除回「确定」。
--reason abandonedmiloco-cli task delete drink_water --reason abandoned:
{
"task_id": "drink_water",
"backend_synced": {
"rules_deleted": ["rule_xyz"]
},
"agent_pending": [
{ "kind": "cron", "ref": "job_aaa", "action": "remove" },
{ "kind": "cron", "ref": "job_bbb", "action": "remove" }
]
}agent_pending:对 job_aaa / job_bbb 调 cron action=removestatus=completed 报告第零步反问后用户答"暂停" / "先停一下":
miloco-cli task disable drink_water → backend 把 task.status 改 paused,rule disabled,返回 agent_pending 让 agent 跑 cron disableagent_pending 的 cron action=disable(不是 remove)status=disabled_instead、operations=[{type:"task.disable", ...}, {type:"cron.disable", ...}]第零步反问后用户答"算了" / "再想想":
status=user_canceled、operations=[]、final_reason=nullXiaoMi/xiaomi-miloco
a48c181
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.