@@ -17,7 +17,8 @@ Gateway ─ Worker + Scheduler + Watchdog + Dashboard
1717```
1818
1919- 插件在 ` plugin/supertask.ts ` 注册 8 个 ` supertask_* ` 工具:` add/next/status/retry/list/get/schedule/upgrade ` ;运行态与执行终态只允许 Gateway 写入,不得恢复外部 ` start/done/fail ` 。
20- - Worker 通过参数数组直接执行 ` opencode run --agent <task.agent> --format json <task.prompt> ` ;退出码决定成功或失败,Gateway 统一写任务状态和执行记录。
20+ - Worker 先启动等待握手的 launcher,持久化 launcher PID 后才通过参数数组执行 ` opencode run --agent <task.agent> --format json <task.prompt> ` ;新 run 使用 ` gated-v3-token-guardian ` ,每 run UUID 必须同时写入 ` task_runs.locked_by ` 和 launcher argv。launcher 只能在整个进程组排空后通过不传递给 OpenCode 的 IPC 发回绑定 UUID 的证明;无证明退出必须隔离,不得结算或释放批次。退出码决定成功或失败,Gateway 统一写任务状态和执行记录。当前只有 Unix 独立进程组能提供可恢复的整树退出证明;Windows 在引入 Job Object 前必须拒绝启动 Worker,不得退回不完整的父子 PID 扫描。
21+ - Worker 启动的受管 OpenCode 进程设置 ` SUPERTASK_MANAGED_RUN=1 ` ;该上下文必须拒绝 ` supertask_upgrade ` ,避免升级流程删除并等待承载自己的 Gateway。升级只能从外部 CLI 或非队列 OpenCode 会话发起。
2122- ` agents/supertask-runner.md ` 与 ` plugin/task.ts ` 是旧架构遗留,不是当前 npm 运行链路;不得重新接入嵌套 runner。
2223- pm2 是可选守护层:仅显式运行 ` supertask install ` 时允许安装;插件加载不得静默安装全局依赖。前台运行使用 ` supertask gateway ` 。
2324
@@ -50,11 +51,15 @@ bun run dev -- db check # 检查数据库完整性与业务统计
5051- 数据库默认位于 ` ~/.local/share/opencode/tasks.db ` ;测试或隔离运行通过 ` SUPERTASK_DB_PATH ` 覆盖。
5152- 配置文件位于 ` ~/.config/opencode/supertask.json ` ,默认值在 ` src/gateway/config.ts ` 。
5253- 数据库初始化时启用 WAL、创建 ` gateway_lock ` 并自动执行 ` drizzle/ ` migrations。
53- - Gateway 用 SQLite ` BEGIN IMMEDIATE ` + ` gateway_lock ` 保证单实例;Dashboard 默认只监听 ` 127.0.0.1:4680 ` 。
54- - Gateway 仅在 Worker、Scheduler、Watchdog 和 Dashboard 启动完成后写入 ` gateway_lock.ready_at ` ;PM2 ` online ` 不能单独作为就绪依据,进程 PID 必须匹配新鲜 ready 锁。
55- - ` /health ` 必须同时反映组件活跃度和连续失败;` supertask doctor ` 汇总 OpenCode、数据库、PM2 ready 锁、Dashboard 与日志轮转。显式 ` supertask install ` 配置有限保留的 PM2 日志轮转。
56- - 数据库检查、备份、清空和恢复统一经过 ` DatabaseMaintenanceService ` ;CLI 清空/恢复必须显式确认并拒绝运行中任务,且只可自动停启 PID 与当前数据库新鲜 ready 锁一致的 PM2 Gateway;前台或无法确认归属的进程必须拒绝误杀。清空/恢复前必须自动创建校验通过的安全备份,默认在操作失败时也恢复原 Gateway 状态,` --keep-stopped ` 除外。
57- - Dashboard 清空只能豁免当前 Gateway PID,仍必须服务端确认、拒绝运行中任务并在同一事务内先备份后删除;不得恢复为直接 ` DELETE ` 三张表的路由实现。
54+ - 从 ` 0005 ` 起 migration 必须遵循 expand/contract 并保持 N-1 二进制兼容:只允许新增表、非唯一索引,以及可空或带默认值的新增列。删除、重命名、收紧约束和数据改写必须延后到旧版本不再是自动回滚目标后执行;测试会拒绝破坏该约束的 SQL。
55+ - Gateway 用 SQLite ` BEGIN IMMEDIATE ` + ` gateway_lock ` 保证单实例;进程身份必须同时识别直接 Gateway 入口与公开的 ` supertask gateway ` /CLI 入口。Dashboard 默认只监听 ` 127.0.0.1:4680 ` 。
56+ - Gateway 必须先完成恢复收敛、Scheduler 初始化和 Dashboard 绑定,最后才启动 Worker,并把包版本与 ` gateway_lock.ready_at ` 一起写入;PM2 ` online ` 不能单独作为就绪依据,进程 PID、版本和运行作用域必须匹配新鲜 ready 锁。
57+ - PM2 替换已有 Gateway 前必须先用保存的运行环境验证管理命令可执行;若新旧进程无法共用同一可回滚的 PM2 管理路径,必须在删除旧进程前失败关闭。
58+ - PM2 替换、数据库维护、卸载与 macOS supervisor 检查必须先共用 ` PM2_HOME/supertask-gateway.manage.sqlite ` canonical SQLite 事务锁;兼容旧 custom lock 时还必须从 PM2 dump/运行环境和 LaunchAgent 恢复全部旧路径,并按固定顺序同时持有,不能因后续 CLI 缺少旧环境变量而绕过旧 supervisor。已安装 LaunchAgent 的 ` PM2_HOME ` 与当前 CLI 不同必须在任何修改前失败关闭,避免两个 PM2 daemon 争用同一 Gateway。不得恢复 PID/stale 文件锁。PM2 kill timeout 不得低于 Worker shutdown grace 加 15 秒,` stop/delete ` 命令 timeout 不得低于实际 kill timeout 加 5 秒,管理锁必须持有到命令返回;显式低值必须在删除旧进程前失败关闭。
59+ - macOS supervisor 只有在 ` jlist ` 成功且确认 Gateway 缺失、同时 ` dump.pm2 ` 明确包含 Gateway 时才可 ` resurrect ` ;状态未知、` errored ` 、` stopped ` 和卸载后的空 dump 都不得触发重启。卸载必须停止并移除项目 LaunchAgent。
60+ - ` /health ` 必须分别反映 Worker、Scheduler、Watchdog 和历史清理的活跃度与连续失败;` supertask doctor ` 还要验证 macOS LaunchAgent 与 PM2 dump 可恢复性。PM2 替换/回滚必须保留既有 Bun 路径、完整运行环境和数据库作用域。
61+ - 数据库检查、备份、清空和恢复统一经过 `DatabaseMaintenanceService`;CLI 清空/恢复必须显式确认并拒绝运行中任务,且只可自动停启 PID 与当前数据库新鲜 ready 锁一致的 PM2 Gateway;前台或无法确认归属的进程必须拒绝误杀。清空/恢复前必须自动创建校验通过的安全备份;清空必须动态删除全部业务表数据(包括 N+1 expand-only 表),通过延迟外键检查支持循环依赖,并保留 `gateway_lock` 与 migration 元数据。恢复来源必须从已打开的 SQLite 连接生成包含已提交 WAL 页的一致快照,并拒绝当前数据库的符号链接/硬链接别名。恢复必须动态校验 source/live 业务表和可写列:source-only 未知表/列在删除前失败关闭,共有未来列完整复制,live-only 列只允许可空/默认值且 live-only 新表必须清空,避免 N/N-1 形成混合时间点;随后在当前连接的排他事务内原位替换,不得关闭连接后 rename 换库。默认在操作失败时也恢复原 Gateway 状态,`--keep-stopped` 除外。
62+ - Dashboard 清空只能豁免当前 Gateway PID,仍必须服务端确认、拒绝运行中任务并在同一事务内先备份后动态删除全部业务表;不得恢复为路由内直接 ` DELETE ` 的实现。
5863- Dashboard 的浏览器写请求必须通过同源检查,数据库字符串进入 HTML 前必须调用 ` esc ` ;API 的 ID、状态和配置不得直接断言类型。
5964
6065## 文档维护
@@ -68,13 +73,15 @@ bun run dev -- db check # 检查数据库完整性与业务统计
6873- 任务状态:` pending | running | done | failed | dead_letter | cancelled ` ;执行记录状态:` running | done | failed ` 。
6974- ` cwd ` 是任务的项目隔离键;插件必须使用 OpenCode 工具上下文的 ` directory ` ,不得信任模型传入的 ` cwd ` ,查询和状态变更必须保持同一作用域。
7075- 队列顺序保持 ` urgency DESC → importance DESC → createdAt ASC → id ASC ` ;全局并发和同一 ` batchId ` 串行必须依据数据库运行态,在 Gateway 重启后仍成立;不同批次可并行,依赖任务仅在同 cwd 的 ` dependsOn ` 完成后运行。
71- - ` maxRetries ` 表示首次执行之外允许的重试次数;失败任务按指数退避,耗尽后进入 ` dead_letter ` ,手动重试会重置重试预算 。
76+ - ` maxRetries ` 表示首次执行之外允许的重试次数;失败任务按指数退避,耗尽后进入 ` dead_letter ` 。手动重试必须在同一写事务内确认依赖仍存在、同 ` cwd ` 且可恢复或已完成,才可重置重试预算,避免和历史清理并发制造悬空 ` pending ` 。
7277- ` retryBackoffMs ` 和 ` timeoutMs ` 可按任务覆盖;调度模板克隆时必须保留 ` cwd/batchId/maxRetries/retryBackoffMs/timeoutMs ` 。
73- - 运行中任务进入 ` cancelled ` 后,Worker 必须在轮询周期内终止对应进程树并关闭 run;Gateway 关闭时先按 ` shutdownGracePeriodMs ` drain,只有剩余任务才重置为 ` pending ` 。
78+ - 运行中任务进入 ` cancelled ` 后,Worker 必须在轮询周期内终止对应进程树并关闭 run;只有确认整棵进程树退出后才能关闭、重试、释放批次或在 Gateway 停机时重置为 ` pending ` ,否则必须保持隔离 。
7479- 删除任务必须拒绝 ` running ` 状态、仍有 ` running ` 执行记录,或仍被 ` pending/running/failed/dead_letter ` 任务依赖的前置任务;手动删除与过期清理都必须防止子进程失联和依赖悬空。
75- - Watchdog 处理数据库中的旧 PID 前必须校验进程命令与配置的 OpenCode 可执行文件匹配;Unix 上仅对确认的独立进程组发送信号。
80+ - Watchdog 处理当前 guardian PID 前必须同时校验 launcher 路径、配置的 OpenCode 参数和 ` locked_by ` 中的每 run UUID;旧 v2/legacy 记录只要 PID/PGID 仍存活或无法确认就必须隔离且不得发信号,只有二者均明确消失才可恢复。组长已退出但进程组仍存活时不得按 ` not-running ` 恢复。旧版 ` started_at ` /` heartbeat_at ` 同时为 NULL 的 running run 必须视为 stale 并按协议隔离,不得永久占用并发且逃逸诊断。Unix 使用独立进程组;Windows 在 Job Object 隔离完成前禁止启动 Worker。
81+ - 旧版无 child PID 的 run 默认保持隔离;` run abandon ` 只允许 ` launch_protocol IS NULL ` 、owner PID 已退出、child PID 为空且关联任务已取消的记录,并要求显式 ` ABANDON ` 确认。未知非空协议和当前 guardian 协议必须 fail-closed。
7682- Watchdog 的 ` checkIntervalMs ` 是心跳检查间隔,` cleanupIntervalMs ` 是数据清理间隔,两者不可混用;配置经 ` validateConfig ` 校验后才允许运行或保存。
7783- 调度模板支持 ` cron | delayed | recurring ` ,Scheduler 将模板克隆为普通任务并受 ` maxInstances ` 限制;` delayed ` 成功生成一次后必须自动禁用。
84+ - ` cron/recurring ` 达到 ` maxInstances ` 时必须推进下一触发点,` delayed ` 保持等待;到期模板扫描必须有界。不可恢复依赖应在状态事件中递归收敛,下游链不得在每个 Worker poll 全局扫描。
7885
7986## 代码规范
8087
@@ -85,6 +92,7 @@ bun run dev -- db check # 检查数据库完整性与业务统计
8592- SQL 中 ` NOT IN ` 对 NULL 值不生效,需加 ` OR column IS NULL `
8693- ` tasks.createdAt/startedAt/finishedAt ` 与 ` task_runs.startedAt/finishedAt ` 是秒级时间;` retryAfter/scheduledAt/heartbeatAt/lockedAt ` 和模板调度时间是毫秒值,比较时必须显式统一单位
8794- 修改 ` src/core/db/schema.ts ` 后运行 ` bun run db:generate ` ,并提交对应的 ` drizzle/*.sql ` 和 ` drizzle/meta/* `
95+ - 不得通过提高 migration 兼容性测试的基线来放行破坏性 migration;必须采用跨版本 expand/contract。
8896
8997## 测试规范
9098
@@ -100,7 +108,7 @@ bun run dev -- db check # 检查数据库完整性与业务统计
100108## 发布流程
101109
102110- 修改代码 → 测试通过 → ` bun run build ` → git commit/push
103- - 创建 GitHub Release 自动触发 CI 发布到 npm;工作流通过 npm Trusted Publisher/OIDC 获取短期发布凭据,不使用长期 ` NPM_TOKEN `
111+ - 创建 GitHub Release 自动触发 CI 发布到 npm;稳定版进入 ` latest ` ,预发布版进入 ` next ` ; 工作流通过 npm Trusted Publisher/OIDC 获取短期发布凭据
104112- npm 包设置必须信任仓库 ` vbgate/opencode-supertask ` 的 ` publish.yml ` ,Allowed actions 仅启用 ` npm publish `
105113- ** 不要手动 npm publish** ,通过 ` gh release create v<x.y.z> ` 触发
106114- 升级版本号在 ` package.json ` 的 ` version ` 字段
0 commit comments