-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprompts.js
More file actions
327 lines (251 loc) · 16.4 KB
/
Copy pathprompts.js
File metadata and controls
327 lines (251 loc) · 16.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
'use strict';
/**
* Duet 프롬프트 템플릿
*
* 구현자(IMPLEMENTER)와 리뷰어(REVIEWER)에게 전달되는 프롬프트 문자열을 생성합니다.
* 각 역할은 작업별로 Claude/Codex 중 선택되므로(t.implementer/t.reviewer)
* 프롬프트는 엔진명이 아닌 역할명을 사용합니다. 오케스트레이션은 orchestrator.js.
*
* 마이크로 이터레이션 구조:
* - planPrompt: 요구사항을 작은 스텝으로 분해 (PLAN_JSON 마커로 출력)
* - implementStepPrompt / reviseStepPrompt: 한 번에 한 스텝만 구현/수정
* - reviewStepPrompt: 해당 스텝만 리뷰 (VERDICT 형식 유지)
* plan이 단일 스텝이면 사실상 기존(전체 한 덩어리) 동작과 같아집니다.
*/
/* ──────────────────────────── 후속 작업(이어가기) 컨텍스트 ──────────────────────────── */
/** 구현자용: 이전 작업 위에 이어서 작업함을 알린다. 후속 작업이 아니면 빈 문자열. */
function followupImplementNote(t) {
if (!t.parentId) return '';
const sessionNote = t.claudeSessionId
? ' This conversation is resumed from that task, so you may remember the details.'
: '';
return `This is a FOLLOW-UP task: you previously completed work in this same working directory.${sessionNote}
Previous task requirement:
<previous_requirement>
${t.parentRequirement || '(unknown)'}
</previous_requirement>
The codebase already contains that work. Build on the existing code — do not start from scratch and do not break existing behavior.
`;
}
/** 리뷰어용: 기존 코드는 이미 승인된 컨텍스트임을 알린다. 후속 작업이 아니면 빈 문자열. */
function followupReviewNote(t) {
if (!t.parentId) return '';
return `Note: this requirement is a FOLLOW-UP to earlier work already completed and approved in this directory (previous requirement: "${t.parentRequirement || '(unknown)'}"). Review the implementation of the NEW requirement; treat pre-existing code as accepted context unless the new changes break it.
`;
}
function acceptanceCriteriaNote(t) {
const criteria = Array.isArray(t.acceptanceCriteria) ? t.acceptanceCriteria.filter(Boolean) : [];
if (!criteria.length) return '';
return `Acceptance criteria:
${criteria.map((c, i) => `${i + 1}. ${c}`).join('\n')}
Treat these criteria as the primary completion contract. Do not approve until every applicable criterion is satisfied.
`;
}
function verificationCommandsNote(t) {
const commands = Array.isArray(t.verificationCommands) ? t.verificationCommands.filter(Boolean) : [];
if (!commands.length) return '';
return `Suggested verification commands detected by the orchestrator:
${commands.map((c) => `- ${c}`).join('\n')}
Run the relevant commands when you verify unless there is a clear reason not to, and report any command you skipped.
`;
}
/* ──────────────────────────── 분해(Plan) ──────────────────────────── */
function planPrompt(t) {
return `You are the IMPLEMENTER in an automated pair-programming loop. Before writing any code, break the requirement below into a short ordered list of small, independently verifiable steps. Your partner, the REVIEWER, will review your work one step at a time.
${followupImplementNote(t)}Task requirement:
<requirement>
${t.requirement}
</requirement>
${acceptanceCriteriaNote(t)}
Guidelines for the plan:
- Each step should be a small, self-contained unit that can be implemented and reviewed on its own (think "one small commit").
- Order steps so each builds on the previous ones.
- Match the plan size to the requirement size. If the requirement is trivial (a single small file, a one-liner, a tiny fix), output exactly ONE step — do not pad the plan. For substantial work prefer 3–8 steps. Do NOT over-split into trivial steps, and do NOT lump everything into one giant step.
- Do NOT implement anything yet — only produce the plan.
End your message with EXACTLY this marker on its own line, followed by a JSON array of steps:
PLAN_JSON:
[{"title": "short imperative description of step 1"}, {"title": "step 2"}]
Write the step titles in Korean (한국어), regardless of the language of the requirement.`;
}
/* ──────────────────────────── 구현(Implement) ──────────────────────────── */
function stepHeader(t, step, plan, stepIndex, total) {
const list = plan
.map((s, i) => {
const mark = i < stepIndex ? '[done]' : i === stepIndex ? '[NOW]' : '[todo]';
return ` ${i + 1}. ${mark} ${s.title}`;
})
.join('\n');
return `Task requirement (overall goal, for context):
<requirement>
${t.requirement}
</requirement>
${acceptanceCriteriaNote(t)}
Full plan (${total} steps):
${list}
You are working on step ${stepIndex + 1}/${total}: "${step.title}"
Steps marked [done] are already implemented and approved — do not redo them, but you may build on them.`;
}
const PLAN_UPDATE_NOTE = `If — and only if — you discover the remaining plan needs to change (a step should be added, removed, split, or reworded), append at the very end of your message EXACTLY this marker on its own line followed by a JSON array of the REMAINING steps (everything AFTER the current one):
PLAN_UPDATE:
[{"title": "..."}]
Omit the marker entirely if the remaining plan is fine.`;
// 구현자가 dev 서버 등을 띄워둔 채 종료하면 stdio 파이프를 물고 있는 고아
// 프로세스 때문에 오케스트레이터가 다음 단계로 진행하지 못한다(실제 발생).
const NO_BACKGROUND_NOTE = `IMPORTANT: do NOT leave long-running background processes (dev servers, watchers, etc.) running when you finish — verify what you need, then shut them down BEFORE writing your final summary. Orphaned processes block the automation loop.`;
function implementStepPrompt(t, step, plan, stepIndex, total) {
return `You are the IMPLEMENTER in an automated pair-programming loop. The REVIEWER will review this step after you finish.
${stepHeader(t, step, plan, stepIndex, total)}
Implement ONLY this step in the current working directory. Write real, working code — create files, run commands, and verify your work where possible. Do not jump ahead to later steps.
${NO_BACKGROUND_NOTE}
When you are done, end with a concise summary of WHAT you implemented for this step, WHICH files you touched, and HOW to run/verify it.
${PLAN_UPDATE_NOTE}
Always respond in Korean (한국어), regardless of the language of the requirement.`;
}
function reviseStepPrompt(t, step, feedback, stepIndex, total, plan) {
return `The REVIEWER reviewed step ${stepIndex + 1}/${total} ("${step.title}") and requests changes. Address EVERY point below, then re-verify your work for this step.
Reviewer feedback:
<feedback>
${feedback}
</feedback>
(Overall requirement, for reference: ${t.requirement})
Stay focused on the current step only. ${NO_BACKGROUND_NOTE}
When done, end with a concise summary of the changes you made in response to each point.
${PLAN_UPDATE_NOTE}
Always respond in Korean (한국어), regardless of the language of the requirement.`;
}
/* ──────────────────────────── 리뷰(Review) ──────────────────────────── */
/** 리뷰어 권한에 따른 검증 지침. 작업 제출 시 선택한 권한 모드가 리뷰어
엔진에 공통 적용된다 — read-only면 Codex는 샌드박스로, Claude는 셸 차단으로
실행이 막힌다. 어느 쪽이든 리뷰어는 파일을 수정하지 않는다(구현자의 몫). */
function sandboxNote(t) {
const canRun = (t.codexSandbox || 'bypass') !== 'read-only';
return canRun
? 'You have permission to execute commands — actually RUN the code/tests to verify the claimed behavior before giving your verdict. However, you must NOT create, modify, or delete any files: you are the reviewer, not the implementer. Report issues in your verdict for the implementer to fix.'
: 'Your sandbox is read-only: verify by reading the code (running it may be blocked by policy — do not treat blocked commands as implementation failures). Do not attempt to modify any files.';
}
function verdictRule(t, iteration) {
const min = Math.max(1, Number(t.minIterations) || 1);
if (iteration >= min) {
return `Your final message MUST start with exactly one of these lines:
VERDICT: APPROVED
VERDICT: CHANGES_REQUESTED`;
}
return `This task is configured for improvement rounds: minimum ${min} review iterations before final approval. This is review iteration ${iteration}, so you MUST NOT use VERDICT: APPROVED yet.
Your final message MUST start with exactly this line:
VERDICT: CHANGES_REQUESTED
If you found correctness, security, or regression issues, list those first. If the implementation already satisfies the original requirement, request exactly ONE narrowly scoped, high-value improvement for the next round. Prefer improvements that reduce real risk, improve maintainability, strengthen tests, remove duplication, or clarify types. Do not ask for broad rewrites, cosmetic churn, or unrelated features.`;
}
function reviewStepPrompt(t, step, report, plan, stepIndex, total, iteration) {
return `You are the REVIEWER in an automated pair-programming loop. The IMPLEMENTER just finished attempt ${iteration} on step ${stepIndex + 1}/${total} of the plan.
Overall requirement (for context only):
<requirement>
${t.requirement}
</requirement>
${followupReviewNote(t)}The step you are reviewing NOW: "${step.title}"
Review ONLY whether THIS step is correctly and completely implemented. Do not demand work that belongs to later steps of the plan; later steps will be reviewed separately. Earlier steps were already approved.
Implementer's report for this step:
<report>
${report}
</report>
Do NOT trust the report — inspect the actual files in the working directory and verify that this step is fully and correctly implemented, and that the code quality is acceptable (correctness first; style nitpicks only if serious).
${acceptanceCriteriaNote(t)}${verificationCommandsNote(t)}
${sandboxNote(t)}
${verdictRule(t, iteration)}
If CHANGES_REQUESTED, follow the verdict line with a concrete, numbered list of issues for THIS step, each actionable for the implementer. Only approve when you have NO further requirements for this step.
End your response with this exact marker followed by valid JSON:
REVIEW_JSON:
{"verdict":"APPROVED|CHANGES_REQUESTED","criteria":[{"id":"criterion or inferred check","status":"pass|fail|unknown","evidence":"short evidence"}],"requiredChanges":["actionable change"],"verification":["command and result"],"riskLevel":"low|medium|high"}
Always respond in Korean (한국어), regardless of the language of the requirement.`;
}
/* ──────────────────────────── 단일 루프(single 모드) ────────────────────────────
요구사항 전체를 한 덩어리로 구현·리뷰하는 기존 방식. 마이크로 이터레이션과의
A/B 성능 비교(bench.js)를 위해 보존한다. */
function implementPrompt(t) {
return `You are the IMPLEMENTER in an automated pair-programming loop. Your partner, the REVIEWER, will review your work after you finish.
${followupImplementNote(t)}Task requirement:
<requirement>
${t.requirement}
</requirement>
${acceptanceCriteriaNote(t)}
Implement this requirement in the current working directory. Write real, working code — create files, run commands, and verify your work where possible.
${verificationCommandsNote(t)}
${NO_BACKGROUND_NOTE}
When you are done, end with a concise summary of WHAT you implemented, WHICH files you touched, and HOW to run/verify it. Always respond in Korean (한국어), regardless of the language of the requirement.`;
}
function revisePrompt(t, feedback) {
return `The REVIEWER reviewed your implementation and requests changes. Address EVERY point below, then re-verify your work.
Reviewer feedback:
<feedback>
${feedback}
</feedback>
(Original requirement, for reference: ${t.requirement})
${NO_BACKGROUND_NOTE}
When done, end with a concise summary of the changes you made in response to each point. Always respond in Korean (한국어), regardless of the language of the requirement.`;
}
function reviewPrompt(t, report, iteration) {
return `You are the REVIEWER in an automated pair-programming loop. The IMPLEMENTER just finished iteration ${iteration} of ${t.maxIterations}.
Task requirement:
<requirement>
${t.requirement}
</requirement>
${followupReviewNote(t)}Implementer's report:
<report>
${report}
</report>
Do NOT trust the report — inspect the actual files in the working directory and verify that the requirement is fully and correctly implemented, and that the code quality is acceptable (correctness first; style nitpicks only if serious).
${acceptanceCriteriaNote(t)}${verificationCommandsNote(t)}
${sandboxNote(t)}
${verdictRule(t, iteration)}
If CHANGES_REQUESTED, follow the verdict line with a concrete, numbered list of issues or missing requirements, each actionable for the implementer. Only approve when you have NO further requirements.
End your response with this exact marker followed by valid JSON:
REVIEW_JSON:
{"verdict":"APPROVED|CHANGES_REQUESTED","criteria":[{"id":"criterion or inferred check","status":"pass|fail|unknown","evidence":"short evidence"}],"requiredChanges":["actionable change"],"verification":["command and result"],"riskLevel":"low|medium|high"}
Always respond in Korean (한국어), regardless of the language of the requirement.`;
}
/* ──────────────────────────── 선리뷰 루프(review 모드) ────────────────────────────
Codex가 먼저 기존 코드를 리뷰하고, 지적사항이 있으면 Claude가 수정하는 역순 루프.
리뷰/감사형 요구사항("이 코드 리뷰해줘", "보안 점검해줘")에 사용한다. */
function reviewFirstPrompt(t, iteration = 1) {
return `You are the REVIEWER in an automated pair-programming loop. This is a REVIEW-FIRST task: you act before the implementer. Review the EXISTING code in the current working directory against the request below. If you raise issues, your partner, the IMPLEMENTER, will fix them and you will re-review.
Review request:
<requirement>
${t.requirement}
</requirement>
${acceptanceCriteriaNote(t)}
${followupReviewNote(t)}Inspect the actual files in the working directory. If the request names specific files, areas, or concerns, focus there; otherwise review for correctness first, then security and code quality (style nitpicks only if serious).
${verificationCommandsNote(t)}
${sandboxNote(t)}
${verdictRule(t, iteration)}
If CHANGES_REQUESTED, follow the verdict line with a concrete, numbered list of issues, each actionable for the implementer. Use APPROVED only when you have NO findings worth fixing.
End your response with this exact marker followed by valid JSON:
REVIEW_JSON:
{"verdict":"APPROVED|CHANGES_REQUESTED","criteria":[{"id":"criterion or inferred check","status":"pass|fail|unknown","evidence":"short evidence"}],"requiredChanges":["actionable change"],"verification":["command and result"],"riskLevel":"low|medium|high"}
Always respond in Korean (한국어), regardless of the language of the requirement.`;
}
function fixPrompt(t, feedback) {
return `You are the IMPLEMENTER in an automated pair-programming loop. The REVIEWER reviewed the existing code in the current working directory against the request below and produced the findings. Address EVERY point, then re-verify your work. The REVIEWER will re-review after you finish.
${followupImplementNote(t)}Review request:
<requirement>
${t.requirement}
</requirement>
Reviewer findings:
<feedback>
${feedback}
</feedback>
${NO_BACKGROUND_NOTE}
When done, end with a concise summary of the changes you made in response to each finding. Always respond in Korean (한국어), regardless of the language of the requirement.`;
}
module.exports = {
// 마이크로 이터레이션 (micro 모드)
planPrompt,
implementStepPrompt,
reviseStepPrompt,
reviewStepPrompt,
// 단일 루프 (single 모드)
implementPrompt,
revisePrompt,
reviewPrompt,
// 선리뷰 루프 (review 모드)
reviewFirstPrompt,
fixPrompt,
};