planpong 0.2.1 → 0.4.2

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.
Files changed (41) hide show
  1. package/dist/src/core/convergence.d.ts +46 -2
  2. package/dist/src/core/convergence.js +278 -6
  3. package/dist/src/core/convergence.js.map +1 -1
  4. package/dist/src/core/loop.d.ts +3 -3
  5. package/dist/src/core/loop.js +20 -8
  6. package/dist/src/core/loop.js.map +1 -1
  7. package/dist/src/core/operations.d.ts +14 -4
  8. package/dist/src/core/operations.js +140 -48
  9. package/dist/src/core/operations.js.map +1 -1
  10. package/dist/src/core/session.d.ts +3 -3
  11. package/dist/src/core/session.js.map +1 -1
  12. package/dist/src/mcp/server.js +25 -1
  13. package/dist/src/mcp/server.js.map +1 -1
  14. package/dist/src/mcp/tools/get-feedback.js +32 -6
  15. package/dist/src/mcp/tools/get-feedback.js.map +1 -1
  16. package/dist/src/mcp/tools/get-report.d.ts +2 -0
  17. package/dist/src/mcp/tools/get-report.js +152 -0
  18. package/dist/src/mcp/tools/get-report.js.map +1 -0
  19. package/dist/src/prompts/planner.d.ts +1 -1
  20. package/dist/src/prompts/planner.js +39 -19
  21. package/dist/src/prompts/planner.js.map +1 -1
  22. package/dist/src/prompts/reviewer.d.ts +1 -1
  23. package/dist/src/prompts/reviewer.js +120 -15
  24. package/dist/src/prompts/reviewer.js.map +1 -1
  25. package/dist/src/providers/claude.d.ts +3 -0
  26. package/dist/src/providers/claude.js +134 -12
  27. package/dist/src/providers/claude.js.map +1 -1
  28. package/dist/src/providers/codex.d.ts +3 -0
  29. package/dist/src/providers/codex.js +101 -12
  30. package/dist/src/providers/codex.js.map +1 -1
  31. package/dist/src/providers/types.d.ts +49 -3
  32. package/dist/src/schemas/feedback.d.ts +236 -5
  33. package/dist/src/schemas/feedback.js +52 -1
  34. package/dist/src/schemas/feedback.js.map +1 -1
  35. package/dist/src/schemas/json-schema.d.ts +9 -0
  36. package/dist/src/schemas/json-schema.js +153 -0
  37. package/dist/src/schemas/json-schema.js.map +1 -0
  38. package/dist/src/schemas/session.d.ts +3 -3
  39. package/dist/src/schemas/session.js +1 -1
  40. package/dist/src/schemas/session.js.map +1 -1
  41. package/package.json +4 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-report.js","sourceRoot":"","sources":["../../../../src/mcp/tools/get-report.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
1
  import type { ReviewFeedback } from "../schemas/feedback.js";
2
2
  import type { ReviewPhase } from "./reviewer.js";
3
3
  export declare function buildInitialPlanPrompt(requirements: string, plansDir: string): string;
4
- export declare function buildRevisionPrompt(currentPlan: string, feedback: ReviewFeedback, keyDecisions: string | null, priorContext: string | null, phase?: ReviewPhase): string;
4
+ export declare function buildRevisionPrompt(currentPlan: string, feedback: ReviewFeedback, keyDecisions: string | null, priorContext: string | null, phase?: ReviewPhase, structuredOutput?: boolean): string;
@@ -17,7 +17,7 @@ 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") {
20
+ export function buildRevisionPrompt(currentPlan, feedback, keyDecisions, priorContext, phase = "detail", structuredOutput = false) {
21
21
  const contextBlock = priorContext
22
22
  ? `\n## Prior Research & Constraints\n\n${priorContext}\n`
23
23
  : "";
@@ -104,23 +104,7 @@ For each response, cite specific evidence: reference the plan section, the resea
104
104
  - Do not reorganize or rephrase parts of the plan unrelated to risk feedback.`
105
105
  : `- 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
106
  - Preserve the plan's existing structure, headings, and formatting. Your job is surgical revision, not rewriting.`;
107
- return `${roleInstructions}
108
- ${contextBlock}${decisionsBlock}
109
- ## Current Plan
110
-
111
- ${currentPlan}
112
-
113
- ## Reviewer Feedback
114
-
115
- **Summary:** ${feedback.summary}
116
-
117
- ${issuesList}
118
-
119
- ## Your Task
120
-
121
- Respond with a JSON object wrapped in <planpong-revision> tags. The JSON must match this schema:
122
-
123
- \`\`\`
107
+ const schemaBlock = `\`\`\`
124
108
  {
125
109
  "responses": [
126
110
  {
@@ -136,7 +120,43 @@ Respond with a JSON object wrapped in <planpong-revision> tags. The JSON must ma
136
120
  ],
137
121
  "updated_plan": "The full updated plan in markdown (incorporate accepted changes)"
138
122
  }
139
- \`\`\`
123
+ \`\`\``;
124
+ const commonBody = `${roleInstructions}
125
+ ${contextBlock}${decisionsBlock}
126
+ ## Current Plan
127
+
128
+ ${currentPlan}
129
+
130
+ ## Reviewer Feedback
131
+
132
+ **Summary:** ${feedback.summary}
133
+
134
+ ${issuesList}
135
+
136
+ ## Your Task`;
137
+ if (structuredOutput) {
138
+ // Structured-output mode. Some providers constrain output at the token
139
+ // level; others only validate post-hoc. Emphatic JSON-only instructions
140
+ // help advisory providers comply; constrained providers ignore them.
141
+ return `${commonBody}
142
+
143
+ 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.
144
+
145
+ Schema:
146
+
147
+ ${schemaBlock}
148
+
149
+ Constraints embedded in your JSON response:
150
+ - Every issue MUST have an entry in \`responses\`. Do not skip any.
151
+ - \`updated_plan\` must be the complete plan markdown, not a diff.
152
+ ${surgicalConstraint}
153
+ - Do NOT modify the \`**planpong:**\` status line — it is managed automatically.`;
154
+ }
155
+ return `${commonBody}
156
+
157
+ Respond with a JSON object wrapped in <planpong-revision> tags. The JSON must match this schema:
158
+
159
+ ${schemaBlock}
140
160
 
141
161
  IMPORTANT:
142
162
  - Every issue MUST have a response. Do not skip any.
@@ -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;IAE7B,MAAM,YAAY,GAAG,YAAY;QAC/B,CAAC,CAAC,wCAAwC,YAAY,IAAI;QAC1D,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,cAAc,GAAG,YAAY;QACjC,CAAC,CAAC,mCAAmC,YAAY,IAAI;QACrD,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM;SAC/B,GAAG,CACF,CAAC,KAAK,EAAE,EAAE,CACR,OAAO,KAAK,CAAC,EAAE,KAAK,KAAK,CAAC,QAAQ,MAAM,KAAK,CAAC,KAAK,kBAAkB,KAAK,CAAC,OAAO,sBAAsB,KAAK,CAAC,WAAW,qBAAqB,KAAK,CAAC,UAAU,EAAE,CACnK;SACA,IAAI,CAAC,MAAM,CAAC,CAAC;IAEhB,MAAM,qBAAqB,GAAG;;;;;;;;;;;;;;;;;;oLAkBoJ,CAAC;IAEnL,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;;4KAmBiJ,CAAC;IAE3K,MAAM,kBAAkB,GAAG;;;;;;;;;;;;;;;;;;;;;;;mTAuBsR,CAAC;IAElT,MAAM,gBAAgB,GACpB,KAAK,KAAK,WAAW;QACnB,CAAC,CAAC,qBAAqB;QACvB,CAAC,CAAC,KAAK,KAAK,MAAM;YAChB,CAAC,CAAC,gBAAgB;YAClB,CAAC,CAAC,kBAAkB,CAAC;IAE3B,MAAM,kBAAkB,GACtB,KAAK,KAAK,WAAW;QACnB,CAAC,CAAC;0DACkD;QACpD,CAAC,CAAC,KAAK,KAAK,MAAM;YAChB,CAAC,CAAC;;8EAEoE;YACtE,CAAC,CAAC;kHACwG,CAAC;IAEjH,OAAO,GAAG,gBAAgB;EAC1B,YAAY,GAAG,cAAc;;;EAG7B,WAAW;;;;eAIE,QAAQ,CAAC,OAAO;;EAE7B,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2BV,kBAAkB;;;;;;qBAMC,CAAC;AACtB,CAAC"}
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;IAEjC,MAAM,YAAY,GAAG,YAAY;QAC/B,CAAC,CAAC,wCAAwC,YAAY,IAAI;QAC1D,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,cAAc,GAAG,YAAY;QACjC,CAAC,CAAC,mCAAmC,YAAY,IAAI;QACrD,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM;SAC/B,GAAG,CACF,CAAC,KAAK,EAAE,EAAE,CACR,OAAO,KAAK,CAAC,EAAE,KAAK,KAAK,CAAC,QAAQ,MAAM,KAAK,CAAC,KAAK,kBAAkB,KAAK,CAAC,OAAO,sBAAsB,KAAK,CAAC,WAAW,qBAAqB,KAAK,CAAC,UAAU,EAAE,CACnK;SACA,IAAI,CAAC,MAAM,CAAC,CAAC;IAEhB,MAAM,qBAAqB,GAAG;;;;;;;;;;;;;;;;;;oLAkBoJ,CAAC;IAEnL,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;;4KAmBiJ,CAAC;IAE3K,MAAM,kBAAkB,GAAG;;;;;;;;;;;;;;;;;;;;;;;mTAuBsR,CAAC;IAElT,MAAM,gBAAgB,GACpB,KAAK,KAAK,WAAW;QACnB,CAAC,CAAC,qBAAqB;QACvB,CAAC,CAAC,KAAK,KAAK,MAAM;YAChB,CAAC,CAAC,gBAAgB;YAClB,CAAC,CAAC,kBAAkB,CAAC;IAE3B,MAAM,kBAAkB,GACtB,KAAK,KAAK,WAAW;QACnB,CAAC,CAAC;0DACkD;QACpD,CAAC,CAAC,KAAK,KAAK,MAAM;YAChB,CAAC,CAAC;;8EAEoE;YACtE,CAAC,CAAC;kHACwG,CAAC;IAEjH,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;OAgBf,CAAC;IAEN,MAAM,UAAU,GAAG,GAAG,gBAAgB;EACtC,YAAY,GAAG,cAAc;;;EAG7B,WAAW;;;;eAIE,QAAQ,CAAC,OAAO;;EAE7B,UAAU;;aAEC,CAAC;IAEZ,IAAI,gBAAgB,EAAE,CAAC;QACrB,uEAAuE;QACvE,wEAAwE;QACxE,qEAAqE;QACrE,OAAO,GAAG,UAAU;;;;;;EAMtB,WAAW;;;;;EAKX,kBAAkB;iFAC6D,CAAC;IAChF,CAAC;IAED,OAAO,GAAG,UAAU;;;;EAIpB,WAAW;;;;;EAKX,kBAAkB;;;;;;qBAMC,CAAC;AACtB,CAAC"}
@@ -1,7 +1,7 @@
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
- export declare function buildReviewPrompt(planContent: string, priorDecisions: string | null, phase?: ReviewPhase): string;
4
+ export declare function buildReviewPrompt(planContent: string, priorDecisions: string | null, phase?: ReviewPhase, structuredOutput?: boolean): string;
5
5
  export declare function formatPriorDecisions(rounds: Array<{
6
6
  round: number;
7
7
  responses: IssueResponse[];
@@ -28,7 +28,10 @@ Assign severity based on directional impact:
28
28
  - P2 = questionable strategic choice that could lead to significant rework
29
29
  - P3 = alternative approach worth considering
30
30
 
31
- - If the direction is sound, approve the plan so detailed review can begin.`;
31
+ Verdict rules:
32
+ - Use "needs_revision" when there are issues to address (this is the normal case).
33
+ - Use "blocked" ONLY when the plan is fundamentally non-viable due to hard external constraints — e.g., depends on a deprecated/unavailable API, violates an organizational policy, or requires resources that don't exist. Do NOT use "blocked" for fixable design issues.
34
+ - You CANNOT approve in this round. Direction review always produces "needs_revision" or "blocked".`;
32
35
  }
33
36
  function buildRiskReviewInstructions(priorDecisions) {
34
37
  const priorBlock = priorDecisions
@@ -50,12 +53,17 @@ Do NOT focus on:
50
53
  - Minor implementation details or code-level concerns (those come in later rounds)
51
54
  - Stylistic or formatting issues
52
55
 
56
+ Produce a structured risk register in "risks" — this is the full set of risks you identified. Then promote the subset that needs plan changes to "issues". Not every risk needs to become an issue — low-likelihood/low-impact risks can stay in the register as informational.
57
+
53
58
  Assign severity based on risk impact:
54
59
  - P1 = unmitigated risk that could cause data loss, outage, or require a full rollback
55
60
  - P2 = risk that could cause significant delay or rework if it materializes
56
61
  - P3 = risk worth acknowledging but unlikely or easily recoverable
57
62
 
58
- - If the plan adequately addresses risks and has reasonable mitigations, approve it.
63
+ Verdict rules:
64
+ - Use "needs_revision" when there are issues to address (this is the normal case).
65
+ - Use "blocked" ONLY when unmitigable risks make the plan non-viable — e.g., a hard dependency is unavailable, a critical external system is unreliable with no workaround. Do NOT use "blocked" for risks that can be mitigated with plan changes.
66
+ - You CANNOT approve in this round. Risk review always produces "needs_revision" or "blocked".
59
67
  ${priorBlock}`;
60
68
  }
61
69
  function buildDetailReviewInstructions(priorDecisions) {
@@ -78,22 +86,79 @@ The plan's overall direction has already been validated. Focus on implementation
78
86
  - If you approve with "approved_with_notes", do NOT include any P1 or P2 issues.
79
87
  ${priorBlock}`;
80
88
  }
81
- export function buildReviewPrompt(planContent, priorDecisions, phase = "detail") {
82
- const instructions = phase === "direction"
83
- ? buildDirectionReviewInstructions()
84
- : phase === "risk"
85
- ? buildRiskReviewInstructions(priorDecisions)
86
- : buildDetailReviewInstructions(priorDecisions);
87
- return `${instructions}
88
- ## Plan to Review
89
-
90
- ${planContent}
89
+ function buildDirectionJsonSchema() {
90
+ return `\`\`\`
91
+ {
92
+ "verdict": "needs_revision" | "blocked",
93
+ "summary": "Overall assessment of the plan's direction",
94
+ "confidence": "high" | "medium" | "low",
95
+ "approach_assessment": "Why the chosen approach works or doesn't — be specific",
96
+ "alternatives": [
97
+ {
98
+ "approach": "Name/description of an alternative approach",
99
+ "tradeoff": "Why it was or wasn't chosen, pros/cons"
100
+ }
101
+ ],
102
+ "assumptions": [
103
+ "Unstated assumption the plan relies on"
104
+ ],
105
+ "issues": [
106
+ {
107
+ "id": "F1",
108
+ "severity": "P1" | "P2" | "P3",
109
+ "section": "Which part of the plan this relates to",
110
+ "title": "One-line summary",
111
+ "description": "Detailed explanation",
112
+ "suggestion": "Recommended fix"
113
+ }
114
+ ]
115
+ }
116
+ \`\`\`
91
117
 
92
- ## Your Task
118
+ If the direction is sound with no issues:
119
+ \`\`\`
120
+ { "verdict": "needs_revision", "summary": "...", "confidence": "high", "approach_assessment": "...", "alternatives": [], "assumptions": [], "issues": [] }
121
+ \`\`\``;
122
+ }
123
+ function buildRiskJsonSchema() {
124
+ return `\`\`\`
125
+ {
126
+ "verdict": "needs_revision" | "blocked",
127
+ "summary": "Overall risk assessment",
128
+ "risk_level": "high" | "medium" | "low",
129
+ "risks": [
130
+ {
131
+ "id": "R1",
132
+ "category": "dependency" | "integration" | "operational" | "assumption" | "external",
133
+ "likelihood": "high" | "medium" | "low",
134
+ "impact": "high" | "medium" | "low",
135
+ "title": "Short risk title",
136
+ "description": "Detailed risk description",
137
+ "mitigation": "Suggested mitigation"
138
+ }
139
+ ],
140
+ "issues": [
141
+ {
142
+ "id": "F1",
143
+ "severity": "P1" | "P2" | "P3",
144
+ "section": "Which part of the plan this relates to",
145
+ "title": "One-line summary",
146
+ "description": "Detailed explanation",
147
+ "suggestion": "Recommended fix"
148
+ }
149
+ ]
150
+ }
151
+ \`\`\`
93
152
 
94
- Respond with a JSON object wrapped in <planpong-feedback> tags. The JSON must match this schema:
153
+ The "risks" array is your full risk register. The "issues" array is the subset of risks that need plan changes. Not every risk needs to be an issue.
95
154
 
155
+ If risks are present but adequately mitigated:
96
156
  \`\`\`
157
+ { "verdict": "needs_revision", "summary": "...", "risk_level": "low", "risks": [...], "issues": [] }
158
+ \`\`\``;
159
+ }
160
+ function buildDetailJsonSchema() {
161
+ return `\`\`\`
97
162
  {
98
163
  "verdict": "needs_revision" | "approved" | "approved_with_notes",
99
164
  "summary": "Overall assessment of the plan",
@@ -113,7 +178,47 @@ Respond with a JSON object wrapped in <planpong-feedback> tags. The JSON must ma
113
178
  If the plan is approved with no issues, use:
114
179
  \`\`\`
115
180
  { "verdict": "approved", "summary": "...", "issues": [] }
116
- \`\`\`
181
+ \`\`\``;
182
+ }
183
+ export function buildReviewPrompt(planContent, priorDecisions, phase = "detail", structuredOutput = false) {
184
+ const instructions = phase === "direction"
185
+ ? buildDirectionReviewInstructions()
186
+ : phase === "risk"
187
+ ? buildRiskReviewInstructions(priorDecisions)
188
+ : buildDetailReviewInstructions(priorDecisions);
189
+ const jsonSchema = phase === "direction"
190
+ ? buildDirectionJsonSchema()
191
+ : phase === "risk"
192
+ ? buildRiskJsonSchema()
193
+ : buildDetailJsonSchema();
194
+ if (structuredOutput) {
195
+ // Structured-output mode. Some providers (OpenAI/Codex) constrain output
196
+ // at the token level; others (Claude) only validate post-hoc. Emphatic
197
+ // JSON-only instructions help the advisory case comply; the constrained
198
+ // case ignores them harmlessly.
199
+ return `${instructions}
200
+ ## Plan to Review
201
+
202
+ ${planContent}
203
+
204
+ ## Your Task
205
+
206
+ 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.
207
+
208
+ Schema:
209
+
210
+ ${jsonSchema}`;
211
+ }
212
+ return `${instructions}
213
+ ## Plan to Review
214
+
215
+ ${planContent}
216
+
217
+ ## Your Task
218
+
219
+ Respond with a JSON object wrapped in <planpong-feedback> tags. The JSON must match this schema:
220
+
221
+ ${jsonSchema}
117
222
 
118
223
  IMPORTANT: Wrap your JSON response in <planpong-feedback>...</planpong-feedback> tags.
119
224
 
@@ -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;;;;;;;;;;;;;;;;;;;;;;4EAsBmE,CAAC;AAC7E,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;;;;;;;;;;;;;;;;;;;;;;EAsBP,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;;;;;;;;;;;;;;EAcP,UAAU,EAAE,CAAC;AACf,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,WAAmB,EACnB,cAA6B,EAC7B,QAAqB,QAAQ;IAE7B,MAAM,YAAY,GAChB,KAAK,KAAK,WAAW;QACnB,CAAC,CAAC,gCAAgC,EAAE;QACpC,CAAC,CAAC,KAAK,KAAK,MAAM;YAChB,CAAC,CAAC,2BAA2B,CAAC,cAAc,CAAC;YAC7C,CAAC,CAAC,6BAA6B,CAAC,cAAc,CAAC,CAAC;IAEtD,OAAO,GAAG,YAAY;;;EAGtB,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAgCQ,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,MAIE;IAEF,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;YACvC,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACnE,MAAM,QAAQ,GAAG,KAAK,EAAE,QAAQ,IAAI,IAAI,CAAC;YACzC,MAAM,KAAK,GAAG,KAAK,EAAE,KAAK,IAAI,QAAQ,CAAC,QAAQ,CAAC;YAChD,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YAC7C,MAAM,SAAS,GACb,QAAQ,CAAC,SAAS,CAAC,MAAM,GAAG,EAAE;gBAC5B,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK;gBACzC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC;YACzB,KAAK,CAAC,IAAI,CACR,MAAM,KAAK,CAAC,KAAK,IAAI,QAAQ,CAAC,QAAQ,KAAK,QAAQ,MAAM,KAAK,MAAM,MAAM,KAAK,SAAS,GAAG,CAC5F,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
1
+ {"version":3,"file":"reviewer.js","sourceRoot":"","sources":["../../../src/prompts/reviewer.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,11 @@
1
1
  import type { Provider, InvokeOptions, ProviderResponse } from "./types.js";
2
2
  export declare class ClaudeProvider implements Provider {
3
3
  name: string;
4
+ private capabilityCache;
4
5
  invoke(prompt: string, options: InvokeOptions): Promise<ProviderResponse>;
5
6
  isAvailable(): Promise<boolean>;
7
+ checkStructuredOutputSupport(): Promise<boolean>;
8
+ markNonCapable(): void;
6
9
  getModels(): string[];
7
10
  getEffortLevels(): string[];
8
11
  }
@@ -13,11 +13,82 @@ function cleanEnv() {
13
13
  }
14
14
  return env;
15
15
  }
16
+ /**
17
+ * Parse claude's `--output-format json` envelope and extract the
18
+ * `structured_output` field as a JSON string ready for downstream parsing.
19
+ * Returns null if the envelope is malformed or the field is missing.
20
+ *
21
+ * Envelope shape (subset):
22
+ * {
23
+ * "type": "result",
24
+ * "is_error": false,
25
+ * "result": "",
26
+ * "structured_output": { ...model's constrained JSON... },
27
+ * ...
28
+ * }
29
+ */
30
+ function extractStructuredOutput(stdout) {
31
+ try {
32
+ const envelope = JSON.parse(stdout);
33
+ if (envelope &&
34
+ typeof envelope === "object" &&
35
+ "structured_output" in envelope &&
36
+ envelope.structured_output !== null &&
37
+ typeof envelope.structured_output === "object") {
38
+ return JSON.stringify(envelope.structured_output);
39
+ }
40
+ }
41
+ catch {
42
+ // Not JSON — may indicate a pre-envelope error or auth failure
43
+ }
44
+ return null;
45
+ }
46
+ /**
47
+ * Classify a CLI invocation failure as `capability` (downgrade-eligible) or
48
+ * `fatal` (terminal). Capability errors indicate the CLI doesn't support the
49
+ * requested structured output flag; fatal errors are everything else.
50
+ */
51
+ function classifyError(stderr, exitCode) {
52
+ const lower = stderr.toLowerCase();
53
+ const capabilityIndicators = [
54
+ "unknown flag",
55
+ "unknown option",
56
+ "unrecognized",
57
+ "invalid schema",
58
+ "invalid json schema",
59
+ "json-schema",
60
+ "unsupported",
61
+ ];
62
+ const isCapability = capabilityIndicators.some((indicator) => lower.includes(indicator));
63
+ return {
64
+ kind: isCapability ? "capability" : "fatal",
65
+ message: stderr.slice(0, 500) || `claude exited with code ${exitCode}`,
66
+ exitCode,
67
+ stderr,
68
+ };
69
+ }
16
70
  export class ClaudeProvider {
17
71
  name = "claude";
72
+ capabilityCache = null;
18
73
  async invoke(prompt, options) {
19
- // claude -p reads prompt from stdin when no positional arg is given
20
- const args = ["-p", "--output-format", "text"];
74
+ // claude -p reads prompt from stdin when no positional arg is given.
75
+ // --bare skips hooks/MCP/auto-memory/CLAUDE.md/plugin-sync for faster
76
+ // subprocess startup, but it bypasses OAuth/keychain — only safe to use
77
+ // when ANTHROPIC_API_KEY is set.
78
+ const args = ["-p"];
79
+ if (process.env.ANTHROPIC_API_KEY) {
80
+ args.push("--bare");
81
+ }
82
+ if (options.jsonSchema) {
83
+ // With a schema, use --output-format json so the response envelope
84
+ // includes a `structured_output` field containing the model's
85
+ // constrained JSON as a native object. --output-format text drops
86
+ // the structured_output field entirely.
87
+ args.push("--output-format", "json", "--json-schema", JSON.stringify(options.jsonSchema));
88
+ }
89
+ else {
90
+ args.push("--output-format", "text");
91
+ }
21
92
  if (options.model) {
22
93
  args.push("--model", options.model);
23
94
  }
@@ -32,22 +103,45 @@ export class ClaudeProvider {
32
103
  extendEnv: false,
33
104
  input: prompt,
34
105
  });
35
- if (result.exitCode !== 0) {
36
- process.stderr.write(`[claude-provider] exit=${result.exitCode} stderr=${result.stderr?.slice(0, 500)}\n`);
106
+ const duration = Date.now() - start;
107
+ const exitCode = result.exitCode ?? 1;
108
+ // claude -p can exit non-zero with valid stdout. Treat presence of
109
+ // stdout as success even on non-zero exit.
110
+ if (result.stdout && result.stdout.trim().length > 0) {
111
+ if (options.jsonSchema) {
112
+ // Parse claude's envelope and extract structured_output.
113
+ const extracted = extractStructuredOutput(result.stdout);
114
+ if (extracted === null) {
115
+ return {
116
+ ok: false,
117
+ error: {
118
+ kind: "capability",
119
+ message: `claude returned envelope without structured_output field: ${result.stdout.slice(0, 300)}`,
120
+ exitCode,
121
+ stderr: result.stderr,
122
+ },
123
+ duration,
124
+ };
125
+ }
126
+ return { ok: true, output: extracted, duration };
127
+ }
128
+ return { ok: true, output: result.stdout, duration };
37
129
  }
130
+ // No usable output — classify the failure
131
+ process.stderr.write(`[claude-provider] exit=${exitCode} stderr=${result.stderr?.slice(0, 500)}\n`);
38
132
  return {
39
- content: result.stdout,
40
- exitCode: result.exitCode ?? 1,
41
- duration: Date.now() - start,
133
+ ok: false,
134
+ error: classifyError(result.stderr ?? "", exitCode),
135
+ duration,
42
136
  };
43
137
  }
44
138
  catch (error) {
139
+ const duration = Date.now() - start;
140
+ const message = error instanceof Error ? error.message : "Unknown error invoking claude";
45
141
  return {
46
- content: error instanceof Error
47
- ? error.message
48
- : "Unknown error invoking claude",
49
- exitCode: 1,
50
- duration: Date.now() - start,
142
+ ok: false,
143
+ error: { kind: "fatal", message, exitCode: 1 },
144
+ duration,
51
145
  };
52
146
  }
53
147
  }
@@ -66,6 +160,34 @@ export class ClaudeProvider {
66
160
  return false;
67
161
  }
68
162
  }
163
+ async checkStructuredOutputSupport() {
164
+ if (this.capabilityCache !== null) {
165
+ return this.capabilityCache;
166
+ }
167
+ try {
168
+ const result = await execa("claude", ["--help"], {
169
+ preferLocal: true,
170
+ timeout: 5_000,
171
+ reject: false,
172
+ env: cleanEnv(),
173
+ extendEnv: false,
174
+ });
175
+ const helpText = `${result.stdout ?? ""}\n${result.stderr ?? ""}`;
176
+ const supported = helpText.includes("--json-schema");
177
+ this.capabilityCache = supported;
178
+ if (!supported) {
179
+ process.stderr.write(`[planpong] Structured output not supported by claude — using legacy parsing\n`);
180
+ }
181
+ return supported;
182
+ }
183
+ catch {
184
+ this.capabilityCache = false;
185
+ return false;
186
+ }
187
+ }
188
+ markNonCapable() {
189
+ this.capabilityCache = false;
190
+ }
69
191
  getModels() {
70
192
  return MODELS;
71
193
  }
@@ -1 +1 @@
1
- {"version":3,"file":"claude.js","sourceRoot":"","sources":["../../../src/providers/claude.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAG9B,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;AAE3C;;;GAGG;AACH,SAAS,QAAQ;IACf,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACvD,IAAI,GAAG,KAAK,YAAY,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YAChD,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACnB,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,OAAO,cAAc;IACzB,IAAI,GAAG,QAAQ,CAAC;IAEhB,KAAK,CAAC,MAAM,CACV,MAAc,EACd,OAAsB;QAEtB,oEAAoE;QACpE,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,iBAAiB,EAAE,MAAM,CAAC,CAAC;QAE/C,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAClB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;QACtC,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE;gBACzC,GAAG,EAAE,OAAO,CAAC,GAAG;gBAChB,WAAW,EAAE,IAAI;gBACjB,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,OAAO;gBACnC,MAAM,EAAE,KAAK;gBACb,GAAG,EAAE,QAAQ,EAAE;gBACf,SAAS,EAAE,KAAK;gBAChB,KAAK,EAAE,MAAM;aACd,CAAC,CAAC;YAEH,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;gBAC1B,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,0BAA0B,MAAM,CAAC,QAAQ,WAAW,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,CACrF,CAAC;YACJ,CAAC;YAED,OAAO;gBACL,OAAO,EAAE,MAAM,CAAC,MAAM;gBACtB,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,CAAC;gBAC9B,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;aAC7B,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,OAAO,EACL,KAAK,YAAY,KAAK;oBACpB,CAAC,CAAC,KAAK,CAAC,OAAO;oBACf,CAAC,CAAC,+BAA+B;gBACrC,QAAQ,EAAE,CAAC;gBACX,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;aAC7B,CAAC;QACJ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,WAAW;QACf,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE,CAAC,WAAW,CAAC,EAAE;gBAClD,WAAW,EAAE,IAAI;gBACjB,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,KAAK;gBACb,GAAG,EAAE,QAAQ,EAAE;gBACf,SAAS,EAAE,KAAK;aACjB,CAAC,CAAC;YACH,OAAO,MAAM,CAAC,QAAQ,KAAK,CAAC,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,SAAS;QACP,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,eAAe;QACb,oEAAoE;QACpE,OAAO,CAAC,SAAS,CAAC,CAAC;IACrB,CAAC;CACF"}
1
+ {"version":3,"file":"claude.js","sourceRoot":"","sources":["../../../src/providers/claude.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,11 @@
1
1
  import type { Provider, InvokeOptions, ProviderResponse } from "./types.js";
2
2
  export declare class CodexProvider implements Provider {
3
3
  name: string;
4
+ private capabilityCache;
4
5
  invoke(prompt: string, options: InvokeOptions): Promise<ProviderResponse>;
5
6
  isAvailable(): Promise<boolean>;
7
+ checkStructuredOutputSupport(): Promise<boolean>;
8
+ markNonCapable(): void;
6
9
  getModels(): string[];
7
10
  getEffortLevels(): string[];
8
11
  }