[IMPROVEMENT] 持久化 bridging scheduler registration identity
Description
为各 host 的 bridging schedule 建立一个轻量、可持久化的 runtime registration identity,使 install refresh 和 uninstall 能在不读取、比较完整 pipeline prompt 的情况下,精确定位并删除自己创建的 scheduler entry。
这项工作是 PR #641 统一 HostSpec.task_name / former_task_names 之后的独立后续架构工作。#641 统一的是跨平台命名;本 issue 处理 scheduler 实际返回的 task/job/automation identity。
Current Behavior
不同 host 当前依赖不同的删除信号:
| Host | 当前最强 identity | 缺口 |
|---|---|---|
| Claude Code / Cursor / Hermes OS scheduler | Windows exact task name、launchd label、cron marker/wrapper | 已有轻量 identity;需要接入统一契约而非改变行为 |
| Hermes legacy native cron | exact name → scheduler 返回的 job ID | 可作为 native scheduler 迁移参考 |
| OpenClaw | .cron_job.openclaw.json 中持久化的 exact job ID |
当前最完整的参考实现 |
| Cola | 固定旧 ID memu-bridging;新标准名 memu-bridging-cola |
文档中 ID 与显示名需要保持区分;不需要解析 prompt |
| WorkBuddy | automation 创建时返回 ID,但 memU 没有持久化 | 旧 task 无 marker/sidecar;当前只能重新扫描 automation list |
| Codex | 标准名只是 hint,且允许用户自选名 | 未持久化 scheduler task ID;历史实现把长 pipeline prompt 当删除依据 |
| Generic default cron | host-scoped wrapper path;#641 增加 cron marker | 默认 integration 可识别,但 registration metadata 未持久化 |
| Generic named/native | 动态 task name、--base-dir 和外部 scheduler |
静态 HostSpec.task_name 无法表达多个 integration 的实际 ID/base dir |
完整 pipeline prompt 不适合作为长期 deletion identity:它很长,需要读取 scheduler payload,随文案变化而漂移,也让 install/uninstall preflight 变重。它最多只能作为 legacy 人工确认时的上下文,不能继续作为自动删除主键。
八个 host 的旧 task 删除方式审计见 PR #641 comment。
Proposed Improvement
引入统一的 scheduler registration 契约,同时允许各 scheduler 保存其原生 identity,而不是强迫所有 host 使用同一个字段。例如:
@dataclass(frozen=True)
class ScheduleRegistration:
scheduler: str
task_name: str
external_id: str | None = None
label: str | None = None
wrapper: str | None = None
base_dir: str | None = None具体字段可以在实现前调整;关键语义是:
创建成功后持久化
- 保存 scheduler kind;
- 保存 scheduler 返回的 exact task/job/automation ID(若存在);
- 保存实际 task name/label;
- 对 cron/Generic 保存 exact wrapper 与 base dir;
- 原子写入 host-scoped sidecar。
刷新和卸载按 structural identity 删除
- 优先读取 sidecar;
- 按 exact external ID、task name、label 或 wrapper entry 删除;
- 删除后重新列出并验证 identity 已消失;
- 不解析完整 pipeline prompt。
legacy migration
- sidecar 缺失时,只在 exact former name/ID、host-scoped wrapper 或 label 能唯一命中时自动迁移;
- 如果旧 task 既没有固定 name,也没有 persisted ID,要求用户从 scheduler 候选列表中确认一次,然后回填 sidecar;
- 多个候选项时停止,不自动批量删除;
- 不通过完整 pipeline prompt 自动猜测 ownership。
生命周期一致性
- 创建 scheduler entry 成功、sidecar 写入失败时,应报告部分失败并保留足够信息供恢复;
- scheduler entry 已不存在时,清理 stale sidecar;
- refresh 的 replacement 成功后才让 sidecar 指向新 identity;
- uninstall 只删除目标 host/integration 的 registration,不触碰其他用户 task 或其他 Generic integration。
Suggested rollout
- WorkBuddy:持久化
automation_update返回的 automation ID;优先解决旧 task 无 marker、当前 ID 未保存的问题。 - Generic:保存 scheduler kind、动态 integration name、base dir、wrapper path,以及 native scheduler ID(若提供);支持多个 named integrations 并存。
- Codex:确认 scheduled-task surface 是否提供稳定 ID;若提供则持久化,否则采用一次人工选择并保存后续可用 identity。
- OpenClaw:把现有
.cron_job.openclaw.json作为参考实现,必要时适配统一读写接口,不要求无意义地重写已可靠的格式。 - Cola / OS hosts:复用已有 fixed ID/name/label/wrapper,接入统一接口;不要为了形式一致重复保存不必要的数据。
Benefits
- install refresh 和 uninstall 都是轻量、确定性的操作;
- 不再把易漂移的长 prompt 当数据库主键;
- WorkBuddy、Codex 和 Generic native scheduler 能可靠删除自己创建的 task;
- 多个 Generic integrations 可以安全共存、单独刷新和卸载;
- 避免同名或相似 prompt 导致误删用户的其他 scheduled tasks;
- 命名契约与 runtime identity 各司其职:
HostSpec管标准名称,registration sidecar 管本机实际 scheduler identity。
Acceptance Criteria
- 定义并测试统一的 schedule registration 读写/校验接口。
- 创建 task 后原子持久化可用的 exact scheduler identity。
- refresh/uninstall 不需要读取或比较完整 bridging pipeline prompt。
- sidecar 缺失、损坏、stale、多个候选项均有安全且可测试的行为。
- WorkBuddy 按 persisted automation ID 删除。
- Generic default 与 named integrations 均按各自 exact marker/wrapper/base-dir/ID 删除,互不影响。
- Codex 的 stable-ID 能力有明确结论和对应实现或人工迁移路径。
- OpenClaw 现有 exact job-ID 行为保持兼容。
- Cola 与 Claude Code/Cursor/Hermes 不降低现有 fixed ID/name/label/wrapper 删除可靠性。
- 文档明确:name 用于显示和标准旧名迁移,runtime registration identity 才是删除 authority。
Version
main / follow-up to PR #641
Additional Information
建议作为 #641 合并后的独立 PR 实现。#641 继续聚焦 task naming contract 和 known former names,不在同一变更中引入所有 native/external scheduler 的新生命周期协议。
Source: NevaMind-AI/memU