fix(tests): 修复三类优化实现后的测试适配
- pipeline.test.ts:PipelineDeps 增加 syncMain 可注入接口(默认用真 git), 测试 mockDeps 加 syncMain=no-op + runConflict,消除 fake-worktree 上真 git 调用失败 - models.test.ts:reviewer 三档默认 fable-5、project.model 不覆盖复审/conflict、 MODEL_FALLBACK_CHAIN 三项链;pickFallbackModel 改为取链上下一档(循环)而非首个不等项 - ingest.test.ts:verdict=reject 硬闸测试改为断言未进 exec_review Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+7
-7
@@ -105,7 +105,7 @@ test('ingest result:task→exec_review,setResult 四字段正确,reviewer/
|
||||
});
|
||||
});
|
||||
|
||||
test('ingest result:任一 verdict=reject 也照常落进 result(裁决归用户)', () => {
|
||||
test('ingest result:任一 verdict=reject → 硬闸退回重执行(不进 exec_review)', () => {
|
||||
withTmpDataDir(() => {
|
||||
const { store, taskId, runId, dir, branch } = setupExecuting();
|
||||
appendOutbox(runId, {
|
||||
@@ -115,12 +115,12 @@ test('ingest result:任一 verdict=reject 也照常落进 result(裁决归
|
||||
} as OutboxPayload);
|
||||
ingestRun(store, noopLog, runId);
|
||||
|
||||
const done = store.getTask(taskId)!;
|
||||
assert.equal(done.status, 'exec_review');
|
||||
assert.equal(done.result!.verdict, 'reject');
|
||||
assert.equal(done.result!.summary, '发现问题');
|
||||
assert.equal(done.result!.securityVerdict, 'reject');
|
||||
assert.equal(done.result!.securitySummary, '发现密钥泄露');
|
||||
const t = store.getTask(taskId)!;
|
||||
// verdict=reject 触发硬闸:退回重执行(queued),不进 exec_review
|
||||
assert.ok(t.status === 'queued' || t.status === 'failed' || t.status === 'needs_attention',
|
||||
`expected task to be re-queued or failed after reject verdict, got ${t.status}`);
|
||||
// 不应进入 exec_review
|
||||
assert.notEqual(t.status, 'exec_review');
|
||||
store.close();
|
||||
});
|
||||
});
|
||||
|
||||
+20
-12
@@ -40,32 +40,39 @@ test('pickModel:复杂度映射默认值(executor / reviewer)', () => {
|
||||
assert.equal(pickModel(fakeTask('easy'), p, 'executor'), 'claude-sonnet-4-6');
|
||||
assert.equal(pickModel(fakeTask('medium'), p, 'executor'), 'claude-opus-4-8');
|
||||
assert.equal(pickModel(fakeTask('hard'), p, 'executor'), 'claude-fable-5');
|
||||
assert.equal(pickModel(fakeTask('easy'), p, 'reviewer'), 'claude-sonnet-4-6');
|
||||
assert.equal(pickModel(fakeTask('medium'), p, 'reviewer'), 'claude-opus-4-8');
|
||||
assert.equal(pickModel(fakeTask('hard'), p, 'reviewer'), 'claude-opus-4-8');
|
||||
// reviewer 三档全升 fable-5(保复审独立性)
|
||||
assert.equal(pickModel(fakeTask('easy'), p, 'reviewer'), 'claude-fable-5');
|
||||
assert.equal(pickModel(fakeTask('medium'), p, 'reviewer'), 'claude-fable-5');
|
||||
assert.equal(pickModel(fakeTask('hard'), p, 'reviewer'), 'claude-fable-5');
|
||||
});
|
||||
});
|
||||
|
||||
test('pickModel:project.model 最优先(两个角色、所有复杂度都用它)', () => {
|
||||
withEnv({ MAESTRO_MODEL_HARD: 'claude-haiku-4-5' }, () => {
|
||||
test('pickModel:project.model executor 最优先,但 reviewer/conflict 不受 project.model 覆盖', () => {
|
||||
withEnv(Object.fromEntries(ENV_KEYS.map((k) => [k, ''])), () => {
|
||||
const p = fakeProject('claude-opus-4-6');
|
||||
for (const c of ['easy', 'medium', 'hard'] as const) {
|
||||
// executor 受 project.model 覆盖
|
||||
assert.equal(pickModel(fakeTask(c), p, 'executor'), 'claude-opus-4-6');
|
||||
assert.equal(pickModel(fakeTask(c), p, 'reviewer'), 'claude-opus-4-6');
|
||||
// reviewer 不受 project.model 覆盖,始终用最强档 fable-5(保自审独立性)
|
||||
assert.equal(pickModel(fakeTask(c), p, 'reviewer'), 'claude-fable-5');
|
||||
// conflict 固定 fable-5
|
||||
assert.equal(pickModel(fakeTask(c), p, 'conflict'), 'claude-fable-5');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('pickModel:env 覆盖默认值,且 executor/reviewer 各用各的 env', () => {
|
||||
test('pickModel:env 覆盖默认值,executor/reviewer 各用各的 env', () => {
|
||||
withEnv({
|
||||
MAESTRO_MODEL_EASY: 'claude-haiku-4-5',
|
||||
MAESTRO_MODEL_REVIEW_HARD: 'claude-fable-5',
|
||||
MAESTRO_MODEL_REVIEW_EASY: 'claude-opus-4-8', // reviewer env 可单独覆盖
|
||||
}, () => {
|
||||
const p = fakeProject();
|
||||
assert.equal(pickModel(fakeTask('easy'), p, 'executor'), 'claude-haiku-4-5');
|
||||
assert.equal(pickModel(fakeTask('easy'), p, 'reviewer'), 'claude-sonnet-4-6'); // reviewer 不受 executor env 影响
|
||||
// reviewer easy 被 MAESTRO_MODEL_REVIEW_EASY 覆盖
|
||||
assert.equal(pickModel(fakeTask('easy'), p, 'reviewer'), 'claude-opus-4-8');
|
||||
// reviewer hard 无 env → 默认 fable-5
|
||||
assert.equal(pickModel(fakeTask('hard'), p, 'reviewer'), 'claude-fable-5');
|
||||
assert.equal(pickModel(fakeTask('hard'), p, 'executor'), 'claude-fable-5'); // executor hard 默认即 fable
|
||||
assert.equal(pickModel(fakeTask('hard'), p, 'executor'), 'claude-fable-5'); // executor hard 默认 fable
|
||||
});
|
||||
});
|
||||
|
||||
@@ -91,8 +98,9 @@ test('isModelError:模型不可用类错误才触发回退', () => {
|
||||
});
|
||||
|
||||
test('pickFallbackModel:回退链取第一个 ≠ 失败模型的', () => {
|
||||
assert.deepEqual([...MODEL_FALLBACK_CHAIN], ['claude-opus-4-8', 'claude-sonnet-4-6']);
|
||||
// 链已扩展为三项:fable → opus → sonnet
|
||||
assert.deepEqual([...MODEL_FALLBACK_CHAIN], ['claude-fable-5', 'claude-opus-4-8', 'claude-sonnet-4-6']);
|
||||
assert.equal(pickFallbackModel('claude-fable-5'), 'claude-opus-4-8');
|
||||
assert.equal(pickFallbackModel('claude-opus-4-8'), 'claude-sonnet-4-6');
|
||||
assert.equal(pickFallbackModel('claude-sonnet-4-6'), 'claude-opus-4-8');
|
||||
assert.equal(pickFallbackModel('claude-sonnet-4-6'), 'claude-fable-5');
|
||||
});
|
||||
|
||||
@@ -56,6 +56,8 @@ function mockDeps(overrides: Partial<PipelineDeps> = {}): PipelineDeps {
|
||||
reviewCode: async () => okReview,
|
||||
reviewSecurity: async () => okSecurity,
|
||||
runPlanner: async () => ({ ok: true, transcriptRef: '/tmp/plan.jsonl', sessionId: 'sess-plan', finalText: '方案正文' }),
|
||||
runConflict: async () => ({ ok: true, transcriptRef: null, sessionId: null, finalText: null }),
|
||||
syncMain: async () => null, // no-op:测试环境无真实 git worktree,跳过同步
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user