planpong 0.1.0

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 (83) hide show
  1. package/README.md +110 -0
  2. package/dist/bin/planpong-mcp.d.ts +2 -0
  3. package/dist/bin/planpong-mcp.js +7 -0
  4. package/dist/bin/planpong-mcp.js.map +1 -0
  5. package/dist/bin/planpong.d.ts +2 -0
  6. package/dist/bin/planpong.js +13 -0
  7. package/dist/bin/planpong.js.map +1 -0
  8. package/dist/src/cli/commands/plan.d.ts +2 -0
  9. package/dist/src/cli/commands/plan.js +128 -0
  10. package/dist/src/cli/commands/plan.js.map +1 -0
  11. package/dist/src/cli/commands/review.d.ts +2 -0
  12. package/dist/src/cli/commands/review.js +156 -0
  13. package/dist/src/cli/commands/review.js.map +1 -0
  14. package/dist/src/cli/ui.d.ts +11 -0
  15. package/dist/src/cli/ui.js +65 -0
  16. package/dist/src/cli/ui.js.map +1 -0
  17. package/dist/src/config/defaults.d.ts +2 -0
  18. package/dist/src/config/defaults.js +12 -0
  19. package/dist/src/config/defaults.js.map +1 -0
  20. package/dist/src/config/loader.d.ts +17 -0
  21. package/dist/src/config/loader.js +74 -0
  22. package/dist/src/config/loader.js.map +1 -0
  23. package/dist/src/core/convergence.d.ts +10 -0
  24. package/dist/src/core/convergence.js +56 -0
  25. package/dist/src/core/convergence.js.map +1 -0
  26. package/dist/src/core/loop.d.ts +53 -0
  27. package/dist/src/core/loop.js +256 -0
  28. package/dist/src/core/loop.js.map +1 -0
  29. package/dist/src/core/operations.d.ts +68 -0
  30. package/dist/src/core/operations.js +323 -0
  31. package/dist/src/core/operations.js.map +1 -0
  32. package/dist/src/core/session.d.ts +14 -0
  33. package/dist/src/core/session.js +77 -0
  34. package/dist/src/core/session.js.map +1 -0
  35. package/dist/src/mcp/server.d.ts +2 -0
  36. package/dist/src/mcp/server.js +109 -0
  37. package/dist/src/mcp/server.js.map +1 -0
  38. package/dist/src/mcp/tools/get-feedback.d.ts +2 -0
  39. package/dist/src/mcp/tools/get-feedback.js +109 -0
  40. package/dist/src/mcp/tools/get-feedback.js.map +1 -0
  41. package/dist/src/mcp/tools/list-sessions.d.ts +2 -0
  42. package/dist/src/mcp/tools/list-sessions.js +61 -0
  43. package/dist/src/mcp/tools/list-sessions.js.map +1 -0
  44. package/dist/src/mcp/tools/revise.d.ts +2 -0
  45. package/dist/src/mcp/tools/revise.js +84 -0
  46. package/dist/src/mcp/tools/revise.js.map +1 -0
  47. package/dist/src/mcp/tools/start-review.d.ts +2 -0
  48. package/dist/src/mcp/tools/start-review.js +105 -0
  49. package/dist/src/mcp/tools/start-review.js.map +1 -0
  50. package/dist/src/mcp/tools/status.d.ts +2 -0
  51. package/dist/src/mcp/tools/status.js +83 -0
  52. package/dist/src/mcp/tools/status.js.map +1 -0
  53. package/dist/src/prompts/planner.d.ts +3 -0
  54. package/dist/src/prompts/planner.js +96 -0
  55. package/dist/src/prompts/planner.js.map +1 -0
  56. package/dist/src/prompts/reviewer.d.ts +11 -0
  57. package/dist/src/prompts/reviewer.js +70 -0
  58. package/dist/src/prompts/reviewer.js.map +1 -0
  59. package/dist/src/providers/claude.d.ts +8 -0
  60. package/dist/src/providers/claude.js +77 -0
  61. package/dist/src/providers/claude.js.map +1 -0
  62. package/dist/src/providers/codex.d.ts +8 -0
  63. package/dist/src/providers/codex.js +83 -0
  64. package/dist/src/providers/codex.js.map +1 -0
  65. package/dist/src/providers/registry.d.ts +4 -0
  66. package/dist/src/providers/registry.js +17 -0
  67. package/dist/src/providers/registry.js.map +1 -0
  68. package/dist/src/providers/types.d.ts +18 -0
  69. package/dist/src/providers/types.js +2 -0
  70. package/dist/src/providers/types.js.map +1 -0
  71. package/dist/src/schemas/config.d.ts +75 -0
  72. package/dist/src/schemas/config.js +14 -0
  73. package/dist/src/schemas/config.js.map +1 -0
  74. package/dist/src/schemas/feedback.d.ts +95 -0
  75. package/dist/src/schemas/feedback.js +24 -0
  76. package/dist/src/schemas/feedback.js.map +1 -0
  77. package/dist/src/schemas/revision.d.ts +116 -0
  78. package/dist/src/schemas/revision.js +17 -0
  79. package/dist/src/schemas/revision.js.map +1 -0
  80. package/dist/src/schemas/session.d.ts +79 -0
  81. package/dist/src/schemas/session.js +16 -0
  82. package/dist/src/schemas/session.js.map +1 -0
  83. package/package.json +52 -0
@@ -0,0 +1,323 @@
1
+ import { createHash } from "node:crypto";
2
+ import { readFileSync, writeFileSync, existsSync } from "node:fs";
3
+ import { relative, resolve } from "node:path";
4
+ import { buildRevisionPrompt } from "../prompts/planner.js";
5
+ import { buildReviewPrompt, formatPriorDecisions, } from "../prompts/reviewer.js";
6
+ import { parseFeedback, parseRevision, isConverged } from "./convergence.js";
7
+ import { createSession, writeSessionState, writeRoundFeedback, writeRoundResponse, readRoundFeedback, readRoundResponse, writeInitialPlan, } from "./session.js";
8
+ // --- Utility functions ---
9
+ export function hashFile(path) {
10
+ const content = readFileSync(path, "utf-8");
11
+ return createHash("sha256").update(content).digest("hex");
12
+ }
13
+ function extractKeyDecisions(plan) {
14
+ const match = plan.match(/## Key [Dd]ecisions\s*\n([\s\S]*?)(?=\n## |\n---|\Z)/);
15
+ return match?.[1]?.trim() ?? null;
16
+ }
17
+ function countLines(text) {
18
+ return text.split("\n").length;
19
+ }
20
+ export function formatRoundSeverity(round) {
21
+ const parts = [];
22
+ if (round.P1 > 0)
23
+ parts.push(`${round.P1}P1`);
24
+ if (round.P2 > 0)
25
+ parts.push(`${round.P2}P2`);
26
+ if (round.P3 > 0)
27
+ parts.push(`${round.P3}P3`);
28
+ if (parts.length === 0)
29
+ return "0";
30
+ return parts.join(" ");
31
+ }
32
+ export function formatTrajectory(trajectory) {
33
+ return trajectory.map(formatRoundSeverity).join(" → ");
34
+ }
35
+ export function severityFromFeedback(feedback) {
36
+ const counts = { P1: 0, P2: 0, P3: 0 };
37
+ for (const issue of feedback.issues) {
38
+ counts[issue.severity]++;
39
+ }
40
+ return counts;
41
+ }
42
+ export function formatTallies(accepted, rejected, deferred) {
43
+ const parts = [];
44
+ if (accepted > 0)
45
+ parts.push(`Accepted: ${accepted}`);
46
+ if (rejected > 0)
47
+ parts.push(`Rejected: ${rejected}`);
48
+ if (deferred > 0)
49
+ parts.push(`Deferred: ${deferred}`);
50
+ return parts.join(" | ");
51
+ }
52
+ export function formatDuration(ms) {
53
+ const seconds = Math.floor(ms / 1000);
54
+ const minutes = Math.floor(seconds / 60);
55
+ const remainingSeconds = seconds % 60;
56
+ if (minutes === 0)
57
+ return `${seconds}s`;
58
+ return `${minutes}m ${remainingSeconds}s`;
59
+ }
60
+ export function formatProviderLabel(provider) {
61
+ const hasModel = provider.model && provider.model !== "default";
62
+ const hasEffort = provider.effort && provider.effort !== "default";
63
+ if (!hasModel && !hasEffort)
64
+ return provider.provider;
65
+ const parts = [
66
+ hasModel ? provider.model : null,
67
+ hasEffort ? provider.effort : null,
68
+ ].filter(Boolean);
69
+ return `${provider.provider}(${parts.join("/")})`;
70
+ }
71
+ export function computeSessionStats(cwd, sessionId, currentRound) {
72
+ const trajectory = [];
73
+ let totalAccepted = 0;
74
+ let totalRejected = 0;
75
+ let totalDeferred = 0;
76
+ for (let r = 1; r <= currentRound; r++) {
77
+ const feedback = readRoundFeedback(cwd, sessionId, r);
78
+ if (feedback) {
79
+ trajectory.push(severityFromFeedback(feedback));
80
+ }
81
+ const response = readRoundResponse(cwd, sessionId, r);
82
+ if (response) {
83
+ for (const resp of response.responses) {
84
+ if (resp.action === "accepted")
85
+ totalAccepted++;
86
+ else if (resp.action === "rejected")
87
+ totalRejected++;
88
+ else if (resp.action === "deferred")
89
+ totalDeferred++;
90
+ }
91
+ }
92
+ }
93
+ return {
94
+ issueTrajectory: trajectory,
95
+ totalAccepted,
96
+ totalRejected,
97
+ totalDeferred,
98
+ };
99
+ }
100
+ export function buildStatusLine(session, config, issueTrajectory, accepted, rejected, deferred, linesAdded, linesRemoved, elapsed) {
101
+ const plannerLabel = formatProviderLabel(config.planner);
102
+ const reviewerLabel = formatProviderLabel(config.reviewer);
103
+ const trajectory = formatTrajectory(issueTrajectory);
104
+ const tallies = formatTallies(accepted, rejected, deferred);
105
+ const elapsedStr = formatDuration(elapsed);
106
+ const parts = [
107
+ `**planpong:** R${session.currentRound}/${config.max_rounds}`,
108
+ `${plannerLabel} → ${reviewerLabel}`,
109
+ trajectory,
110
+ tallies,
111
+ `+${linesAdded}/-${linesRemoved} lines`,
112
+ elapsedStr,
113
+ ].filter(Boolean);
114
+ return parts.join(" | ");
115
+ }
116
+ /**
117
+ * Build and write the status line to the plan file.
118
+ * Used by both CLI and MCP paths after each round.
119
+ */
120
+ export function writeStatusLineToPlan(session, cwd, config, suffix) {
121
+ const planPath = resolve(cwd, session.planPath);
122
+ let planContent = readFileSync(planPath, "utf-8");
123
+ const stats = computeSessionStats(cwd, session.id, session.currentRound);
124
+ const elapsed = Date.now() - new Date(session.startedAt).getTime();
125
+ const currentLines = countLines(planContent);
126
+ const initialLines = session.initialLineCount ?? currentLines;
127
+ const linesAdded = Math.max(0, currentLines - initialLines);
128
+ const linesRemoved = Math.max(0, initialLines - currentLines);
129
+ const statusLine = buildStatusLine(session, config, stats.issueTrajectory, stats.totalAccepted, stats.totalRejected, stats.totalDeferred, linesAdded, linesRemoved, elapsed) + (suffix ? ` | ${suffix}` : "");
130
+ planContent = updatePlanStatusLine(planContent, statusLine);
131
+ writeFileSync(planPath, planContent);
132
+ session.planHash = hashFile(planPath);
133
+ writeSessionState(cwd, session);
134
+ return statusLine;
135
+ }
136
+ export function updatePlanStatusLine(planContent, statusLine) {
137
+ const lines = planContent.split("\n");
138
+ const planpongIdx = lines.findIndex((l) => l.startsWith("**planpong:**"));
139
+ if (planpongIdx >= 0) {
140
+ lines[planpongIdx] = statusLine;
141
+ }
142
+ else {
143
+ const statusIdx = lines.findIndex((l) => l.startsWith("**Status:**"));
144
+ if (statusIdx >= 0) {
145
+ lines.splice(statusIdx + 1, 0, statusLine);
146
+ }
147
+ else {
148
+ lines.splice(1, 0, "", statusLine);
149
+ }
150
+ }
151
+ return lines.join("\n");
152
+ }
153
+ // --- Core operations ---
154
+ /**
155
+ * Initialize a review session for an existing plan file.
156
+ * Validates the file exists, creates a session directory, and writes
157
+ * an initial status line to the plan.
158
+ */
159
+ export function initReviewSession(planPath, cwd, config) {
160
+ if (!existsSync(planPath)) {
161
+ throw new Error(`Plan file not found: ${planPath}`);
162
+ }
163
+ const relativePlanPath = relative(cwd, planPath);
164
+ const originalContent = readFileSync(planPath, "utf-8");
165
+ let planContent = originalContent;
166
+ const initialStatusLine = `**planpong:** R0/${config.max_rounds} | ${formatProviderLabel(config.planner)} → ${formatProviderLabel(config.reviewer)} | Awaiting review`;
167
+ planContent = updatePlanStatusLine(planContent, initialStatusLine);
168
+ writeFileSync(planPath, planContent);
169
+ const session = createSession(cwd, relativePlanPath, config.planner, config.reviewer, hashFile(planPath));
170
+ session.initialLineCount = countLines(planContent);
171
+ session.status = "in_review";
172
+ writeInitialPlan(cwd, session.id, originalContent);
173
+ writeSessionState(cwd, session);
174
+ return { session, planContent, config };
175
+ }
176
+ /**
177
+ * Build prior decisions context for rounds 2+.
178
+ */
179
+ function buildPriorDecisions(cwd, sessionId, currentRound) {
180
+ if (currentRound <= 1)
181
+ return null;
182
+ const priorRounds = [];
183
+ for (let r = 1; r < currentRound; r++) {
184
+ const fb = readRoundFeedback(cwd, sessionId, r);
185
+ const resp = readRoundResponse(cwd, sessionId, r);
186
+ if (fb && resp) {
187
+ priorRounds.push({
188
+ round: r,
189
+ responses: resp.responses,
190
+ issues: fb.issues.map((i) => ({
191
+ id: i.id,
192
+ severity: i.severity,
193
+ title: i.title,
194
+ })),
195
+ });
196
+ }
197
+ }
198
+ if (priorRounds.length === 0)
199
+ return null;
200
+ return formatPriorDecisions(priorRounds);
201
+ }
202
+ /**
203
+ * Run a single review round: send current plan to the reviewer for critique.
204
+ */
205
+ export async function runReviewRound(session, cwd, config, reviewerProvider) {
206
+ const round = session.currentRound;
207
+ const planPath = resolve(cwd, session.planPath);
208
+ const planContent = readFileSync(planPath, "utf-8");
209
+ const priorDecisions = buildPriorDecisions(cwd, session.id, round);
210
+ const reviewPrompt = buildReviewPrompt(planContent, priorDecisions);
211
+ const reviewResponse = await reviewerProvider.invoke(reviewPrompt, {
212
+ cwd,
213
+ model: config.reviewer.model,
214
+ effort: config.reviewer.effort,
215
+ });
216
+ // Try to parse even on non-zero exit — CLIs can exit 1 with valid output
217
+ let feedback;
218
+ try {
219
+ feedback = parseFeedback(reviewResponse.content);
220
+ }
221
+ catch (parseError) {
222
+ // If exit code was also non-zero, the provider genuinely failed
223
+ if (reviewResponse.exitCode !== 0) {
224
+ throw new Error(`Reviewer failed (exit ${reviewResponse.exitCode}):\n${reviewResponse.content.slice(0, 500)}`);
225
+ }
226
+ // Exit was 0 but parse failed — retry
227
+ const retryPrompt = `Your previous response could not be parsed. Please output ONLY a valid JSON object wrapped in <planpong-feedback> tags. The error was: ${parseError instanceof Error ? parseError.message : "parse error"}\n\nOriginal prompt:\n${reviewPrompt}`;
228
+ const retryResponse = await reviewerProvider.invoke(retryPrompt, {
229
+ cwd,
230
+ model: config.reviewer.model,
231
+ effort: config.reviewer.effort,
232
+ });
233
+ feedback = parseFeedback(retryResponse.content);
234
+ }
235
+ writeRoundFeedback(cwd, session.id, round, feedback);
236
+ const severity = severityFromFeedback(feedback);
237
+ const converged = isConverged(feedback);
238
+ return { round, feedback, severity, converged };
239
+ }
240
+ /**
241
+ * Run a single revision round: send plan + feedback to the planner for revision.
242
+ */
243
+ export async function runRevisionRound(session, cwd, config, plannerProvider) {
244
+ const round = session.currentRound;
245
+ const planPath = resolve(cwd, session.planPath);
246
+ const planContent = readFileSync(planPath, "utf-8");
247
+ const feedback = readRoundFeedback(cwd, session.id, round);
248
+ if (!feedback) {
249
+ throw new Error(`No feedback found for session ${session.id} round ${round}`);
250
+ }
251
+ const keyDecisions = extractKeyDecisions(planContent);
252
+ const revisionPrompt = buildRevisionPrompt(planContent, feedback, keyDecisions, null);
253
+ const revisionResponse = await plannerProvider.invoke(revisionPrompt, {
254
+ cwd,
255
+ model: config.planner.model,
256
+ effort: config.planner.effort,
257
+ });
258
+ // Try to parse even on non-zero exit — CLIs can exit 1 with valid output
259
+ let revision;
260
+ try {
261
+ revision = parseRevision(revisionResponse.content);
262
+ }
263
+ catch (parseError) {
264
+ // If exit code was also non-zero, the provider genuinely failed
265
+ if (revisionResponse.exitCode !== 0) {
266
+ throw new Error(`Planner revision failed (exit ${revisionResponse.exitCode}):\n${revisionResponse.content.slice(0, 500)}`);
267
+ }
268
+ // Exit was 0 but parse failed — retry
269
+ const retryPrompt = `Your previous response could not be parsed. Please output ONLY a valid JSON object wrapped in <planpong-revision> tags. The error was: ${parseError instanceof Error ? parseError.message : "parse error"}\n\nOriginal prompt:\n${revisionPrompt}`;
270
+ const retryResponse = await plannerProvider.invoke(retryPrompt, {
271
+ cwd,
272
+ model: config.planner.model,
273
+ effort: config.planner.effort,
274
+ });
275
+ revision = parseRevision(retryResponse.content);
276
+ }
277
+ writeRoundResponse(cwd, session.id, round, revision);
278
+ // Tally responses
279
+ let accepted = 0;
280
+ let rejected = 0;
281
+ let deferred = 0;
282
+ for (const resp of revision.responses) {
283
+ if (resp.action === "accepted")
284
+ accepted++;
285
+ else if (resp.action === "rejected")
286
+ rejected++;
287
+ else if (resp.action === "deferred")
288
+ deferred++;
289
+ }
290
+ // Write updated plan to disk
291
+ const updatedPlan = revision.updated_plan;
292
+ writeFileSync(planPath, updatedPlan);
293
+ session.planHash = hashFile(planPath);
294
+ writeSessionState(cwd, session);
295
+ return {
296
+ round,
297
+ revision,
298
+ accepted,
299
+ rejected,
300
+ deferred,
301
+ planUpdated: true,
302
+ };
303
+ }
304
+ /**
305
+ * Mark the session as approved and update the plan's status line.
306
+ */
307
+ export function finalizeApproved(session, cwd, config, issueTrajectory, totalAccepted, totalRejected, totalDeferred, startTime, initialLineCount) {
308
+ const planPath = resolve(cwd, session.planPath);
309
+ const round = session.currentRound;
310
+ const elapsed = Date.now() - startTime;
311
+ let planContent = readFileSync(planPath, "utf-8");
312
+ const currentLines = countLines(planContent);
313
+ const linesAdded = Math.max(0, currentLines - initialLineCount);
314
+ const linesRemoved = Math.max(0, initialLineCount - currentLines);
315
+ const finalStatus = buildStatusLine(session, config, issueTrajectory, totalAccepted, totalRejected, totalDeferred, linesAdded, linesRemoved, elapsed) + ` | Approved after ${round} rounds`;
316
+ planContent = updatePlanStatusLine(planContent, finalStatus);
317
+ planContent = planContent.replace(/\*\*Status:\*\* .*/, "**Status:** Approved");
318
+ writeFileSync(planPath, planContent);
319
+ session.status = "approved";
320
+ session.planHash = hashFile(planPath);
321
+ writeSessionState(cwd, session);
322
+ }
323
+ //# sourceMappingURL=operations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operations.js","sourceRoot":"","sources":["../../../src/core/operations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { Session } from "../schemas/session.js";
2
+ import type { ReviewFeedback } from "../schemas/feedback.js";
3
+ import type { PlannerRevision } from "../schemas/revision.js";
4
+ import type { ProviderConfig } from "../schemas/config.js";
5
+ export declare function createSession(repoRoot: string, planPath: string, planner: ProviderConfig, reviewer: ProviderConfig, planHash: string): Session;
6
+ export declare function writeSessionState(repoRoot: string, session: Session): void;
7
+ export declare function readSessionState(repoRoot: string, sessionId: string): Session | null;
8
+ export declare function writeRoundFeedback(repoRoot: string, sessionId: string, round: number, feedback: ReviewFeedback): void;
9
+ export declare function writeRoundResponse(repoRoot: string, sessionId: string, round: number, response: PlannerRevision): void;
10
+ export declare function readRoundFeedback(repoRoot: string, sessionId: string, round: number): ReviewFeedback | null;
11
+ export declare function readRoundResponse(repoRoot: string, sessionId: string, round: number): PlannerRevision | null;
12
+ export declare function writeInitialPlan(repoRoot: string, sessionId: string, content: string): void;
13
+ export declare function readInitialPlan(repoRoot: string, sessionId: string): string | null;
14
+ export declare function resolvePlanPath(session: Session): string;
@@ -0,0 +1,77 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
+ import { dirname, join, resolve } from "node:path";
4
+ const SESSIONS_DIR = ".planpong/sessions";
5
+ function getSessionDir(repoRoot, sessionId) {
6
+ return join(repoRoot, SESSIONS_DIR, sessionId);
7
+ }
8
+ export function createSession(repoRoot, planPath, planner, reviewer, planHash) {
9
+ const id = randomBytes(6).toString("hex");
10
+ const session = {
11
+ id,
12
+ repoRoot: resolve(repoRoot),
13
+ planPath,
14
+ planPathAbsolute: resolve(repoRoot, planPath),
15
+ planner,
16
+ reviewer,
17
+ status: "planning",
18
+ currentRound: 0,
19
+ startedAt: new Date().toISOString(),
20
+ planHash,
21
+ };
22
+ const dir = getSessionDir(repoRoot, id);
23
+ mkdirSync(dir, { recursive: true });
24
+ writeSessionState(repoRoot, session);
25
+ return session;
26
+ }
27
+ export function writeSessionState(repoRoot, session) {
28
+ const dir = getSessionDir(repoRoot, session.id);
29
+ writeFileSync(join(dir, "session.json"), JSON.stringify(session, null, 2));
30
+ }
31
+ export function readSessionState(repoRoot, sessionId) {
32
+ const path = join(getSessionDir(repoRoot, sessionId), "session.json");
33
+ if (!existsSync(path))
34
+ return null;
35
+ return JSON.parse(readFileSync(path, "utf-8"));
36
+ }
37
+ export function writeRoundFeedback(repoRoot, sessionId, round, feedback) {
38
+ const dir = getSessionDir(repoRoot, sessionId);
39
+ writeFileSync(join(dir, `round-${round}-feedback.json`), JSON.stringify(feedback, null, 2));
40
+ }
41
+ export function writeRoundResponse(repoRoot, sessionId, round, response) {
42
+ const dir = getSessionDir(repoRoot, sessionId);
43
+ writeFileSync(join(dir, `round-${round}-response.json`), JSON.stringify(response, null, 2));
44
+ }
45
+ export function readRoundFeedback(repoRoot, sessionId, round) {
46
+ const path = join(getSessionDir(repoRoot, sessionId), `round-${round}-feedback.json`);
47
+ if (!existsSync(path))
48
+ return null;
49
+ return JSON.parse(readFileSync(path, "utf-8"));
50
+ }
51
+ export function readRoundResponse(repoRoot, sessionId, round) {
52
+ const path = join(getSessionDir(repoRoot, sessionId), `round-${round}-response.json`);
53
+ if (!existsSync(path))
54
+ return null;
55
+ return JSON.parse(readFileSync(path, "utf-8"));
56
+ }
57
+ export function writeInitialPlan(repoRoot, sessionId, content) {
58
+ const dir = getSessionDir(repoRoot, sessionId);
59
+ writeFileSync(join(dir, "initial-plan.md"), content);
60
+ }
61
+ export function readInitialPlan(repoRoot, sessionId) {
62
+ const path = join(getSessionDir(repoRoot, sessionId), "initial-plan.md");
63
+ if (!existsSync(path))
64
+ return null;
65
+ return readFileSync(path, "utf-8");
66
+ }
67
+ export function resolvePlanPath(session) {
68
+ // Try repoRoot + relative path first
69
+ const fromRepo = join(session.repoRoot, session.planPath);
70
+ if (existsSync(dirname(fromRepo)))
71
+ return fromRepo;
72
+ // Fallback to absolute path
73
+ if (existsSync(dirname(session.planPathAbsolute)))
74
+ return session.planPathAbsolute;
75
+ throw new Error(`Cannot resolve plan path. Tried:\n ${fromRepo}\n ${session.planPathAbsolute}`);
76
+ }
77
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../../src/core/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function createPlanpongServer(): McpServer;
@@ -0,0 +1,109 @@
1
+ import { z } from "zod";
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { registerStartReview } from "./tools/start-review.js";
4
+ import { registerGetFeedback } from "./tools/get-feedback.js";
5
+ import { registerRevise } from "./tools/revise.js";
6
+ import { registerStatus } from "./tools/status.js";
7
+ import { registerListSessions } from "./tools/list-sessions.js";
8
+ export function createPlanpongServer() {
9
+ const server = new McpServer({
10
+ name: "planpong",
11
+ version: "0.1.0",
12
+ }, {
13
+ instructions: `Planpong is a multi-model adversarial plan review tool. It sends plans to a reviewer model for critique, then to a planner model for revision, iterating until the plan converges.
14
+
15
+ When the user asks you to review a plan:
16
+ 1. Call planpong_start_review with the plan path. Pass interactive: true if the user asks to review interactively, step by step, or wants to approve each round. Default is false (autonomous).
17
+ 2. Call planpong_get_feedback to get reviewer critique
18
+ 3. Show the user the feedback summary and issues
19
+ 4. If is_converged is false, call planpong_revise to revise the plan
20
+ 5. Show the user the revision summary (accepted/rejected/deferred)
21
+ 6. Repeat steps 2-5 until converged or max rounds reached
22
+
23
+ Execution mode (check the "interactive" field in planpong_start_review response):
24
+ - interactive: false (default) — Run the full loop autonomously. Do NOT ask the user for confirmation between rounds. Only pause if an error occurs or the user explicitly interrupts. Present a brief summary after each round but keep going.
25
+ - interactive: true — After each round, present the results and ask the user if they want to continue, stop, or adjust before proceeding to the next step.
26
+
27
+ When the review completes (converged OR max rounds reached):
28
+ 1. Display the status_line from the final tool response — this is the canonical summary.
29
+ 2. Generate a "Summary of what changed" table comparing the initial plan to the final plan. The final get_feedback response includes initial_plan and final_plan when converged. For max rounds, read the plan file yourself. The table should have columns: Area | Original | Final — showing the key decisions and approaches that changed during the review. Keep it to the most meaningful changes (5-10 rows max). Use a markdown table.
30
+ 3. If the review hit max rounds without converging, note which reviewer concerns remain unresolved and whether they are substantive or deployment-level details.`,
31
+ });
32
+ registerStartReview(server);
33
+ registerGetFeedback(server);
34
+ registerRevise(server);
35
+ registerStatus(server);
36
+ registerListSessions(server);
37
+ // MCP prompts — become slash commands in Claude Code
38
+ server.registerPrompt("review", {
39
+ title: "Review a plan",
40
+ description: "Run adversarial plan review — reviewer critiques, planner revises, repeat until approved",
41
+ argsSchema: {
42
+ plan_path: z
43
+ .string()
44
+ .describe("Path to the plan file (e.g. docs/plans/my-feature.md)"),
45
+ },
46
+ }, (args) => ({
47
+ messages: [
48
+ {
49
+ role: "user",
50
+ content: {
51
+ type: "text",
52
+ text: `Review the plan at ${args.plan_path} using planpong. Run the full review loop autonomously (start_review → get_feedback → revise → repeat until converged). Print a brief summary after each round. When done, display the final status line and a summary table of what changed.`,
53
+ },
54
+ },
55
+ ],
56
+ }));
57
+ server.registerPrompt("review_interactive", {
58
+ title: "Review a plan (interactive)",
59
+ description: "Run adversarial plan review with pauses between rounds for user input",
60
+ argsSchema: {
61
+ plan_path: z
62
+ .string()
63
+ .describe("Path to the plan file (e.g. docs/plans/my-feature.md)"),
64
+ },
65
+ }, (args) => ({
66
+ messages: [
67
+ {
68
+ role: "user",
69
+ content: {
70
+ type: "text",
71
+ text: `Review the plan at ${args.plan_path} using planpong in interactive mode. Start the review with interactive: true, then after each round present the full results and ask me before continuing.`,
72
+ },
73
+ },
74
+ ],
75
+ }));
76
+ server.registerPrompt("status", {
77
+ title: "Check review status",
78
+ description: "Show the current state and round history of a planpong session",
79
+ argsSchema: {
80
+ session_id: z.string().describe("Session ID to check"),
81
+ },
82
+ }, (args) => ({
83
+ messages: [
84
+ {
85
+ role: "user",
86
+ content: {
87
+ type: "text",
88
+ text: `Check the status of planpong session ${args.session_id}. Show the session state, round history, and issue trajectory.`,
89
+ },
90
+ },
91
+ ],
92
+ }));
93
+ server.registerPrompt("sessions", {
94
+ title: "List review sessions",
95
+ description: "List all planpong review sessions in the current project",
96
+ }, () => ({
97
+ messages: [
98
+ {
99
+ role: "user",
100
+ content: {
101
+ type: "text",
102
+ text: "List all planpong review sessions in this project.",
103
+ },
104
+ },
105
+ ],
106
+ }));
107
+ return server;
108
+ }
109
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/mcp/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerGetFeedback(server: McpServer): void;