planpong 0.5.7 → 0.6.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/README.md +53 -14
- package/dist/bin/planpong.js +4 -0
- package/dist/bin/planpong.js.map +1 -1
- package/dist/src/cli/commands/config.d.ts +10 -0
- package/dist/src/cli/commands/config.js +65 -0
- package/dist/src/cli/commands/config.js.map +1 -1
- package/dist/src/cli/commands/init.d.ts +53 -0
- package/dist/src/cli/commands/init.js +221 -0
- package/dist/src/cli/commands/init.js.map +1 -0
- package/dist/src/cli/commands/plan.js +7 -7
- package/dist/src/cli/commands/plan.js.map +1 -1
- package/dist/src/cli/commands/review.js +7 -7
- package/dist/src/cli/commands/review.js.map +1 -1
- package/dist/src/cli/ui.js +11 -19
- package/dist/src/cli/ui.js.map +1 -1
- package/dist/src/config/loader.d.ts +5 -0
- package/dist/src/config/loader.js +21 -1
- package/dist/src/config/loader.js.map +1 -1
- package/dist/src/config/mutate.d.ts +26 -0
- package/dist/src/config/mutate.js +51 -38
- package/dist/src/config/mutate.js.map +1 -1
- package/dist/src/core/convergence.js +1 -1
- package/dist/src/core/convergence.js.map +1 -1
- package/dist/src/core/operations.d.ts +44 -1
- package/dist/src/core/operations.js +110 -37
- package/dist/src/core/operations.js.map +1 -1
- package/dist/src/core/presentation.d.ts +39 -0
- package/dist/src/core/presentation.js +132 -0
- package/dist/src/core/presentation.js.map +1 -0
- package/dist/src/core/round-state.d.ts +15 -0
- package/dist/src/core/round-state.js +49 -0
- package/dist/src/core/round-state.js.map +1 -0
- package/dist/src/core/session.d.ts +1 -0
- package/dist/src/core/session.js +60 -1
- package/dist/src/core/session.js.map +1 -1
- package/dist/src/mcp/server.js +6 -6
- package/dist/src/mcp/server.js.map +1 -1
- package/dist/src/mcp/tools/get-feedback.d.ts +1 -2
- package/dist/src/mcp/tools/get-feedback.js +154 -56
- package/dist/src/mcp/tools/get-feedback.js.map +1 -1
- package/dist/src/mcp/tools/record-revision.d.ts +0 -6
- package/dist/src/mcp/tools/record-revision.js +170 -95
- package/dist/src/mcp/tools/record-revision.js.map +1 -1
- package/dist/src/mcp/tools/revise.d.ts +1 -7
- package/dist/src/mcp/tools/revise.js +126 -90
- package/dist/src/mcp/tools/revise.js.map +1 -1
- package/dist/src/mcp/tools/status.js +18 -1
- package/dist/src/mcp/tools/status.js.map +1 -1
- package/dist/src/providers/claude.d.ts +22 -1
- package/dist/src/providers/claude.js +10 -10
- package/dist/src/providers/claude.js.map +1 -1
- package/dist/src/providers/codex.d.ts +12 -1
- package/dist/src/providers/codex.js +6 -3
- package/dist/src/providers/codex.js.map +1 -1
- package/dist/src/providers/gemini.d.ts +58 -0
- package/dist/src/providers/gemini.js +169 -0
- package/dist/src/providers/gemini.js.map +1 -0
- package/dist/src/providers/registry.js +8 -2
- package/dist/src/providers/registry.js.map +1 -1
- package/dist/src/providers/shared.d.ts +16 -0
- package/dist/src/providers/shared.js +22 -0
- package/dist/src/providers/shared.js.map +1 -0
- package/dist/src/providers/types.d.ts +1 -1
- package/dist/src/schemas/metrics.d.ts +14 -14
- package/dist/src/schemas/metrics.js +13 -2
- package/dist/src/schemas/metrics.js.map +1 -1
- package/dist/src/schemas/session.d.ts +2 -2
- package/package.json +3 -2
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
|
-
import { readSessionState, readRoundFeedback, writeRoundMetrics, } from "../../core/session.js";
|
|
4
|
+
import { readSessionState, readRoundFeedback, readRoundResponse, writeRoundMetrics, withSessionLock, } from "../../core/session.js";
|
|
5
5
|
import { finalizeRevision, writeStatusLineToPlan, } from "../../core/operations.js";
|
|
6
6
|
import { loadConfig } from "../../config/loader.js";
|
|
7
7
|
import { getReviewPhase } from "../../prompts/reviewer.js";
|
|
8
8
|
import { IssueResponseSchema, } from "../../schemas/revision.js";
|
|
9
|
+
import { formatDecisionDisplay } from "../../core/presentation.js";
|
|
9
10
|
/**
|
|
10
11
|
* Inline-mode counterpart to `planpong_revise`. The agent that invoked
|
|
11
12
|
* /pong-review acts as the planner: it edited the plan with its own
|
|
@@ -33,110 +34,184 @@ const inputSchema = {
|
|
|
33
34
|
};
|
|
34
35
|
export async function recordRevisionHandler(input) {
|
|
35
36
|
const cwd = input.cwd ?? process.cwd();
|
|
36
|
-
const
|
|
37
|
-
if (!
|
|
37
|
+
const existing = readSessionState(cwd, input.session_id);
|
|
38
|
+
if (!existing) {
|
|
38
39
|
return errorResponse(`Session not found: ${input.session_id}`);
|
|
39
40
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
41
|
+
return withSessionLock(cwd, input.session_id, async () => {
|
|
42
|
+
const session = readSessionState(cwd, input.session_id);
|
|
43
|
+
if (!session) {
|
|
44
|
+
return errorResponse(`Session not found: ${input.session_id}`);
|
|
45
|
+
}
|
|
46
|
+
if (session.status !== "in_review") {
|
|
47
|
+
return errorResponse(`Session status is '${session.status}', expected 'in_review'`);
|
|
48
|
+
}
|
|
49
|
+
if (session.plannerMode !== "inline") {
|
|
50
|
+
return errorResponse(`session is in ${session.plannerMode} planner mode — use planpong_revise instead`, { planner_mode: session.plannerMode });
|
|
51
|
+
}
|
|
52
|
+
if (input.expected_round !== session.currentRound) {
|
|
53
|
+
const relation = input.expected_round < session.currentRound ? "stale" : "out-of-order";
|
|
54
|
+
const message = relation === "stale"
|
|
55
|
+
? `stale revision call for round ${input.expected_round}; current round is ${session.currentRound}`
|
|
56
|
+
: `out-of-order revision call for round ${input.expected_round}; call planpong_get_feedback first`;
|
|
57
|
+
return errorResponse(message, {
|
|
58
|
+
expected_round: input.expected_round,
|
|
59
|
+
current_round: session.currentRound,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
const feedback = readRoundFeedback(cwd, session.id, session.currentRound);
|
|
63
|
+
if (!feedback) {
|
|
64
|
+
return errorResponse(`No feedback found for session ${session.id} round ${session.currentRound}. Call planpong_get_feedback first.`);
|
|
65
|
+
}
|
|
66
|
+
const existingResponse = readRoundResponse(cwd, session.id, session.currentRound);
|
|
67
|
+
if (existingResponse &&
|
|
68
|
+
JSON.stringify(existingResponse.responses) ===
|
|
69
|
+
JSON.stringify(input.responses)) {
|
|
70
|
+
const accepted = existingResponse.responses.filter((r) => r.action === "accepted").length;
|
|
71
|
+
const rejected = existingResponse.responses.filter((r) => r.action === "rejected").length;
|
|
72
|
+
const deferred = existingResponse.responses.filter((r) => r.action === "deferred").length;
|
|
73
|
+
const config = loadConfig({ cwd });
|
|
74
|
+
const sessionConfig = {
|
|
75
|
+
...config,
|
|
76
|
+
planner: session.planner,
|
|
77
|
+
reviewer: session.reviewer,
|
|
78
|
+
};
|
|
79
|
+
const statusLine = writeStatusLineToPlan(session, cwd, sessionConfig, "Revision recorded");
|
|
80
|
+
return buildRecordRevisionResponse({
|
|
81
|
+
round: session.currentRound,
|
|
82
|
+
feedback,
|
|
83
|
+
revision: existingResponse,
|
|
84
|
+
responses: existingResponse.responses,
|
|
85
|
+
accepted,
|
|
86
|
+
rejected,
|
|
87
|
+
deferred,
|
|
88
|
+
unverifiedRejected: countUnverifiedRejected(existingResponse.responses),
|
|
89
|
+
planUpdated: false,
|
|
90
|
+
statusLine,
|
|
91
|
+
idempotentReplay: true,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
if (existingResponse) {
|
|
95
|
+
return errorResponse(`round ${session.currentRound} already finalized with different responses`, {
|
|
96
|
+
current_round: session.currentRound,
|
|
97
|
+
idempotent_replay: false,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
// Validate every issue has a response. Mirrors the planner prompt's
|
|
101
|
+
// "every issue MUST have an entry in responses" constraint so inline
|
|
102
|
+
// mode produces the same shape downstream tools expect.
|
|
103
|
+
const responseIds = new Set(input.responses.map((r) => r.issue_id));
|
|
104
|
+
const missing = feedback.issues
|
|
105
|
+
.map((i) => i.id)
|
|
106
|
+
.filter((id) => !responseIds.has(id));
|
|
107
|
+
if (missing.length > 0) {
|
|
108
|
+
return errorResponse(`responses missing for issue(s): ${missing.join(", ")}. Provide one response per feedback issue.`, { missing_issue_ids: missing });
|
|
109
|
+
}
|
|
110
|
+
const round = session.currentRound;
|
|
111
|
+
const phase = getReviewPhase(round);
|
|
112
|
+
const planPath = resolve(cwd, session.planPath);
|
|
113
|
+
// Hash before finalize so we can detect "agent forgot to edit".
|
|
114
|
+
const planHashBefore = session.planHash;
|
|
115
|
+
// Construct PlannerRevision-shape payload. Direction phase keeps the
|
|
116
|
+
// full-plan shape; risk/detail keep the edits shape (with empty edits[]
|
|
117
|
+
// — the agent applied changes via its own Edit tool rather than
|
|
118
|
+
// declaring them here, so the array is informational-only).
|
|
119
|
+
const planContent = readFileSync(planPath, "utf-8");
|
|
120
|
+
const revision = phase === "direction"
|
|
121
|
+
? { responses: input.responses, updated_plan: planContent }
|
|
122
|
+
: { responses: input.responses, edits: [] };
|
|
123
|
+
const tally = finalizeRevision({
|
|
124
|
+
session,
|
|
125
|
+
cwd,
|
|
126
|
+
round,
|
|
127
|
+
revision,
|
|
128
|
+
planPath,
|
|
129
|
+
});
|
|
130
|
+
// Plan-hash warn: any accepted issue should correspond to a plan edit.
|
|
131
|
+
// Surface the no-op case but don't gate — sometimes all issues are
|
|
132
|
+
// legitimately rejected and the plan correctly stays unchanged.
|
|
133
|
+
const planUnchanged = session.planHash === planHashBefore;
|
|
134
|
+
const anyAccepted = input.responses.some((r) => r.action === "accepted");
|
|
135
|
+
const planUpdateWarning = planUnchanged && anyAccepted
|
|
136
|
+
? `Round ${round} has accepted issues but the plan hash is unchanged. Confirm the plan edits were applied.`
|
|
137
|
+
: undefined;
|
|
138
|
+
if (planUnchanged && anyAccepted) {
|
|
139
|
+
process.stderr.write(`[planpong] warn: round ${round} has accepted issues but plan hash is unchanged — did the agent forget to edit?\n`);
|
|
140
|
+
}
|
|
141
|
+
// Write fully valid RoundMetrics so bench/run.ts:226 doesn't drop this
|
|
142
|
+
// round from analysis. Inline revisions have no provider duration —
|
|
143
|
+
// started_at and completed_at are the same instant.
|
|
144
|
+
const ts = new Date().toISOString();
|
|
145
|
+
const metrics = {
|
|
146
|
+
schema_version: 1,
|
|
147
|
+
session_id: session.id,
|
|
148
|
+
round,
|
|
149
|
+
phase,
|
|
150
|
+
role: "revision",
|
|
151
|
+
started_at: ts,
|
|
152
|
+
completed_at: ts,
|
|
153
|
+
total_duration_ms: 0,
|
|
154
|
+
attempts: [],
|
|
155
|
+
planner_mode: "inline",
|
|
156
|
+
};
|
|
157
|
+
writeRoundMetrics(cwd, session.id, round, "revision", metrics);
|
|
158
|
+
// Update plan status line. Use loadConfig for provider labels (the
|
|
159
|
+
// status-line writer needs them). In inline mode the planner provider
|
|
160
|
+
// is informational, not invoked.
|
|
161
|
+
const config = loadConfig({ cwd });
|
|
162
|
+
const sessionConfig = {
|
|
163
|
+
...config,
|
|
164
|
+
planner: session.planner,
|
|
165
|
+
reviewer: session.reviewer,
|
|
166
|
+
};
|
|
167
|
+
const statusLine = writeStatusLineToPlan(session, cwd, sessionConfig, "Revision recorded");
|
|
168
|
+
// Match planpong_revise's unverified_rejected counter so the slash
|
|
169
|
+
// command can consume either tool's output uniformly.
|
|
170
|
+
return buildRecordRevisionResponse({
|
|
171
|
+
round,
|
|
172
|
+
feedback,
|
|
173
|
+
revision,
|
|
174
|
+
responses: input.responses,
|
|
175
|
+
accepted: tally.accepted,
|
|
176
|
+
rejected: tally.rejected,
|
|
177
|
+
deferred: tally.deferred,
|
|
178
|
+
unverifiedRejected: countUnverifiedRejected(input.responses),
|
|
179
|
+
planUpdated: !planUnchanged,
|
|
180
|
+
statusLine,
|
|
181
|
+
idempotentReplay: !tally.fresh,
|
|
182
|
+
displayWarning: planUpdateWarning,
|
|
50
183
|
});
|
|
51
|
-
}
|
|
52
|
-
const feedback = readRoundFeedback(cwd, session.id, session.currentRound);
|
|
53
|
-
if (!feedback) {
|
|
54
|
-
return errorResponse(`No feedback found for session ${session.id} round ${session.currentRound}. Call planpong_get_feedback first.`);
|
|
55
|
-
}
|
|
56
|
-
// Validate every issue has a response. Mirrors the planner prompt's
|
|
57
|
-
// "every issue MUST have an entry in responses" constraint so inline
|
|
58
|
-
// mode produces the same shape downstream tools expect.
|
|
59
|
-
const responseIds = new Set(input.responses.map((r) => r.issue_id));
|
|
60
|
-
const missing = feedback.issues
|
|
61
|
-
.map((i) => i.id)
|
|
62
|
-
.filter((id) => !responseIds.has(id));
|
|
63
|
-
if (missing.length > 0) {
|
|
64
|
-
return errorResponse(`responses missing for issue(s): ${missing.join(", ")}. Provide one response per feedback issue.`, { missing_issue_ids: missing });
|
|
65
|
-
}
|
|
66
|
-
const round = session.currentRound;
|
|
67
|
-
const phase = getReviewPhase(round);
|
|
68
|
-
const planPath = resolve(cwd, session.planPath);
|
|
69
|
-
// Hash before finalize so we can detect "agent forgot to edit".
|
|
70
|
-
const planHashBefore = session.planHash;
|
|
71
|
-
// Construct PlannerRevision-shape payload. Direction phase keeps the
|
|
72
|
-
// full-plan shape; risk/detail keep the edits shape (with empty edits[]
|
|
73
|
-
// — the agent applied changes via its own Edit tool rather than
|
|
74
|
-
// declaring them here, so the array is informational-only).
|
|
75
|
-
const planContent = readFileSync(planPath, "utf-8");
|
|
76
|
-
const revision = phase === "direction"
|
|
77
|
-
? { responses: input.responses, updated_plan: planContent }
|
|
78
|
-
: { responses: input.responses, edits: [] };
|
|
79
|
-
const tally = finalizeRevision({
|
|
80
|
-
session,
|
|
81
|
-
cwd,
|
|
82
|
-
round,
|
|
83
|
-
revision,
|
|
84
|
-
planPath,
|
|
85
184
|
});
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const planUnchanged = session.planHash === planHashBefore;
|
|
90
|
-
const anyAccepted = input.responses.some((r) => r.action === "accepted");
|
|
91
|
-
if (planUnchanged && anyAccepted) {
|
|
92
|
-
process.stderr.write(`[planpong] warn: round ${round} has accepted issues but plan hash is unchanged — did the agent forget to edit?\n`);
|
|
93
|
-
}
|
|
94
|
-
// Write fully valid RoundMetrics so bench/run.ts:226 doesn't drop this
|
|
95
|
-
// round from analysis. Inline revisions have no provider duration —
|
|
96
|
-
// started_at and completed_at are the same instant.
|
|
97
|
-
const ts = new Date().toISOString();
|
|
98
|
-
const metrics = {
|
|
99
|
-
schema_version: 1,
|
|
100
|
-
session_id: session.id,
|
|
101
|
-
round,
|
|
102
|
-
phase,
|
|
103
|
-
role: "revision",
|
|
104
|
-
started_at: ts,
|
|
105
|
-
completed_at: ts,
|
|
106
|
-
total_duration_ms: 0,
|
|
107
|
-
attempts: [],
|
|
108
|
-
planner_mode: "inline",
|
|
109
|
-
};
|
|
110
|
-
writeRoundMetrics(cwd, session.id, round, "revision", metrics);
|
|
111
|
-
// Update plan status line. Use loadConfig for provider labels (the
|
|
112
|
-
// status-line writer needs them). In inline mode the planner provider
|
|
113
|
-
// is informational, not invoked.
|
|
114
|
-
const config = loadConfig({ cwd });
|
|
115
|
-
const sessionConfig = {
|
|
116
|
-
...config,
|
|
117
|
-
planner: session.planner,
|
|
118
|
-
reviewer: session.reviewer,
|
|
119
|
-
};
|
|
120
|
-
const statusLine = writeStatusLineToPlan(session, cwd, sessionConfig, "Revision recorded");
|
|
121
|
-
// Match planpong_revise's unverified_rejected counter so the slash
|
|
122
|
-
// command can consume either tool's output uniformly.
|
|
123
|
-
const unverifiedRejected = input.responses.filter((r) => r.action === "rejected" &&
|
|
185
|
+
}
|
|
186
|
+
function countUnverifiedRejected(responses) {
|
|
187
|
+
return responses.filter((r) => r.action === "rejected" &&
|
|
124
188
|
/unverified\s+evidence/i.test(r.rationale ?? "")).length;
|
|
189
|
+
}
|
|
190
|
+
function buildRecordRevisionResponse(args) {
|
|
191
|
+
const display = formatDecisionDisplay({
|
|
192
|
+
round: args.round,
|
|
193
|
+
feedback: args.feedback,
|
|
194
|
+
revision: args.revision,
|
|
195
|
+
warning: args.displayWarning,
|
|
196
|
+
});
|
|
125
197
|
const payload = {
|
|
126
|
-
round,
|
|
127
|
-
responses:
|
|
128
|
-
accepted:
|
|
129
|
-
rejected:
|
|
130
|
-
deferred:
|
|
131
|
-
unverified_rejected: unverifiedRejected,
|
|
132
|
-
plan_updated:
|
|
133
|
-
status_line: statusLine,
|
|
198
|
+
round: args.round,
|
|
199
|
+
responses: args.responses,
|
|
200
|
+
accepted: args.accepted,
|
|
201
|
+
rejected: args.rejected,
|
|
202
|
+
deferred: args.deferred,
|
|
203
|
+
unverified_rejected: args.unverifiedRejected,
|
|
204
|
+
plan_updated: args.planUpdated,
|
|
205
|
+
status_line: args.statusLine,
|
|
134
206
|
planner_mode: "inline",
|
|
135
|
-
idempotent_replay:
|
|
207
|
+
idempotent_replay: args.idempotentReplay,
|
|
208
|
+
decision_rows: display.rows,
|
|
209
|
+
display_markdown: display.markdown,
|
|
210
|
+
...(display.warnings.length > 0 && { display_warnings: display.warnings }),
|
|
136
211
|
};
|
|
137
212
|
return {
|
|
138
213
|
content: [
|
|
139
|
-
{ type: "text", text: statusLine },
|
|
214
|
+
{ type: "text", text: args.statusLine },
|
|
140
215
|
{ type: "text", text: JSON.stringify(payload) },
|
|
141
216
|
],
|
|
142
217
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"record-revision.js","sourceRoot":"","sources":["../../../../src/mcp/tools/record-revision.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,
|
|
1
|
+
{"version":3,"file":"record-revision.js","sourceRoot":"","sources":["../../../../src/mcp/tools/record-revision.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,18 +1,12 @@
|
|
|
1
1
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
2
|
export declare function reviseHandler(input: {
|
|
3
3
|
session_id: string;
|
|
4
|
+
expected_round: number;
|
|
4
5
|
cwd?: string;
|
|
5
6
|
}): Promise<{
|
|
6
7
|
content: {
|
|
7
8
|
type: "text";
|
|
8
9
|
text: string;
|
|
9
10
|
}[];
|
|
10
|
-
isError: boolean;
|
|
11
|
-
} | {
|
|
12
|
-
content: {
|
|
13
|
-
type: "text";
|
|
14
|
-
text: string;
|
|
15
|
-
}[];
|
|
16
|
-
isError?: undefined;
|
|
17
11
|
}>;
|
|
18
12
|
export declare function registerRevise(server: McpServer): void;
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { loadConfig } from "../../config/loader.js";
|
|
3
3
|
import { getProvider } from "../../providers/registry.js";
|
|
4
|
-
import { readSessionState } from "../../core/session.js";
|
|
4
|
+
import { readRoundFeedback, readRoundResponse, readSessionState, withSessionLock, } from "../../core/session.js";
|
|
5
5
|
import { runRevisionRound, writeStatusLineToPlan, } from "../../core/operations.js";
|
|
6
|
+
import { formatDecisionDisplay } from "../../core/presentation.js";
|
|
6
7
|
const inputSchema = {
|
|
7
8
|
session_id: z.string().describe("Session ID from planpong_start_review"),
|
|
9
|
+
expected_round: z
|
|
10
|
+
.number()
|
|
11
|
+
.int()
|
|
12
|
+
.positive()
|
|
13
|
+
.describe("The feedback round this revision responds to. Must equal session.currentRound."),
|
|
8
14
|
cwd: z
|
|
9
15
|
.string()
|
|
10
16
|
.optional()
|
|
@@ -12,111 +18,141 @@ const inputSchema = {
|
|
|
12
18
|
};
|
|
13
19
|
export async function reviseHandler(input) {
|
|
14
20
|
const cwd = input.cwd ?? process.cwd();
|
|
15
|
-
const
|
|
16
|
-
if (!
|
|
17
|
-
return {
|
|
18
|
-
content: [
|
|
19
|
-
{
|
|
20
|
-
type: "text",
|
|
21
|
-
text: JSON.stringify({
|
|
22
|
-
error: `Session not found: ${input.session_id}`,
|
|
23
|
-
}),
|
|
24
|
-
},
|
|
25
|
-
],
|
|
26
|
-
isError: true,
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
if (session.status !== "in_review") {
|
|
30
|
-
return {
|
|
31
|
-
content: [
|
|
32
|
-
{
|
|
33
|
-
type: "text",
|
|
34
|
-
text: JSON.stringify({
|
|
35
|
-
error: `Session status is '${session.status}', expected 'in_review'`,
|
|
36
|
-
}),
|
|
37
|
-
},
|
|
38
|
-
],
|
|
39
|
-
isError: true,
|
|
40
|
-
};
|
|
21
|
+
const existing = readSessionState(cwd, input.session_id);
|
|
22
|
+
if (!existing) {
|
|
23
|
+
return errorResponse(`Session not found: ${input.session_id}`);
|
|
41
24
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
25
|
+
return withSessionLock(cwd, input.session_id, async () => {
|
|
26
|
+
const session = readSessionState(cwd, input.session_id);
|
|
27
|
+
if (!session) {
|
|
28
|
+
return errorResponse(`Session not found: ${input.session_id}`);
|
|
29
|
+
}
|
|
30
|
+
if (input.expected_round < session.currentRound) {
|
|
31
|
+
return errorResponse(`stale revision call for round ${input.expected_round}; current round is ${session.currentRound}`, {
|
|
32
|
+
expected_round: input.expected_round,
|
|
33
|
+
current_round: session.currentRound,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
if (input.expected_round > session.currentRound) {
|
|
37
|
+
return errorResponse(`out-of-order revision call for round ${input.expected_round}; call planpong_get_feedback first`, {
|
|
38
|
+
expected_round: input.expected_round,
|
|
39
|
+
current_round: session.currentRound,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
if (session.status !== "in_review") {
|
|
43
|
+
return errorResponse(`Session status is '${session.status}', expected 'in_review'`);
|
|
44
|
+
}
|
|
45
|
+
if (session.plannerMode === "inline") {
|
|
46
|
+
return errorResponse("session is in inline planner mode — use planpong_record_revision instead", { planner_mode: "inline" });
|
|
47
|
+
}
|
|
48
|
+
const config = loadConfig({ cwd });
|
|
49
|
+
const sessionConfig = {
|
|
50
|
+
...config,
|
|
51
|
+
planner: session.planner,
|
|
52
|
+
reviewer: session.reviewer,
|
|
69
53
|
};
|
|
54
|
+
const feedback = readRoundFeedback(cwd, session.id, input.expected_round);
|
|
55
|
+
if (!feedback) {
|
|
56
|
+
return errorResponse(`No feedback found for session ${session.id} round ${input.expected_round}. Call planpong_get_feedback first.`);
|
|
57
|
+
}
|
|
58
|
+
const existingResponse = readRoundResponse(cwd, session.id, input.expected_round);
|
|
59
|
+
if (existingResponse) {
|
|
60
|
+
const tally = tallyResponses(existingResponse.responses);
|
|
61
|
+
const statusLine = writeStatusLineToPlan(session, cwd, sessionConfig, "Revision submitted");
|
|
62
|
+
return buildRevisionResponse({
|
|
63
|
+
round: input.expected_round,
|
|
64
|
+
revision: existingResponse,
|
|
65
|
+
accepted: tally.accepted,
|
|
66
|
+
rejected: tally.rejected,
|
|
67
|
+
deferred: tally.deferred,
|
|
68
|
+
planUpdated: false,
|
|
69
|
+
statusLine,
|
|
70
|
+
feedback,
|
|
71
|
+
idempotentReplay: true,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
const plannerProvider = getProvider(session.planner.provider);
|
|
75
|
+
if (!plannerProvider) {
|
|
76
|
+
return errorResponse(`Planner provider not found: ${session.planner.provider}`);
|
|
77
|
+
}
|
|
78
|
+
const result = await runRevisionRound(session, cwd, sessionConfig, plannerProvider);
|
|
79
|
+
// Update status line in plan file (planner may have mangled it)
|
|
80
|
+
const statusLine = writeStatusLineToPlan(session, cwd, sessionConfig, "Revision submitted");
|
|
81
|
+
return buildRevisionResponse({
|
|
82
|
+
...result,
|
|
83
|
+
statusLine,
|
|
84
|
+
feedback,
|
|
85
|
+
idempotentReplay: false,
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
function tallyResponses(responses) {
|
|
90
|
+
let accepted = 0;
|
|
91
|
+
let rejected = 0;
|
|
92
|
+
let deferred = 0;
|
|
93
|
+
for (const response of responses) {
|
|
94
|
+
if (response.action === "accepted")
|
|
95
|
+
accepted++;
|
|
96
|
+
else if (response.action === "rejected")
|
|
97
|
+
rejected++;
|
|
98
|
+
else if (response.action === "deferred")
|
|
99
|
+
deferred++;
|
|
70
100
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
};
|
|
76
|
-
const result = await runRevisionRound(session, cwd, sessionConfig, plannerProvider);
|
|
77
|
-
// Update status line in plan file (planner may have mangled it)
|
|
78
|
-
const statusLine = writeStatusLineToPlan(session, cwd, sessionConfig, "Revision submitted");
|
|
79
|
-
// Count rejections whose rationale matches "unverified evidence".
|
|
80
|
-
// Free-text matching is intentionally lenient; the planner prompt
|
|
81
|
-
// suggests the exact phrase but accepts variants (the plan flags
|
|
82
|
-
// this in Limitations & Future Work — a structured enum is a
|
|
83
|
-
// follow-up).
|
|
84
|
-
const unverifiedRejected = result.revision.responses.filter((r) => r.action === "rejected" &&
|
|
101
|
+
return { accepted, rejected, deferred };
|
|
102
|
+
}
|
|
103
|
+
function buildRevisionResponse(args) {
|
|
104
|
+
const unverifiedRejected = args.revision.responses.filter((r) => r.action === "rejected" &&
|
|
85
105
|
/unverified\s+evidence/i.test(r.rationale ?? "")).length;
|
|
106
|
+
const display = formatDecisionDisplay({
|
|
107
|
+
round: args.round,
|
|
108
|
+
feedback: args.feedback,
|
|
109
|
+
revision: args.revision,
|
|
110
|
+
});
|
|
86
111
|
const payload = {
|
|
87
|
-
round:
|
|
88
|
-
responses:
|
|
89
|
-
accepted:
|
|
90
|
-
rejected:
|
|
91
|
-
deferred:
|
|
112
|
+
round: args.round,
|
|
113
|
+
responses: args.revision.responses,
|
|
114
|
+
accepted: args.accepted,
|
|
115
|
+
rejected: args.rejected,
|
|
116
|
+
deferred: args.deferred,
|
|
92
117
|
unverified_rejected: unverifiedRejected,
|
|
93
|
-
plan_updated:
|
|
94
|
-
status_line: statusLine,
|
|
118
|
+
plan_updated: args.planUpdated,
|
|
119
|
+
status_line: args.statusLine,
|
|
120
|
+
idempotent_replay: args.idempotentReplay,
|
|
121
|
+
decision_rows: display.rows,
|
|
122
|
+
display_markdown: display.markdown,
|
|
95
123
|
};
|
|
96
|
-
if (
|
|
97
|
-
payload.
|
|
124
|
+
if (display.warnings.length > 0) {
|
|
125
|
+
payload.display_warnings = display.warnings;
|
|
98
126
|
}
|
|
99
|
-
if (
|
|
100
|
-
payload.
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
payload.
|
|
106
|
-
payload.
|
|
127
|
+
if (args.timing) {
|
|
128
|
+
payload.timing = args.timing;
|
|
129
|
+
}
|
|
130
|
+
if (args.edits) {
|
|
131
|
+
payload.revision_mode = args.edits.revision_mode;
|
|
132
|
+
if (args.edits.revision_mode === "edits") {
|
|
133
|
+
payload.edits_attempted = args.edits.edits_attempted;
|
|
134
|
+
payload.edits_applied = args.edits.edits_applied;
|
|
135
|
+
payload.edits_failed = args.edits.edits_failed;
|
|
136
|
+
payload.edits_recovered = args.edits.edits_recovered;
|
|
137
|
+
payload.retry_invoked = args.edits.retry_invoked;
|
|
107
138
|
}
|
|
108
139
|
}
|
|
140
|
+
return {
|
|
141
|
+
content: [
|
|
142
|
+
{ type: "text", text: args.statusLine },
|
|
143
|
+
{ type: "text", text: JSON.stringify(payload) },
|
|
144
|
+
],
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
function errorResponse(error, extra = {}) {
|
|
109
148
|
return {
|
|
110
149
|
content: [
|
|
111
150
|
{
|
|
112
151
|
type: "text",
|
|
113
|
-
text:
|
|
114
|
-
},
|
|
115
|
-
{
|
|
116
|
-
type: "text",
|
|
117
|
-
text: JSON.stringify(payload),
|
|
152
|
+
text: JSON.stringify({ error, ...extra }),
|
|
118
153
|
},
|
|
119
154
|
],
|
|
155
|
+
isError: true,
|
|
120
156
|
};
|
|
121
157
|
}
|
|
122
158
|
export function registerRevise(server) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"revise.js","sourceRoot":"","sources":["../../../../src/mcp/tools/revise.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,
|
|
1
|
+
{"version":3,"file":"revise.js","sourceRoot":"","sources":["../../../../src/mcp/tools/revise.ts"],"names":[],"mappings":"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"}
|