import { test } from 'node:test'; import assert from 'node:assert/strict'; import { parseVerdict, buildReviewPrompt } from '../src/executor/reviewer.js'; import type { Project, Task } from '../src/model/types.js'; test('parseVerdict:approve', () => { const { summary, verdict } = parseVerdict('## 做了什么\n改了 README\n\n## 结论\n建议通过\nVERDICT: approve'); assert.equal(verdict, 'approve'); assert.equal(summary, '## 做了什么\n改了 README\n\n## 结论\n建议通过'); // VERDICT 行已剔除 }); test('parseVerdict:reject(大小写/前后空白宽容)', () => { const { summary, verdict } = parseVerdict('问题很多\n verdict: REJECT \n'); assert.equal(verdict, 'reject'); assert.equal(summary, '问题很多'); }); test('parseVerdict:解析不到 = null,summary 原样保留', () => { const { summary, verdict } = parseVerdict('## 结论\n建议通过,但忘了写 VERDICT 行'); assert.equal(verdict, null); assert.equal(summary, '## 结论\n建议通过,但忘了写 VERDICT 行'); }); test('parseVerdict:多个 VERDICT 行取最后一个,全部从 summary 剔除', () => { const { summary, verdict } = parseVerdict('VERDICT: approve\n复查后改判\nVERDICT: reject'); assert.equal(verdict, 'reject'); assert.equal(summary, '复查后改判'); }); test('parseVerdict:VERDICT 行带多余内容不算(如模板原文 approve|reject)', () => { const { verdict } = parseVerdict('VERDICT: approve|reject'); assert.equal(verdict, null); }); test('buildReviewPrompt:含任务说明、执行者自述、diff 指令与固定模板', () => { const task = { id: 'task_1', title: '修复登录', operations: '改 auth.ts', spec: null, plan: null } as Task; const project = { defaultBranch: 'main' } as Project; const wt = { dir: '/tmp/wt', branch: 'maestro/task_1' }; const prompt = buildReviewPrompt(task, project, wt, '我改了 auth.ts 并加了测试'); assert.match(prompt, /修复登录/); assert.match(prompt, /改 auth\.ts/); assert.match(prompt, /我改了 auth\.ts 并加了测试/); assert.match(prompt, /git diff main\.\.\.maestro\/task_1/); for (const section of ['## 做了什么', '## 怎么做的', '## 测试情况', '## Code Review', '## 安全 Review', '## 结论']) { assert.ok(prompt.includes(section), `模板缺少 ${section}`); } assert.match(prompt, /VERDICT: approve\|reject/); assert.match(prompt, /只读权限/); }); test('buildReviewPrompt:执行者无自述时给占位说明', () => { const task = { id: 'task_2', title: 't', operations: null, spec: null, plan: null } as Task; const project = { defaultBranch: 'main' } as Project; const prompt = buildReviewPrompt(task, project, { dir: '/x', branch: 'maestro/task_2' }, ''); assert.match(prompt, /执行者未留下自述/); });