diff --git a/skills/chatgpt-review/scripts/lib/prompt.mjs b/skills/chatgpt-review/scripts/lib/prompt.mjs index b315c79b..6d957ed7 100644 --- a/skills/chatgpt-review/scripts/lib/prompt.mjs +++ b/skills/chatgpt-review/scripts/lib/prompt.mjs @@ -18,7 +18,10 @@ export function buildPrompt({ mode, target, context = '', publish = false, pass return `${UNTRUSTED}\n\nCritically investigate ${target.canonicalUrl}. Browse the repository and relevant history as needed. Evaluate whether the issue is accurate, sufficiently specified, feasible, and testable; identify hidden constraints and simpler options.\n${contextBlock}\n${publication}`; } if (mode === 'plan') { - return `${UNTRUSTED}\n\nThe complete proposed implementation plan is attached as ${uploadName}. Critically review whether it closes the stated acceptance gap, respects the repository architecture and seams, has a safe migration order and rollback story, and includes adequate tests. Identify omissions and simpler designs.\n${contextBlock}\nDo not write anything to GitHub or any other external system. Return the review only in this chat.`; + const passTask = pass === 1 + ? 'Critically review whether it closes the stated acceptance gap, respects the repository architecture and seams, has a safe migration order and rollback story, and includes adequate tests. Identify omissions and simpler designs.' + : `This is revision review pass ${pass} of the SAME plan, in the SAME conversation as your earlier pass(es). The attached file is the current revision: it already folds in the findings you previously raised that were accepted, and it carries its own "## Review responses" section recording, with cited evidence, every finding you raised that was rejected. Do NOT re-raise a finding already addressed in "## Review responses" unless you have genuinely new evidence — if you still disagree with a rebuttal there, explicitly engage with and refute its cited evidence rather than restating your original claim. Otherwise review the plan fresh: does it now close the stated acceptance gap, respect the repository architecture and seams, have a safe migration order and rollback story, and include adequate tests? Identify any remaining omissions or simpler designs.`; + return `${UNTRUSTED}\n\nThe complete proposed implementation plan is attached as ${uploadName}. ${passTask}\n${contextBlock}\nDo not write anything to GitHub or any other external system. Return the review only in this chat.`; } if (mode === 'plan-author') { // No attachment on a revision pass: this is a follow-up message in the SAME diff --git a/skills/chatgpt-review/tests/core.test.mjs b/skills/chatgpt-review/tests/core.test.mjs index 365b7eb7..f16a69de 100644 --- a/skills/chatgpt-review/tests/core.test.mjs +++ b/skills/chatgpt-review/tests/core.test.mjs @@ -64,9 +64,15 @@ test('prompts enforce investigation, trust, publication, and follow-up contracts assert.match(followup, new RegExp('a{40}')); assert.match(followup, /Do not edit or replace/); assert.match(buildPrompt({ mode: 'issue', target: { ...target, canonicalUrl: 'https://github.com/o/r/issues/9' }, publish: false, pass: 1 }), /Do not post/); - const plan = buildPrompt({ mode: 'plan', uploadName: 'exact-plan.md', context: 'acceptance' }); + const plan = buildPrompt({ mode: 'plan', uploadName: 'exact-plan.md', context: 'acceptance', pass: 1 }); assert.match(plan, /attached as exact-plan\.md/); assert.match(plan, /Do not write anything to GitHub/); + assert.doesNotMatch(plan, /SAME conversation/); + const planRevision = buildPrompt({ mode: 'plan', uploadName: 'exact-plan.md', context: 'acceptance', pass: 2 }); + assert.match(planRevision, /revision review pass 2 of the SAME plan, in the SAME conversation/); + assert.match(planRevision, /"## Review responses" section/); + assert.match(planRevision, /explicitly engage with and refute its cited evidence/); + assert.doesNotMatch(planRevision, /Critically review whether it closes the stated acceptance gap, respects the repository architecture and seams, has a safe migration order and rollback story, and includes adequate tests\. Identify omissions/); const author = buildPrompt({ mode: 'plan-author', target: { canonicalUrl: 'https://github.com/o/r/issues/9' }, pass: 1, context: 'delivery contract' }); assert.match(author, /Browse the issue, the actual repository, CLAUDE\.md/); assert.match(author, /PLAN_STATUS: READY/);