planpong 0.4.2 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/planpong.js +37 -1
- package/dist/bin/planpong.js.map +1 -1
- package/dist/src/config/defaults.js +1 -0
- package/dist/src/config/defaults.js.map +1 -1
- package/dist/src/config/loader.d.ts +1 -0
- package/dist/src/config/loader.js +3 -0
- package/dist/src/config/loader.js.map +1 -1
- package/dist/src/core/apply-edits.d.ts +40 -0
- package/dist/src/core/apply-edits.js +220 -0
- package/dist/src/core/apply-edits.js.map +1 -0
- package/dist/src/core/convergence.d.ts +18 -2
- package/dist/src/core/convergence.js +21 -9
- package/dist/src/core/convergence.js.map +1 -1
- package/dist/src/core/operations.d.ts +14 -1
- package/dist/src/core/operations.js +551 -62
- package/dist/src/core/operations.js.map +1 -1
- package/dist/src/core/plan-diff.d.ts +23 -0
- package/dist/src/core/plan-diff.js +135 -0
- package/dist/src/core/plan-diff.js.map +1 -0
- package/dist/src/core/session.d.ts +11 -0
- package/dist/src/core/session.js +51 -1
- package/dist/src/core/session.js.map +1 -1
- package/dist/src/mcp/tools/get-feedback.d.ts +16 -0
- package/dist/src/mcp/tools/get-feedback.js +118 -114
- package/dist/src/mcp/tools/get-feedback.js.map +1 -1
- package/dist/src/mcp/tools/revise.d.ts +16 -0
- package/dist/src/mcp/tools/revise.js +76 -61
- package/dist/src/mcp/tools/revise.js.map +1 -1
- package/dist/src/mcp/tools/status.js +15 -1
- package/dist/src/mcp/tools/status.js.map +1 -1
- package/dist/src/prompts/planner.d.ts +34 -1
- package/dist/src/prompts/planner.js +239 -4
- package/dist/src/prompts/planner.js.map +1 -1
- package/dist/src/prompts/reviewer.d.ts +13 -0
- package/dist/src/prompts/reviewer.js +65 -0
- package/dist/src/prompts/reviewer.js.map +1 -1
- package/dist/src/providers/claude.js +19 -3
- package/dist/src/providers/claude.js.map +1 -1
- package/dist/src/providers/codex.js +50 -3
- package/dist/src/providers/codex.js.map +1 -1
- package/dist/src/providers/types.d.ts +20 -0
- package/dist/src/schemas/config.d.ts +3 -0
- package/dist/src/schemas/config.js +6 -0
- package/dist/src/schemas/config.js.map +1 -1
- package/dist/src/schemas/json-schema.d.ts +12 -0
- package/dist/src/schemas/json-schema.js +20 -1
- package/dist/src/schemas/json-schema.js.map +1 -1
- package/dist/src/schemas/metrics.d.ts +171 -0
- package/dist/src/schemas/metrics.js +49 -0
- package/dist/src/schemas/metrics.js.map +1 -0
- package/dist/src/schemas/revision.d.ts +166 -2
- package/dist/src/schemas/revision.js +35 -2
- package/dist/src/schemas/revision.js.map +1 -1
- package/dist/src/schemas/session.d.ts +6 -0
- package/dist/src/schemas/session.js +10 -0
- package/dist/src/schemas/session.js.map +1 -1
- package/package.json +1 -1
|
@@ -17,7 +17,10 @@ Output ONLY the markdown plan. No preamble, no commentary.
|
|
|
17
17
|
|
|
18
18
|
${requirements}`;
|
|
19
19
|
}
|
|
20
|
-
export function buildRevisionPrompt(currentPlan, feedback, keyDecisions, priorContext, phase = "detail", structuredOutput = false) {
|
|
20
|
+
export function buildRevisionPrompt(currentPlan, feedback, keyDecisions, priorContext, phase = "detail", structuredOutput = false, revisionMode = "full") {
|
|
21
|
+
// Direction phase always uses full-plan output (sweeping rewrites are
|
|
22
|
+
// expected). Risk + detail phases honor `revisionMode`.
|
|
23
|
+
const useEdits = revisionMode === "edits" && phase !== "direction";
|
|
21
24
|
const contextBlock = priorContext
|
|
22
25
|
? `\n## Prior Research & Constraints\n\n${priorContext}\n`
|
|
23
26
|
: "";
|
|
@@ -104,7 +107,7 @@ For each response, cite specific evidence: reference the plan section, the resea
|
|
|
104
107
|
- Do not reorganize or rephrase parts of the plan unrelated to risk feedback.`
|
|
105
108
|
: `- Only modify sections of the plan that are directly addressed by accepted feedback. Do not reorganize, rephrase, or "improve" parts of the plan that aren't related to any issue.
|
|
106
109
|
- Preserve the plan's existing structure, headings, and formatting. Your job is surgical revision, not rewriting.`;
|
|
107
|
-
const
|
|
110
|
+
const fullSchemaBlock = `\`\`\`
|
|
108
111
|
{
|
|
109
112
|
"responses": [
|
|
110
113
|
{
|
|
@@ -121,6 +124,47 @@ For each response, cite specific evidence: reference the plan section, the resea
|
|
|
121
124
|
"updated_plan": "The full updated plan in markdown (incorporate accepted changes)"
|
|
122
125
|
}
|
|
123
126
|
\`\`\``;
|
|
127
|
+
// Edits-mode schema for risk + detail phases: planner emits a structured
|
|
128
|
+
// edit list instead of the full plan. Each edit is section-scoped — the
|
|
129
|
+
// applier locates the section heading, then finds `before` within that
|
|
130
|
+
// section's content. `before` MUST be unique within the section.
|
|
131
|
+
const editsSchemaBlock = `\`\`\`
|
|
132
|
+
{
|
|
133
|
+
"responses": [
|
|
134
|
+
{
|
|
135
|
+
"issue_id": "F1",
|
|
136
|
+
"action": "accepted" | "rejected" | "deferred",
|
|
137
|
+
"severity_dispute": { // optional
|
|
138
|
+
"original": "P1",
|
|
139
|
+
"revised": "P2",
|
|
140
|
+
"justification": "..."
|
|
141
|
+
},
|
|
142
|
+
"rationale": "Detailed explanation of why this action was taken"
|
|
143
|
+
}
|
|
144
|
+
],
|
|
145
|
+
"edits": [
|
|
146
|
+
{
|
|
147
|
+
"section": "Steps",
|
|
148
|
+
"before": "verbatim text from the plan to replace (must appear EXACTLY ONCE within the named section)",
|
|
149
|
+
"after": "replacement text (may be empty for deletion)"
|
|
150
|
+
}
|
|
151
|
+
]
|
|
152
|
+
}
|
|
153
|
+
\`\`\``;
|
|
154
|
+
const schemaBlock = useEdits ? editsSchemaBlock : fullSchemaBlock;
|
|
155
|
+
// Edits-mode constraints. The applier is strict: section-scoped lookup,
|
|
156
|
+
// unique-match-within-section enforcement, no plan-wide fallback. The
|
|
157
|
+
// prompt has to make those constraints visible so the planner produces
|
|
158
|
+
// edits that actually apply.
|
|
159
|
+
const editsConstraints = `- Output edits, NOT the full plan. The plan is updated server-side by replaying your edits.
|
|
160
|
+
- Each edit's \`section\` is the nearest markdown heading label (e.g., "Steps", "Limitations & Future Work"). The applier searches ONLY within that section's content.
|
|
161
|
+
- Each edit's \`before\` must appear EXACTLY ONCE within the named section, character-for-character (whitespace tolerant). If the same text appears multiple times in the section, expand \`before\` with surrounding context until it is unique within the section.
|
|
162
|
+
- Use the SHORTEST \`before\` that is unambiguous. Do not quote large unchanged blocks.
|
|
163
|
+
- \`after\` is the replacement. Empty string deletes; non-empty replaces.
|
|
164
|
+
- For an addition, set \`before\` to a short stable anchor (e.g., the line before the insertion point) and \`after\` to that anchor plus the new content.
|
|
165
|
+
- Edits run sequentially: later edits see earlier edits' results. If you have multiple edits in the same section, order them so each one's \`before\` is unique against the running plan state.
|
|
166
|
+
- Keep the total number of edits small — only what is needed to address accepted issues. One issue typically maps to one edit.`;
|
|
167
|
+
const fullModeConstraint = `- The \`updated_plan\` must be the complete plan markdown, not a diff.`;
|
|
124
168
|
const commonBody = `${roleInstructions}
|
|
125
169
|
${contextBlock}${decisionsBlock}
|
|
126
170
|
## Current Plan
|
|
@@ -134,6 +178,7 @@ ${currentPlan}
|
|
|
134
178
|
${issuesList}
|
|
135
179
|
|
|
136
180
|
## Your Task`;
|
|
181
|
+
const outputConstraint = useEdits ? editsConstraints : fullModeConstraint;
|
|
137
182
|
if (structuredOutput) {
|
|
138
183
|
// Structured-output mode. Some providers constrain output at the token
|
|
139
184
|
// level; others only validate post-hoc. Emphatic JSON-only instructions
|
|
@@ -148,7 +193,7 @@ ${schemaBlock}
|
|
|
148
193
|
|
|
149
194
|
Constraints embedded in your JSON response:
|
|
150
195
|
- Every issue MUST have an entry in \`responses\`. Do not skip any.
|
|
151
|
-
|
|
196
|
+
${outputConstraint}
|
|
152
197
|
${surgicalConstraint}
|
|
153
198
|
- Do NOT modify the \`**planpong:**\` status line — it is managed automatically.`;
|
|
154
199
|
}
|
|
@@ -160,11 +205,201 @@ ${schemaBlock}
|
|
|
160
205
|
|
|
161
206
|
IMPORTANT:
|
|
162
207
|
- Every issue MUST have a response. Do not skip any.
|
|
163
|
-
|
|
208
|
+
${outputConstraint}
|
|
164
209
|
${surgicalConstraint}
|
|
165
210
|
- Do NOT modify the \`**planpong:**\` status line — it is managed automatically.
|
|
166
211
|
- Wrap your JSON response in <planpong-revision>...</planpong-revision> tags.
|
|
167
212
|
|
|
213
|
+
<planpong-revision>
|
|
214
|
+
YOUR_JSON_HERE
|
|
215
|
+
</planpong-revision>`;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Build a minimal revision prompt for resumed planner sessions.
|
|
219
|
+
*
|
|
220
|
+
* The planner is already in a persistent CLI conversation that has the
|
|
221
|
+
* plan, the prior reviewer feedback, and the planner's own prior rationales
|
|
222
|
+
* in context. We do NOT re-send "Current Plan", "Prior Decisions", or
|
|
223
|
+
* "Key Decisions" — the model has all of that. Only the new feedback +
|
|
224
|
+
* minimal phase reminder + output schema instructions.
|
|
225
|
+
*
|
|
226
|
+
* The output schema and surgical constraints stay because they're per-call
|
|
227
|
+
* directives, not stable context. (We don't trust that the model won't
|
|
228
|
+
* drift in format across many turns of a long session.)
|
|
229
|
+
*/
|
|
230
|
+
export function buildIncrementalRevisionPrompt(feedback, phase, structuredOutput, revisionMode = "full") {
|
|
231
|
+
const useEdits = revisionMode === "edits" && phase !== "direction";
|
|
232
|
+
const issuesList = feedback.issues
|
|
233
|
+
.map((issue) => `### ${issue.id} (${issue.severity}): ${issue.title}\n**Section:** ${issue.section}\n**Description:** ${issue.description}\n**Suggestion:** ${issue.suggestion}`)
|
|
234
|
+
.join("\n\n");
|
|
235
|
+
const phaseLabel = phase === "direction"
|
|
236
|
+
? "DIRECTION"
|
|
237
|
+
: phase === "risk"
|
|
238
|
+
? "RISK / PRE-MORTEM"
|
|
239
|
+
: "DETAIL";
|
|
240
|
+
const surgicalConstraint = phase === "direction"
|
|
241
|
+
? `- You may make structural changes (reorder sections, change approach, adjust scope) if accepted feedback warrants it.
|
|
242
|
+
- Preserve sections that aren't affected by the feedback.`
|
|
243
|
+
: phase === "risk"
|
|
244
|
+
? `- Add mitigations, verification steps, or fallback procedures for accepted risks.
|
|
245
|
+
- You may add new sections (e.g., "Risks & Mitigations") if needed.
|
|
246
|
+
- Do not reorganize or rephrase parts of the plan unrelated to risk feedback.`
|
|
247
|
+
: `- Only modify sections of the plan that are directly addressed by accepted feedback.
|
|
248
|
+
- Preserve the plan's existing structure, headings, and formatting. Surgical revision, not rewriting.`;
|
|
249
|
+
const fullSchemaBlock = `\`\`\`
|
|
250
|
+
{
|
|
251
|
+
"responses": [
|
|
252
|
+
{ "issue_id": "F1", "action": "accepted" | "rejected" | "deferred",
|
|
253
|
+
"severity_dispute": { "original": "P1", "revised": "P2", "justification": "..." }, // optional
|
|
254
|
+
"rationale": "Why this action" }
|
|
255
|
+
],
|
|
256
|
+
"updated_plan": "The full updated plan in markdown"
|
|
257
|
+
}
|
|
258
|
+
\`\`\``;
|
|
259
|
+
const editsSchemaBlock = `\`\`\`
|
|
260
|
+
{
|
|
261
|
+
"responses": [
|
|
262
|
+
{ "issue_id": "F1", "action": "accepted" | "rejected" | "deferred",
|
|
263
|
+
"severity_dispute": { "original": "P1", "revised": "P2", "justification": "..." }, // optional
|
|
264
|
+
"rationale": "Why this action" }
|
|
265
|
+
],
|
|
266
|
+
"edits": [
|
|
267
|
+
{ "section": "Steps", "before": "verbatim text from the plan (must appear EXACTLY ONCE within the named section)", "after": "replacement" }
|
|
268
|
+
]
|
|
269
|
+
}
|
|
270
|
+
\`\`\``;
|
|
271
|
+
const schemaBlock = useEdits ? editsSchemaBlock : fullSchemaBlock;
|
|
272
|
+
const editsConstraints = `- Output edits, NOT the full plan. The plan is updated server-side by replaying your edits.
|
|
273
|
+
- Each edit's \`section\` is the nearest markdown heading. \`before\` must appear EXACTLY ONCE within that section.
|
|
274
|
+
- Use the SHORTEST \`before\` that is unambiguous within the section.
|
|
275
|
+
- For an addition: \`before\` = a stable anchor; \`after\` = anchor + new content.
|
|
276
|
+
- Edits run sequentially: later edits see earlier edits' results.`;
|
|
277
|
+
const fullModeConstraint = `- The \`updated_plan\` must be the complete plan markdown, not a diff.`;
|
|
278
|
+
const outputConstraint = useEdits ? editsConstraints : fullModeConstraint;
|
|
279
|
+
const body = `## ${phaseLabel} ROUND — Round ${"current round in your session memory"}: New Reviewer Feedback
|
|
280
|
+
|
|
281
|
+
You are continuing the same revision conversation. The plan, your prior rationales, and the prior rounds of reviewer feedback are already in your context — do not re-emit them.
|
|
282
|
+
|
|
283
|
+
The reviewer has produced new feedback for this round. Process it below.
|
|
284
|
+
|
|
285
|
+
**Summary:** ${feedback.summary}
|
|
286
|
+
|
|
287
|
+
${issuesList}
|
|
288
|
+
|
|
289
|
+
## Your Task`;
|
|
290
|
+
if (structuredOutput) {
|
|
291
|
+
return `${body}
|
|
292
|
+
|
|
293
|
+
Output ONLY a single JSON object conforming to the schema below. The first character of your response must be \`{\` and the last must be \`}\`. No prose. No markdown. No code fences. No preamble or explanation. No trailing text.
|
|
294
|
+
|
|
295
|
+
Schema:
|
|
296
|
+
|
|
297
|
+
${schemaBlock}
|
|
298
|
+
|
|
299
|
+
Constraints:
|
|
300
|
+
- Every issue MUST have an entry in \`responses\`. Do not skip any.
|
|
301
|
+
${outputConstraint}
|
|
302
|
+
${surgicalConstraint}
|
|
303
|
+
- Do NOT modify the \`**planpong:**\` status line — it is managed automatically.`;
|
|
304
|
+
}
|
|
305
|
+
return `${body}
|
|
306
|
+
|
|
307
|
+
Respond with a JSON object wrapped in <planpong-revision> tags conforming to:
|
|
308
|
+
|
|
309
|
+
${schemaBlock}
|
|
310
|
+
|
|
311
|
+
IMPORTANT:
|
|
312
|
+
- Every issue MUST have a response. Do not skip any.
|
|
313
|
+
${outputConstraint}
|
|
314
|
+
${surgicalConstraint}
|
|
315
|
+
- Do NOT modify the \`**planpong:**\` status line — it is managed automatically.
|
|
316
|
+
- Wrap your JSON response in <planpong-revision>...</planpong-revision> tags.
|
|
317
|
+
|
|
318
|
+
<planpong-revision>
|
|
319
|
+
YOUR_JSON_HERE
|
|
320
|
+
</planpong-revision>`;
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Build a targeted retry prompt for failed edits in edits-mode revisions.
|
|
324
|
+
* Given the partially-edited plan and the list of edits that failed first
|
|
325
|
+
* pass, asks the planner to re-express each failed edit with corrected
|
|
326
|
+
* `section` and `before` values.
|
|
327
|
+
*
|
|
328
|
+
* The retry prompt is small — it does not re-include the full feedback or
|
|
329
|
+
* key decisions, only the failed edits and the current state of the plan.
|
|
330
|
+
*/
|
|
331
|
+
export function buildEditsRetryPrompt(currentPlan, failures, structuredOutput) {
|
|
332
|
+
const failureBlock = failures
|
|
333
|
+
.map((f, i) => {
|
|
334
|
+
const reasonHelp = f.reason === "no-match"
|
|
335
|
+
? "Your `before` did not match any text in that section. Re-quote a verbatim string from the plan."
|
|
336
|
+
: f.reason === "multi-match"
|
|
337
|
+
? "Your `before` matched multiple times in that section. Add surrounding context until it is unique within the section."
|
|
338
|
+
: f.reason === "section-not-found"
|
|
339
|
+
? "The section heading does not exist in the plan. Pick a heading that does exist."
|
|
340
|
+
: f.reason === "status-line"
|
|
341
|
+
? "Your edit modified the **planpong:** status line, which is reserved. Move the change elsewhere."
|
|
342
|
+
: "Edit failed. Re-express it.";
|
|
343
|
+
const diagnosticLine = f.diagnostic ? `\nDiagnostic: ${f.diagnostic}` : "";
|
|
344
|
+
return `### Failed edit ${i + 1}
|
|
345
|
+
**Section:** ${f.edit.section}
|
|
346
|
+
**Reason:** ${f.reason}${diagnosticLine}
|
|
347
|
+
**Help:** ${reasonHelp}
|
|
348
|
+
**Original \`before\`:**
|
|
349
|
+
\`\`\`
|
|
350
|
+
${f.edit.before}
|
|
351
|
+
\`\`\`
|
|
352
|
+
**Original \`after\`:**
|
|
353
|
+
\`\`\`
|
|
354
|
+
${f.edit.after}
|
|
355
|
+
\`\`\``;
|
|
356
|
+
})
|
|
357
|
+
.join("\n\n");
|
|
358
|
+
const schemaBlock = `\`\`\`
|
|
359
|
+
{
|
|
360
|
+
"edits": [
|
|
361
|
+
{ "section": "Steps", "before": "verbatim", "after": "replacement" }
|
|
362
|
+
]
|
|
363
|
+
}
|
|
364
|
+
\`\`\``;
|
|
365
|
+
const body = `You are correcting failed edits. The previous edit list partially applied; the edits below failed at the apply step.
|
|
366
|
+
|
|
367
|
+
For EACH failed edit, produce a corrected edit with the same intent but a working \`section\` and \`before\`. You may also revise \`after\` if the previous version assumed text that is no longer present.
|
|
368
|
+
|
|
369
|
+
## Current Plan (with previously-successful edits already applied)
|
|
370
|
+
|
|
371
|
+
${currentPlan}
|
|
372
|
+
|
|
373
|
+
## Failed Edits
|
|
374
|
+
|
|
375
|
+
${failureBlock}
|
|
376
|
+
|
|
377
|
+
## Your Task`;
|
|
378
|
+
if (structuredOutput) {
|
|
379
|
+
return `${body}
|
|
380
|
+
|
|
381
|
+
Output ONLY a single JSON object with an \`edits\` array. The first character of your response must be \`{\` and the last must be \`}\`. Do NOT include \`responses\` — those are already finalized.
|
|
382
|
+
|
|
383
|
+
Schema:
|
|
384
|
+
|
|
385
|
+
${schemaBlock}
|
|
386
|
+
|
|
387
|
+
- Output one corrected edit per failure (same count, same order).
|
|
388
|
+
- Each \`before\` must appear EXACTLY ONCE within the named section in the current plan above.
|
|
389
|
+
- Do NOT modify the \`**planpong:**\` status line.`;
|
|
390
|
+
}
|
|
391
|
+
return `${body}
|
|
392
|
+
|
|
393
|
+
Respond with a JSON object wrapped in <planpong-revision> tags. The JSON must match this schema:
|
|
394
|
+
|
|
395
|
+
${schemaBlock}
|
|
396
|
+
|
|
397
|
+
IMPORTANT:
|
|
398
|
+
- Output one corrected edit per failure (same count, same order). Do NOT include \`responses\`.
|
|
399
|
+
- Each \`before\` must appear EXACTLY ONCE within the named section in the current plan above.
|
|
400
|
+
- Do NOT modify the \`**planpong:**\` status line.
|
|
401
|
+
- Wrap your JSON response in <planpong-revision>...</planpong-revision> tags.
|
|
402
|
+
|
|
168
403
|
<planpong-revision>
|
|
169
404
|
YOUR_JSON_HERE
|
|
170
405
|
</planpong-revision>`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"planner.js","sourceRoot":"","sources":["../../../src/prompts/planner.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,sBAAsB,CACpC,YAAoB,EACpB,QAAgB;IAEhB,OAAO;;;;;;;;;;;;;;;;EAgBP,YAAY,EAAE,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,WAAmB,EACnB,QAAwB,EACxB,YAA2B,EAC3B,YAA2B,EAC3B,QAAqB,QAAQ,EAC7B,mBAA4B,KAAK;
|
|
1
|
+
{"version":3,"file":"planner.js","sourceRoot":"","sources":["../../../src/prompts/planner.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
import type { IssueResponse } from "../schemas/revision.js";
|
|
2
2
|
export type ReviewPhase = "direction" | "risk" | "detail";
|
|
3
3
|
export declare function getReviewPhase(round: number): ReviewPhase;
|
|
4
|
+
/**
|
|
5
|
+
* Incremental review prompt for resumed reviewer sessions.
|
|
6
|
+
*
|
|
7
|
+
* The reviewer has already seen the full plan (round 1) and produced its
|
|
8
|
+
* own prior critique. Instead of re-sending the full plan markdown, we
|
|
9
|
+
* send only what's changed since the model last saw it (a markdown diff)
|
|
10
|
+
* plus the new phase instructions.
|
|
11
|
+
*
|
|
12
|
+
* Falls back to full-plan content if `planDiffOrContent` is the entire
|
|
13
|
+
* plan rather than a diff (caller's choice — see operations.ts logic that
|
|
14
|
+
* skips diffing on certain cases).
|
|
15
|
+
*/
|
|
16
|
+
export declare function buildIncrementalReviewPrompt(planDiffOrContent: string, priorDecisions: string | null, phase?: ReviewPhase, structuredOutput?: boolean): string;
|
|
4
17
|
export declare function buildReviewPrompt(planContent: string, priorDecisions: string | null, phase?: ReviewPhase, structuredOutput?: boolean): string;
|
|
5
18
|
export declare function formatPriorDecisions(rounds: Array<{
|
|
6
19
|
round: number;
|
|
@@ -74,6 +74,7 @@ function buildDetailReviewInstructions(priorDecisions) {
|
|
|
74
74
|
|
|
75
75
|
The plan's overall direction has already been validated. Focus on implementation completeness and correctness.
|
|
76
76
|
|
|
77
|
+
- When the plan references files, function names, exports, imports, configs, or APIs, VERIFY them against the codebase using your tools (Read, Grep, Glob, Bash). A plan that references \`src/foo/bar.ts\` should have a corresponding file; a plan that calls \`someLib.thing()\` should match the library's actual API. Flag verifiable mismatches as P1 (would break implementation) — these are the issues only an independent reviewer catches.
|
|
77
78
|
- Only flag issues you have concrete evidence for. Cite the plan section.
|
|
78
79
|
- Assign severity honestly:
|
|
79
80
|
- P1 = blocks implementation or causes failure
|
|
@@ -180,6 +181,70 @@ If the plan is approved with no issues, use:
|
|
|
180
181
|
{ "verdict": "approved", "summary": "...", "issues": [] }
|
|
181
182
|
\`\`\``;
|
|
182
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* Incremental review prompt for resumed reviewer sessions.
|
|
186
|
+
*
|
|
187
|
+
* The reviewer has already seen the full plan (round 1) and produced its
|
|
188
|
+
* own prior critique. Instead of re-sending the full plan markdown, we
|
|
189
|
+
* send only what's changed since the model last saw it (a markdown diff)
|
|
190
|
+
* plus the new phase instructions.
|
|
191
|
+
*
|
|
192
|
+
* Falls back to full-plan content if `planDiffOrContent` is the entire
|
|
193
|
+
* plan rather than a diff (caller's choice — see operations.ts logic that
|
|
194
|
+
* skips diffing on certain cases).
|
|
195
|
+
*/
|
|
196
|
+
export function buildIncrementalReviewPrompt(planDiffOrContent, priorDecisions, phase = "detail", structuredOutput = false) {
|
|
197
|
+
const instructions = phase === "direction"
|
|
198
|
+
? buildDirectionReviewInstructions()
|
|
199
|
+
: phase === "risk"
|
|
200
|
+
? buildRiskReviewInstructions(priorDecisions)
|
|
201
|
+
: buildDetailReviewInstructions(priorDecisions);
|
|
202
|
+
const jsonSchema = phase === "direction"
|
|
203
|
+
? buildDirectionJsonSchema()
|
|
204
|
+
: phase === "risk"
|
|
205
|
+
? buildRiskJsonSchema()
|
|
206
|
+
: buildDetailJsonSchema();
|
|
207
|
+
const isDiff = planDiffOrContent.startsWith("```diff");
|
|
208
|
+
const planSection = isDiff
|
|
209
|
+
? `## Plan Changes Since Last Round
|
|
210
|
+
|
|
211
|
+
The plan has been revised in response to your prior feedback. Below is what changed (the rest of the plan is unchanged from your context).
|
|
212
|
+
|
|
213
|
+
${planDiffOrContent}`
|
|
214
|
+
: `## Plan to Review
|
|
215
|
+
|
|
216
|
+
${planDiffOrContent}`;
|
|
217
|
+
if (structuredOutput) {
|
|
218
|
+
return `${instructions}
|
|
219
|
+
${planSection}
|
|
220
|
+
|
|
221
|
+
## Your Task
|
|
222
|
+
|
|
223
|
+
You are continuing the same review conversation. Your prior round's feedback and the plan you reviewed are in your context — use them.
|
|
224
|
+
|
|
225
|
+
Output ONLY a single JSON object conforming to the schema below. The first character of your response must be \`{\` and the last must be \`}\`. No prose. No markdown. No code fences. No preamble or explanation. No trailing text.
|
|
226
|
+
|
|
227
|
+
Schema:
|
|
228
|
+
|
|
229
|
+
${jsonSchema}`;
|
|
230
|
+
}
|
|
231
|
+
return `${instructions}
|
|
232
|
+
${planSection}
|
|
233
|
+
|
|
234
|
+
## Your Task
|
|
235
|
+
|
|
236
|
+
You are continuing the same review conversation. Your prior round's feedback and the plan you reviewed are in your context — use them.
|
|
237
|
+
|
|
238
|
+
Respond with a JSON object wrapped in <planpong-feedback> tags conforming to:
|
|
239
|
+
|
|
240
|
+
${jsonSchema}
|
|
241
|
+
|
|
242
|
+
IMPORTANT: Wrap your JSON response in <planpong-feedback>...</planpong-feedback> tags.
|
|
243
|
+
|
|
244
|
+
<planpong-feedback>
|
|
245
|
+
YOUR_JSON_HERE
|
|
246
|
+
</planpong-feedback>`;
|
|
247
|
+
}
|
|
183
248
|
export function buildReviewPrompt(planContent, priorDecisions, phase = "detail", structuredOutput = false) {
|
|
184
249
|
const instructions = phase === "direction"
|
|
185
250
|
? buildDirectionReviewInstructions()
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reviewer.js","sourceRoot":"","sources":["../../../src/prompts/reviewer.ts"],"names":[],"mappings":"AAIA,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,WAAW,CAAC;IACnC,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC;IAC/B,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,gCAAgC;IACvC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;oGAyB2F,CAAC;AACrG,CAAC;AAED,SAAS,2BAA2B,CAAC,cAA6B;IAChE,MAAM,UAAU,GAAG,cAAc;QAC/B,CAAC,CAAC,iCAAiC,cAAc,+IAA+I;QAChM,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2BP,UAAU,EAAE,CAAC;AACf,CAAC;AAED,SAAS,6BAA6B,CAAC,cAA6B;IAClE,MAAM,UAAU,GAAG,cAAc;QAC/B,CAAC,CAAC,iCAAiC,cAAc,yLAAyL;QAC1O,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO
|
|
1
|
+
{"version":3,"file":"reviewer.js","sourceRoot":"","sources":["../../../src/prompts/reviewer.ts"],"names":[],"mappings":"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"}
|
|
@@ -92,12 +92,25 @@ export class ClaudeProvider {
|
|
|
92
92
|
if (options.model) {
|
|
93
93
|
args.push("--model", options.model);
|
|
94
94
|
}
|
|
95
|
+
// Persistent conversation. `--session-id` creates a new session with the
|
|
96
|
+
// given UUID; `--resume` continues an existing one. Caller must use one
|
|
97
|
+
// or the other, never both. Lets us drop heavy "current plan + prior
|
|
98
|
+
// decisions" stuffing on round 2+ since the model retains context.
|
|
99
|
+
if (options.newSessionId && options.resumeSessionId) {
|
|
100
|
+
throw new Error("claude provider: newSessionId and resumeSessionId are mutually exclusive");
|
|
101
|
+
}
|
|
102
|
+
if (options.newSessionId) {
|
|
103
|
+
args.push("--session-id", options.newSessionId);
|
|
104
|
+
}
|
|
105
|
+
else if (options.resumeSessionId) {
|
|
106
|
+
args.push("--resume", options.resumeSessionId);
|
|
107
|
+
}
|
|
95
108
|
const start = Date.now();
|
|
96
109
|
try {
|
|
97
110
|
const result = await execa("claude", args, {
|
|
98
111
|
cwd: options.cwd,
|
|
99
112
|
preferLocal: true,
|
|
100
|
-
timeout: options.timeout ??
|
|
113
|
+
timeout: options.timeout ?? 600_000,
|
|
101
114
|
reject: false,
|
|
102
115
|
env: cleanEnv(),
|
|
103
116
|
extendEnv: false,
|
|
@@ -107,6 +120,9 @@ export class ClaudeProvider {
|
|
|
107
120
|
const exitCode = result.exitCode ?? 1;
|
|
108
121
|
// claude -p can exit non-zero with valid stdout. Treat presence of
|
|
109
122
|
// stdout as success even on non-zero exit.
|
|
123
|
+
// Canonical session ID for the response: echoes the input UUID
|
|
124
|
+
// (claude accepts external UUIDs as session IDs, so input == output).
|
|
125
|
+
const sessionId = options.newSessionId ?? options.resumeSessionId;
|
|
110
126
|
if (result.stdout && result.stdout.trim().length > 0) {
|
|
111
127
|
if (options.jsonSchema) {
|
|
112
128
|
// Parse claude's envelope and extract structured_output.
|
|
@@ -123,9 +139,9 @@ export class ClaudeProvider {
|
|
|
123
139
|
duration,
|
|
124
140
|
};
|
|
125
141
|
}
|
|
126
|
-
return { ok: true, output: extracted, duration };
|
|
142
|
+
return { ok: true, output: extracted, duration, sessionId };
|
|
127
143
|
}
|
|
128
|
-
return { ok: true, output: result.stdout, duration };
|
|
144
|
+
return { ok: true, output: result.stdout, duration, sessionId };
|
|
129
145
|
}
|
|
130
146
|
// No usable output — classify the failure
|
|
131
147
|
process.stderr.write(`[claude-provider] exit=${exitCode} stderr=${result.stderr?.slice(0, 500)}\n`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../../src/providers/claude.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../../src/providers/claude.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,11 +14,37 @@ const EFFORT_LEVELS = ["low", "medium", "high", "xhigh"];
|
|
|
14
14
|
* names like "output-schema:" in its info output, so substring matches on
|
|
15
15
|
* the flag name alone produce false positives.
|
|
16
16
|
*/
|
|
17
|
+
function extractCodexThreadId(stdout) {
|
|
18
|
+
if (!stdout)
|
|
19
|
+
return undefined;
|
|
20
|
+
// The first non-empty line of `codex exec --json` stdout is a
|
|
21
|
+
// `thread.started` or `thread.resumed` event with `thread_id`. Scan
|
|
22
|
+
// the first ~10 lines defensively in case the model emits anything
|
|
23
|
+
// else first.
|
|
24
|
+
const lines = stdout.split("\n").slice(0, 10);
|
|
25
|
+
for (const line of lines) {
|
|
26
|
+
const trimmed = line.trim();
|
|
27
|
+
if (!trimmed.startsWith("{"))
|
|
28
|
+
continue;
|
|
29
|
+
try {
|
|
30
|
+
const evt = JSON.parse(trimmed);
|
|
31
|
+
if ((evt.type === "thread.started" || evt.type === "thread.resumed") &&
|
|
32
|
+
typeof evt.thread_id === "string") {
|
|
33
|
+
return evt.thread_id;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
17
42
|
function classifyError(stderr, exitCode) {
|
|
18
43
|
const lower = stderr.toLowerCase();
|
|
19
44
|
const capabilityPatterns = [
|
|
20
45
|
/\bunknown (?:flag|option|argument)\b/,
|
|
21
46
|
/\bunrecognized (?:flag|option|argument)\b/,
|
|
47
|
+
/\bunexpected (?:flag|option|argument)\b/,
|
|
22
48
|
/\binvalid_json_schema\b/,
|
|
23
49
|
/\binvalid schema\b/,
|
|
24
50
|
/\bschema is not supported\b/,
|
|
@@ -36,7 +62,18 @@ export class CodexProvider {
|
|
|
36
62
|
name = "codex";
|
|
37
63
|
capabilityCache = null;
|
|
38
64
|
async invoke(prompt, options) {
|
|
39
|
-
|
|
65
|
+
// codex doesn't accept an externally-generated session UUID. The first
|
|
66
|
+
// call always creates a fresh thread; we capture `thread_id` from the
|
|
67
|
+
// `--json` event stream on stdout and the caller persists it. Resume
|
|
68
|
+
// subsequent calls via `codex exec resume <id>` (subcommand form).
|
|
69
|
+
if (options.newSessionId) {
|
|
70
|
+
// Silent ignore — codex generates its own ID. The caller will get
|
|
71
|
+
// the actual ID back via ProviderResponse.sessionId.
|
|
72
|
+
}
|
|
73
|
+
const isResume = options.resumeSessionId != null && options.resumeSessionId.length > 0;
|
|
74
|
+
const args = isResume
|
|
75
|
+
? ["exec", "resume", options.resumeSessionId]
|
|
76
|
+
: ["exec"];
|
|
40
77
|
if (options.model) {
|
|
41
78
|
args.push("-m", options.model);
|
|
42
79
|
}
|
|
@@ -46,6 +83,10 @@ export class CodexProvider {
|
|
|
46
83
|
// Write clean output to a temp file to avoid parsing header/footer
|
|
47
84
|
const outFile = join(tmpdir(), `planpong-codex-${randomBytes(6).toString("hex")}.txt`);
|
|
48
85
|
args.push("-o", outFile);
|
|
86
|
+
// Always enable --json so we can capture the thread_id event from
|
|
87
|
+
// stdout. The `-o` file still receives the agent's clean text output;
|
|
88
|
+
// `--json` only changes stdout/stderr streaming.
|
|
89
|
+
args.push("--json");
|
|
49
90
|
// Optional structured output schema
|
|
50
91
|
let schemaFile = null;
|
|
51
92
|
if (options.jsonSchema) {
|
|
@@ -66,7 +107,7 @@ export class CodexProvider {
|
|
|
66
107
|
const result = await execa("codex", args, {
|
|
67
108
|
cwd: options.cwd,
|
|
68
109
|
preferLocal: true,
|
|
69
|
-
timeout: options.timeout ??
|
|
110
|
+
timeout: options.timeout ?? 600_000,
|
|
70
111
|
reject: false,
|
|
71
112
|
input: prompt,
|
|
72
113
|
});
|
|
@@ -96,7 +137,13 @@ export class CodexProvider {
|
|
|
96
137
|
}
|
|
97
138
|
}
|
|
98
139
|
if (content && content.trim().length > 0) {
|
|
99
|
-
|
|
140
|
+
// Capture thread_id from --json stdout. The first event is
|
|
141
|
+
// `thread.started` (fresh) or `thread.resumed` (resume). Both
|
|
142
|
+
// carry `thread_id`. We treat parse failures as "no session
|
|
143
|
+
// tracking" rather than as errors — sessions are an
|
|
144
|
+
// optimization, not a correctness requirement.
|
|
145
|
+
const sessionId = extractCodexThreadId(result.stdout);
|
|
146
|
+
return { ok: true, output: content, duration, sessionId };
|
|
100
147
|
}
|
|
101
148
|
return {
|
|
102
149
|
ok: false,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex.js","sourceRoot":"","sources":["../../../src/providers/codex.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAQ9B,MAAM,MAAM,GAAG,CAAC,eAAe,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;AAC5D,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AAEzD;;;;;;;;GAQG;AACH,SAAS,aAAa,CAAC,MAAc,EAAE,QAAgB;IACrD,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IACnC,MAAM,kBAAkB,GAAG;QACzB,sCAAsC;QACtC,2CAA2C;QAC3C,yBAAyB;QACzB,oBAAoB;QACpB,6BAA6B;QAC7B,+CAA+C;KAChD,CAAC;IACF,MAAM,YAAY,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CACvD,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CACpB,CAAC;IACF,OAAO;QACL,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO;QAC3C,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,0BAA0B,QAAQ,EAAE;QACrE,QAAQ;QACR,MAAM;KACP,CAAC;AACJ,CAAC;AAED,MAAM,OAAO,aAAa;IACxB,IAAI,GAAG,OAAO,CAAC;IAEP,eAAe,GAAmB,IAAI,CAAC;IAE/C,KAAK,CAAC,MAAM,CACV,MAAc,EACd,OAAsB;QAEtB,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"codex.js","sourceRoot":"","sources":["../../../src/providers/codex.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,6 +9,18 @@ export interface InvokeOptions {
|
|
|
9
9
|
* `--output-schema` for codex).
|
|
10
10
|
*/
|
|
11
11
|
jsonSchema?: Record<string, unknown>;
|
|
12
|
+
/**
|
|
13
|
+
* Initialize a NEW persistent conversation with this UUID. Mutually
|
|
14
|
+
* exclusive with `resumeSessionId`. After the first call succeeds, the
|
|
15
|
+
* caller must use `resumeSessionId` on subsequent calls.
|
|
16
|
+
*/
|
|
17
|
+
newSessionId?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Resume an EXISTING persistent conversation. The model retains context
|
|
20
|
+
* from prior turns. Only valid for sessions previously created with
|
|
21
|
+
* `newSessionId`.
|
|
22
|
+
*/
|
|
23
|
+
resumeSessionId?: string;
|
|
12
24
|
}
|
|
13
25
|
/**
|
|
14
26
|
* Provider invocation error categories. Used by the operations-layer state
|
|
@@ -32,11 +44,19 @@ export interface ProviderError {
|
|
|
32
44
|
* single-shot — they perform one invocation and return either the output
|
|
33
45
|
* or a typed error. They do NOT retry or downgrade internally; that is
|
|
34
46
|
* the operations-layer state machine's job.
|
|
47
|
+
*
|
|
48
|
+
* `sessionId` (success only): the canonical conversation ID the provider
|
|
49
|
+
* used. For providers that accept an externally-generated UUID (claude),
|
|
50
|
+
* this echoes the input; for providers that generate their own IDs
|
|
51
|
+
* (codex), this is parsed from the provider's output. Caller persists
|
|
52
|
+
* this and passes it as `resumeSessionId` on subsequent calls to keep
|
|
53
|
+
* the same conversation thread.
|
|
35
54
|
*/
|
|
36
55
|
export type ProviderResponse = {
|
|
37
56
|
ok: true;
|
|
38
57
|
output: string;
|
|
39
58
|
duration: number;
|
|
59
|
+
sessionId?: string;
|
|
40
60
|
} | {
|
|
41
61
|
ok: false;
|
|
42
62
|
error: ProviderError;
|