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:
@@ -76,10 +76,9 @@ export function isModelError(msg: string): boolean {
|
||||
return /not[_\s-]?found|invalid|permission|forbidden|unauthorized|unavailable|unknown|unsupported|does not exist|no access|404|403/i.test(msg);
|
||||
}
|
||||
|
||||
/** 回退链里取第一个与失败模型不同的;链上全相同(不可能两项都等)则 null */
|
||||
/** 回退链里取失败模型的下一档(循环);未在链上则取首档。 */
|
||||
export function pickFallbackModel(failedModel: string): string | null {
|
||||
for (const m of MODEL_FALLBACK_CHAIN) {
|
||||
if (m !== failedModel) return m;
|
||||
}
|
||||
return null;
|
||||
const idx = MODEL_FALLBACK_CHAIN.indexOf(failedModel as typeof MODEL_FALLBACK_CHAIN[number]);
|
||||
if (idx === -1) return MODEL_FALLBACK_CHAIN[0];
|
||||
return MODEL_FALLBACK_CHAIN[(idx + 1) % MODEL_FALLBACK_CHAIN.length];
|
||||
}
|
||||
|
||||
+26
-22
@@ -29,6 +29,27 @@ export interface PipelineDeps {
|
||||
reviewSecurity: ReviewerFn; // 安全审计(daemon 落成 kind=security 的 run)
|
||||
runPlanner: PlannerFn; // planner(拆解 Hard / 写方案 Medium,只读跑 CC)
|
||||
runConflict: typeof runConflict; // 解冲突(conflict run)
|
||||
/** 执行前同步 defaultBranch:返回 null=成功,string=错误信息(已 abort)。可测试 mock。 */
|
||||
syncMain?: (dir: string, defaultBranch: string) => Promise<string | null>;
|
||||
}
|
||||
|
||||
/** 执行前同步 defaultBranch 默认实现:fetch→merge origin/<branch>;失败再试本地 <branch>。 */
|
||||
async function defaultSyncMain(dir: string, defaultBranch: string): Promise<string | null> {
|
||||
try {
|
||||
await git(dir, ['fetch', 'origin', defaultBranch]);
|
||||
} catch { /* 无远端时跳过 fetch,直接用本地 */ }
|
||||
try {
|
||||
await git(dir, ['-c', 'user.name=maestro', '-c', 'user.email=maestro@local', 'merge', '--no-edit', `origin/${defaultBranch}`]);
|
||||
return null;
|
||||
} catch {
|
||||
try {
|
||||
await git(dir, ['-c', 'user.name=maestro', '-c', 'user.email=maestro@local', 'merge', '--no-edit', defaultBranch]);
|
||||
return null;
|
||||
} catch (e) {
|
||||
await git(dir, ['merge', '--abort']).catch(() => undefined);
|
||||
return (e as Error).message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 真实依赖(worker 生产用)。 */
|
||||
@@ -90,28 +111,11 @@ export async function runPipeline(job: JobSpec, deps: PipelineDeps = realDeps, e
|
||||
const wt = await deps.createWorktree(job.project.repoPath, job.task.id, job.project.defaultBranch);
|
||||
|
||||
// sync main:把 defaultBranch 最新代码 merge 进 worktree(排队期间 main 可能已前移)
|
||||
try {
|
||||
await git(wt.dir, ['fetch', 'origin', job.project.defaultBranch]);
|
||||
} catch { /* 无远端时跳过 fetch,直接用本地 */ }
|
||||
try {
|
||||
await git(wt.dir, [
|
||||
'-c', 'user.name=maestro', '-c', 'user.email=maestro@local',
|
||||
'merge', '--no-edit', `origin/${job.project.defaultBranch}`,
|
||||
]);
|
||||
} catch {
|
||||
// 尝试用本地分支
|
||||
try {
|
||||
await git(wt.dir, [
|
||||
'-c', 'user.name=maestro', '-c', 'user.email=maestro@local',
|
||||
'merge', '--no-edit', job.project.defaultBranch,
|
||||
]);
|
||||
} catch (e) {
|
||||
// sync main 失败(冲突或其他)→ abort 并报失败,让 daemon 转 needs_attention
|
||||
await git(wt.dir, ['merge', '--abort']).catch(() => undefined);
|
||||
emit({ type: 'failed', error: `执行前同步 ${job.project.defaultBranch} 失败,建议重新评估方案:${(e as Error).message}`, transcriptRef: null, sessionId: null });
|
||||
emit({ type: 'done' });
|
||||
return;
|
||||
}
|
||||
const syncErr = await (deps.syncMain ?? defaultSyncMain)(wt.dir, job.project.defaultBranch);
|
||||
if (syncErr !== null) {
|
||||
emit({ type: 'failed', error: `执行前同步 ${job.project.defaultBranch} 失败,建议重新评估方案:${syncErr}`, transcriptRef: null, sessionId: null });
|
||||
emit({ type: 'done' });
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 执行
|
||||
|
||||
Reference in New Issue
Block a user