phase3(契约层): protocol.ts + 落盘状态 + store 失败策略/判活原语

多进程执行解耦的 Phase 0 共享契约(worker 与 daemon 都 import 它):
- executor/protocol.ts: JobSpec(daemon→worker 唯一输入) + OutboxRecord(worker→daemon) +
  文件 IO(job/outbox/heartbeat) + isWorkerAlive(心跳为主/boot 窗口 pid 兜底/防 pid 复用)
- schema+db+types+mappers: runs.worker_pid/last_seq、tasks.next_eligible_at(持久化退避)
- store: failTaskAttempt(失败/重试策略唯一落点) + setNextEligibleAt/setWorkerPid/setLastSeq +
  countExecuting + executingWithLatestExecutorRun + reconcileInterrupted(isAlive 注入,默认保守回收)

纯增量,140 测试全绿。worker.ts/pipeline.ts(worker 侧) 与 orchestrator/ingest/index(daemon 侧) 待接。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
wangjia
2026-06-13 12:51:09 +08:00
parent d49192344f
commit 007dffac39
7 changed files with 269 additions and 12 deletions
+3
View File
@@ -70,6 +70,7 @@ export interface Task {
result: TaskResult | null;
assignee: 'agent' | 'human' | null;
retryBaseline: number; // 上次手动重投时已有的失败 run 数(重置重试计数用)
nextEligibleAt: string | null; // 持久化退避:早于此时间不被领取(重试退避,重启不丢);null=即刻可领
createdAt: string;
updatedAt: string;
}
@@ -89,6 +90,8 @@ export interface Run {
transcriptRef: string | null; // agent 转录日志文件路径
claudeSessionId: string | null;
error: string | null;
workerPid: number | null; // 执行该 run 的 worker 进程 pid(多进程执行;daemon 写,判活用)
lastSeq: number; // 已 ingest 的 outbox 最大 seqdaemon 写,幂等游标;重启续读)
}
export type EventType =