planpong 0.5.7 → 0.6.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.
- package/README.md +47 -10
- package/dist/bin/planpong.js +3 -0
- package/dist/bin/planpong.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/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 +45 -32
- 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 +7 -1
- 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
|
@@ -3,9 +3,11 @@ import { readFileSync, writeFileSync } from "node:fs";
|
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
4
|
import { loadConfig } from "../../config/loader.js";
|
|
5
5
|
import { getProvider } from "../../providers/registry.js";
|
|
6
|
-
import { readSessionState, writeSessionState, readInitialPlan, } from "../../core/session.js";
|
|
7
|
-
import { runReviewRound, writeStatusLineToPlan, } from "../../core/operations.js";
|
|
6
|
+
import { readSessionState, writeSessionState, readInitialPlan, withSessionLock, } from "../../core/session.js";
|
|
7
|
+
import { runReviewRound, severityFromFeedback, writeStatusLineToPlan, formatPhaseExtras, phaseExtrasFromFeedback, } from "../../core/operations.js";
|
|
8
8
|
import { getReviewPhase } from "../../prompts/reviewer.js";
|
|
9
|
+
import { formatFeedbackDisplay } from "../../core/presentation.js";
|
|
10
|
+
import { getRoundState } from "../../core/round-state.js";
|
|
9
11
|
const inputSchema = {
|
|
10
12
|
session_id: z.string().describe("Session ID from planpong_start_review"),
|
|
11
13
|
cwd: z
|
|
@@ -15,8 +17,8 @@ const inputSchema = {
|
|
|
15
17
|
};
|
|
16
18
|
export async function getFeedbackHandler(input) {
|
|
17
19
|
const cwd = input.cwd ?? process.cwd();
|
|
18
|
-
const
|
|
19
|
-
if (!
|
|
20
|
+
const existing = readSessionState(cwd, input.session_id);
|
|
21
|
+
if (!existing) {
|
|
20
22
|
return {
|
|
21
23
|
content: [
|
|
22
24
|
{
|
|
@@ -29,76 +31,179 @@ export async function getFeedbackHandler(input) {
|
|
|
29
31
|
isError: true,
|
|
30
32
|
};
|
|
31
33
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
return {
|
|
53
|
-
content: [
|
|
54
|
-
{
|
|
55
|
-
type: "text",
|
|
56
|
-
text: JSON.stringify({
|
|
57
|
-
error: `Reviewer provider not found: ${session.reviewer.provider}`,
|
|
58
|
-
}),
|
|
59
|
-
},
|
|
60
|
-
],
|
|
61
|
-
isError: true,
|
|
34
|
+
return withSessionLock(cwd, input.session_id, async () => {
|
|
35
|
+
const session = readSessionState(cwd, input.session_id);
|
|
36
|
+
if (!session) {
|
|
37
|
+
return {
|
|
38
|
+
content: [
|
|
39
|
+
{
|
|
40
|
+
type: "text",
|
|
41
|
+
text: JSON.stringify({
|
|
42
|
+
error: `Session not found: ${input.session_id}`,
|
|
43
|
+
}),
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
isError: true,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
const config = loadConfig({ cwd });
|
|
50
|
+
const sessionConfig = {
|
|
51
|
+
...config,
|
|
52
|
+
reviewer: session.reviewer,
|
|
53
|
+
planner: session.planner,
|
|
62
54
|
};
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
55
|
+
const roundState = getRoundState(cwd, session, sessionConfig.max_rounds);
|
|
56
|
+
if (session.status !== "in_review") {
|
|
57
|
+
return {
|
|
58
|
+
content: [
|
|
59
|
+
{
|
|
60
|
+
type: "text",
|
|
61
|
+
text: JSON.stringify({
|
|
62
|
+
error: `Session status is '${session.status}', expected 'in_review'`,
|
|
63
|
+
}),
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
isError: true,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
if (roundState.inconsistentArtifacts) {
|
|
70
|
+
return {
|
|
71
|
+
content: [
|
|
72
|
+
{
|
|
73
|
+
type: "text",
|
|
74
|
+
text: JSON.stringify({
|
|
75
|
+
error: `Session ${session.id} has round ${session.currentRound} response without feedback`,
|
|
76
|
+
current_round: session.currentRound,
|
|
77
|
+
}),
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
isError: true,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
if (roundState.currentRound > 0 &&
|
|
84
|
+
roundState.latestFeedback &&
|
|
85
|
+
!roundState.latestResponse) {
|
|
86
|
+
return buildFeedbackResponse({
|
|
87
|
+
session,
|
|
88
|
+
cwd,
|
|
89
|
+
config: sessionConfig,
|
|
90
|
+
result: reviewResultFromFeedback(roundState.currentRound, roundState.latestFeedback),
|
|
91
|
+
idempotentReplay: true,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
if (roundState.currentRound > 0 &&
|
|
95
|
+
roundState.latestFeedback &&
|
|
96
|
+
roundState.latestResponse) {
|
|
97
|
+
if (roundState.currentRound >= sessionConfig.max_rounds) {
|
|
98
|
+
const statusLine = writeStatusLineToPlan(session, cwd, sessionConfig, "Max rounds reached");
|
|
99
|
+
return {
|
|
100
|
+
content: [
|
|
101
|
+
{ type: "text", text: statusLine },
|
|
102
|
+
{
|
|
103
|
+
type: "text",
|
|
104
|
+
text: JSON.stringify({
|
|
105
|
+
status: "max_rounds",
|
|
106
|
+
round: roundState.currentRound,
|
|
107
|
+
is_converged: false,
|
|
108
|
+
status_line: statusLine,
|
|
109
|
+
idempotent_replay: false,
|
|
110
|
+
}),
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
session.currentRound++;
|
|
116
|
+
writeSessionState(cwd, session);
|
|
117
|
+
}
|
|
118
|
+
else if (roundState.currentRound === 0) {
|
|
119
|
+
session.currentRound = 1;
|
|
120
|
+
writeSessionState(cwd, session);
|
|
121
|
+
}
|
|
122
|
+
// If currentRound > 0 and feedback is missing, this is an incomplete
|
|
123
|
+
// transition from a prior attempt. Retry the same round without
|
|
124
|
+
// incrementing.
|
|
125
|
+
// Use session-stored provider config
|
|
126
|
+
const reviewerProvider = getProvider(session.reviewer.provider);
|
|
127
|
+
if (!reviewerProvider) {
|
|
128
|
+
return {
|
|
129
|
+
content: [
|
|
130
|
+
{
|
|
131
|
+
type: "text",
|
|
132
|
+
text: JSON.stringify({
|
|
133
|
+
error: `Reviewer provider not found: ${session.reviewer.provider}`,
|
|
134
|
+
}),
|
|
135
|
+
},
|
|
136
|
+
],
|
|
137
|
+
isError: true,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
const result = await runReviewRound(session, cwd, sessionConfig, reviewerProvider);
|
|
141
|
+
return buildFeedbackResponse({
|
|
142
|
+
session,
|
|
143
|
+
cwd,
|
|
144
|
+
config: sessionConfig,
|
|
145
|
+
result,
|
|
146
|
+
idempotentReplay: false,
|
|
147
|
+
resumedIncompleteRound: roundState.incompleteTransition,
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
function reviewResultFromFeedback(round, feedback) {
|
|
152
|
+
const phase = getReviewPhase(round);
|
|
153
|
+
const severity = severityFromFeedback(feedback);
|
|
154
|
+
const phaseExtras = phaseExtrasFromFeedback(phase, feedback);
|
|
155
|
+
return {
|
|
156
|
+
round,
|
|
157
|
+
feedback,
|
|
158
|
+
severity,
|
|
159
|
+
converged: feedback.verdict !== "needs_revision",
|
|
160
|
+
phaseExtras,
|
|
69
161
|
};
|
|
70
|
-
|
|
71
|
-
|
|
162
|
+
}
|
|
163
|
+
function buildFeedbackResponse(args) {
|
|
164
|
+
const { session, cwd, config, result } = args;
|
|
72
165
|
const suffix = result.converged
|
|
73
166
|
? result.feedback.verdict === "blocked"
|
|
74
167
|
? `BLOCKED in ${getReviewPhase(result.round)} phase`
|
|
75
168
|
: `Approved after ${result.round} rounds`
|
|
76
169
|
: `Reviewed — ${result.feedback.issues.length} issues`;
|
|
77
|
-
const statusLine = writeStatusLineToPlan(session, cwd,
|
|
170
|
+
const statusLine = writeStatusLineToPlan(session, cwd, config, suffix, result.phaseExtras);
|
|
78
171
|
const phase = getReviewPhase(result.round);
|
|
172
|
+
const phaseSignal = formatPhaseExtras(phase, result.phaseExtras);
|
|
173
|
+
const display = formatFeedbackDisplay({
|
|
174
|
+
round: result.round,
|
|
175
|
+
phase,
|
|
176
|
+
verdict: result.feedback.verdict,
|
|
177
|
+
severity: result.severity,
|
|
178
|
+
feedback: result.feedback,
|
|
179
|
+
phaseSignal,
|
|
180
|
+
});
|
|
79
181
|
const response = {
|
|
80
182
|
round: result.round,
|
|
81
183
|
phase,
|
|
184
|
+
phase_label: phase,
|
|
82
185
|
verdict: result.feedback.verdict,
|
|
83
186
|
summary: result.feedback.summary,
|
|
84
187
|
issues: result.feedback.issues,
|
|
188
|
+
issue_rows: display.rows,
|
|
85
189
|
severity_counts: result.severity,
|
|
86
190
|
is_converged: result.converged,
|
|
87
191
|
status_line: statusLine,
|
|
192
|
+
display_markdown: display.markdown,
|
|
193
|
+
idempotent_replay: args.idempotentReplay,
|
|
88
194
|
};
|
|
195
|
+
if (args.resumedIncompleteRound) {
|
|
196
|
+
response.resumed_incomplete_round = true;
|
|
197
|
+
}
|
|
89
198
|
if (result.timing) {
|
|
90
199
|
response.timing = result.timing;
|
|
91
200
|
}
|
|
92
|
-
// Evidence-verification telemetry: surface the post-parse verifier's
|
|
93
|
-
// counts so consumers can spot reviewer hallucinations and sustained
|
|
94
|
-
// quote-compliance noncompliance without inspecting individual issues.
|
|
95
201
|
if (result.feedback.unverified_count !== undefined) {
|
|
96
202
|
response.unverified_count = result.feedback.unverified_count;
|
|
97
203
|
}
|
|
98
204
|
if (result.feedback.quote_compliance_warning) {
|
|
99
205
|
response.quote_compliance_warning = true;
|
|
100
206
|
}
|
|
101
|
-
// Phase-specific lean fields for status line consumption
|
|
102
207
|
if (result.phaseExtras.is_blocked) {
|
|
103
208
|
response.is_blocked = true;
|
|
104
209
|
}
|
|
@@ -128,7 +233,6 @@ export async function getFeedbackHandler(input) {
|
|
|
128
233
|
writeFileSync(planPath, planContent);
|
|
129
234
|
}
|
|
130
235
|
writeSessionState(cwd, session);
|
|
131
|
-
// Include initial plan for change summary
|
|
132
236
|
const initialPlan = readInitialPlan(cwd, session.id);
|
|
133
237
|
if (initialPlan) {
|
|
134
238
|
response.initial_plan = initialPlan;
|
|
@@ -138,14 +242,8 @@ export async function getFeedbackHandler(input) {
|
|
|
138
242
|
}
|
|
139
243
|
return {
|
|
140
244
|
content: [
|
|
141
|
-
{
|
|
142
|
-
|
|
143
|
-
text: statusLine,
|
|
144
|
-
},
|
|
145
|
-
{
|
|
146
|
-
type: "text",
|
|
147
|
-
text: JSON.stringify(response),
|
|
148
|
-
},
|
|
245
|
+
{ type: "text", text: statusLine },
|
|
246
|
+
{ type: "text", text: JSON.stringify(response) },
|
|
149
247
|
],
|
|
150
248
|
};
|
|
151
249
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-feedback.js","sourceRoot":"","sources":["../../../../src/mcp/tools/get-feedback.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,GAChB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,cAAc,
|
|
1
|
+
{"version":3,"file":"get-feedback.js","sourceRoot":"","sources":["../../../../src/mcp/tools/get-feedback.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,11 +10,5 @@ export declare function recordRevisionHandler(input: {
|
|
|
10
10
|
type: "text";
|
|
11
11
|
text: string;
|
|
12
12
|
}[];
|
|
13
|
-
isError: boolean;
|
|
14
|
-
} | {
|
|
15
|
-
content: {
|
|
16
|
-
type: "text";
|
|
17
|
-
text: string;
|
|
18
|
-
}[];
|
|
19
13
|
}>;
|
|
20
14
|
export declare function registerRecordRevision(server: McpServer): void;
|
|
@@ -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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"}
|