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:
@@ -264,6 +264,33 @@ test('planner:CC 失败 → emit failed', async () => {
|
||||
assert.equal(emitted.at(-1)?.type, 'done');
|
||||
});
|
||||
|
||||
test('规则13 分歧重评估:reevalGate 撞声明范围 → emit needs-reeval + done,不执行/不复审/无 failed', async () => {
|
||||
const { emitted, emit } = collector();
|
||||
const job: JobSpec = { ...fakeJob, task: { ...fakeTask, scopeFiles: ['src/**'] } };
|
||||
let ranTask = false;
|
||||
await runPipeline(job, mockDeps({
|
||||
reevalGate: async () => ({ overlap: ['src/a.ts', 'src/b.ts'] }),
|
||||
runTask: async () => { ranTask = true; return okRun; },
|
||||
}), emit);
|
||||
|
||||
const re = find(emitted, 'needs-reeval');
|
||||
assert.ok(re, '撞声明范围应 emit needs-reeval');
|
||||
assert.deepEqual(re.files, ['src/a.ts', 'src/b.ts']);
|
||||
assert.match(re.reason, /原方案可能已过时/);
|
||||
assert.equal(ranTask, false, '重评估时不应执行任务');
|
||||
assert.equal(find(emitted, 'result'), undefined, '不应 emit result');
|
||||
assert.equal(find(emitted, 'failed'), undefined, '重评估不是失败,不应 emit failed');
|
||||
assert.equal(emitted.at(-1)?.type, 'done', '末尾应为 done');
|
||||
});
|
||||
|
||||
test('规则13 分歧重评估:无重叠 → 正常往下执行(emit result)', async () => {
|
||||
const { emitted, emit } = collector();
|
||||
const job: JobSpec = { ...fakeJob, task: { ...fakeTask, scopeFiles: ['src/**'] } };
|
||||
await runPipeline(job, mockDeps({ reevalGate: async () => ({ overlap: [] }) }), emit);
|
||||
assert.equal(find(emitted, 'needs-reeval'), undefined, '无重叠不应触发重评估');
|
||||
assert.ok(find(emitted, 'result'), '应正常执行到 result');
|
||||
});
|
||||
|
||||
test('parseDecompose:取最后一个 json 块;非法/缺失 → null', () => {
|
||||
assert.equal(parseDecompose('no json here'), null);
|
||||
assert.equal(parseDecompose('```json\n{"subtasks":[]}\n```'), null, '空 subtasks → null');
|
||||
|
||||
Reference in New Issue
Block a user