feat(rule13): 执行前分歧重评估闸——main 撞声明范围→needs_attention 重评估

通用规则13的(B)半边:sync main 之前先跑 reevalScopeGate,
以 git diff HEAD...origin/main 取 main 自分支点以来改动的文件,
与任务 scopeFiles 求交集;非空即 emit needs-reeval →
daemon markReeval 直接转 needs_attention(不重试/不计失败/run收尾cancelled)。

- checks.ts: + reevalScopeGate / ReevalGateFn / ReevalGateResult
- pipeline.ts: createWorktree 后、syncMain 前插入重评估闸 + reevalGate 依赖注入
- protocol.ts: + needs-reeval OutboxRecord/Payload 事件
- ingest.ts: + case 'needs-reeval' → store.markReeval
- store.ts: + markReeval(executing→needs_attention,不进重试链)
- status.ts: executing 合法转移 + needs_attention
- 测试 +5:reevalScopeGate(命中/未命中/空/无前移/git错) · pipeline(命中emit/未命中续跑) · store.markReeval;全套 242 绿
- docs: optimization-plan.html 规则13 标  已实现

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
wangjia
2026-06-25 20:15:02 +08:00
parent 6bf2b3619c
commit fa4ba3db28
10 changed files with 194 additions and 6 deletions
+19
View File
@@ -755,6 +755,25 @@ export class Store {
return this.getTask(taskId)!;
}
/**
* 通用规则13 执行前分歧重评估:sync main 发现 defaultBranch 改动与任务声明范围(scopeFiles)重叠,
* 原方案可能过时 → 不重试、不计失败次数,直接把任务转 needs_attention 待人工重评估。
* 与 failTaskAttempt 区别:run 收尾为 cancelled(未真失败,是主动停下重评估),不退避、不进重试链。
*/
markReeval(taskId: string, runId: string | null, reason: string): Task {
const row = this.getTaskRow(taskId);
if (!row) throw new StoreError(`任务不存在: ${taskId}`);
if (runId) {
const rr = this.db.prepare(`SELECT status FROM runs WHERE id = ?`).get(runId) as { status: string } | undefined;
if (rr && rr.status === 'started') this.finishRun(runId, 'cancelled', { error: reason });
}
this.setNextEligibleAt(taskId, null);
if ((this.getTaskRow(taskId)!.status as TaskStatus) !== 'needs_attention') {
this.transition(taskId, 'needs_attention', { by: 'markReeval', reason });
}
return this.getTask(taskId)!;
}
/**
* planner(拆解 Hard / 写方案 Medium)失败的落点:收尾 planner run + 退避,任务【留在 analyzing/speccing】
* 等退避到期重新被领取;累计 planner 失败超 project.maxRetries → 升级 needs_attention(清退避)。