codecartographer-pi 0.10.0 → 0.12.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/.codecarto/GUIDE.md +40 -18
- package/.codecarto/README.md +3 -0
- package/.codecarto/findings/goal-synthesis/README.md +3 -0
- package/.codecarto/findings/goal-synthesis-finalize/SKILL.md +30 -0
- package/.codecarto/findings/goal-synthesis-propose/SKILL.md +24 -0
- package/.codecarto/findings/porting/SKILL.md +7 -0
- package/.codecarto/findings/reimplementation-spec/SKILL.md +10 -0
- package/.codecarto/findings/spec-merge/README.md +3 -0
- package/.codecarto/findings/spec-merge/SKILL.md +23 -0
- package/.codecarto/findings/vision-capture/README.md +3 -0
- package/.codecarto/findings/vision-capture/SKILL.md +26 -0
- package/.codecarto/inputs/vision.md +11 -0
- package/.codecarto/templates/architecture-map.md +9 -0
- package/.codecarto/templates/behavioral-contracts.md +9 -0
- package/.codecarto/templates/defect-report.md +9 -0
- package/.codecarto/templates/mechanical-defects.md +9 -0
- package/.codecarto/templates/merged-spec.md +58 -0
- package/.codecarto/templates/phase-checkpoint.md +41 -0
- package/.codecarto/templates/phase-handoff.yaml +22 -0
- package/.codecarto/templates/project-plan.md +70 -0
- package/.codecarto/templates/proposal.md +43 -0
- package/.codecarto/templates/protocols-and-state.md +9 -0
- package/.codecarto/templates/reimplementation-spec-opinionated.md +10 -0
- package/.codecarto/templates/reimplementation-spec.md +10 -0
- package/.codecarto/templates/reverse-engineering-bundle.md +29 -3
- package/.codecarto/templates/semantic-defects.md +9 -0
- package/.codecarto/templates/vision.md +63 -0
- package/.codecarto/workflow/pipeline-architecture-only.yaml +1 -0
- package/.codecarto/workflow/pipeline-defect-scan.yaml +2 -0
- package/.codecarto/workflow/pipeline-full-with-audit.yaml +8 -3
- package/.codecarto/workflow/pipeline-full-with-deep-audit.yaml +9 -5
- package/.codecarto/workflow/pipeline-lite.yaml +3 -0
- package/.codecarto/workflow/pipeline-synthesis.yaml +105 -0
- package/.codecarto/workflow/pipeline.yaml +7 -3
- package/.codecarto/workflow/status.yaml +2 -0
- package/README.md +89 -7
- package/dist/core/completion.d.ts +6 -0
- package/dist/core/completion.js +127 -0
- package/dist/core/dashboard.js +37 -7
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.js +2 -0
- package/dist/core/pipeline.js +1 -0
- package/dist/core/prompts.d.ts +9 -3
- package/dist/core/prompts.js +43 -26
- package/dist/core/status.d.ts +7 -1
- package/dist/core/status.js +187 -2
- package/dist/core/synthesis.d.ts +31 -0
- package/dist/core/synthesis.js +140 -0
- package/dist/core/types.d.ts +29 -1
- package/dist/core/usage.d.ts +11 -0
- package/dist/core/usage.js +64 -46
- package/dist/core/workspace.d.ts +3 -1
- package/dist/core/workspace.js +39 -3
- package/dist/core/yaml.js +24 -0
- package/dist/extensions/codecarto/agent-rewriter.js +0 -1
- package/dist/extensions/codecarto/agent-runner.d.ts +19 -0
- package/dist/extensions/codecarto/agent-runner.js +68 -6
- package/dist/extensions/codecarto/agent-state.d.ts +3 -0
- package/dist/extensions/codecarto/agent-state.js +2 -0
- package/dist/extensions/codecarto/agent-summary.d.ts +5 -0
- package/dist/extensions/codecarto/agent-summary.js +9 -0
- package/dist/extensions/codecarto/agent-widget.js +6 -0
- package/dist/extensions/codecarto/auto-runner.d.ts +3 -1
- package/dist/extensions/codecarto/auto-runner.js +33 -69
- package/dist/extensions/codecarto/dashboard-narrator.js +0 -1
- package/dist/extensions/codecarto/index.d.ts +1 -1
- package/dist/extensions/codecarto/index.js +153 -12
- package/dist/extensions/codecarto/phase-compaction.d.ts +11 -0
- package/dist/extensions/codecarto/phase-compaction.js +115 -0
- package/dist/mcp-server/server.js +24 -68
- package/package.json +4 -3
|
@@ -15,7 +15,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
15
15
|
import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError, } from "@modelcontextprotocol/sdk/types.js";
|
|
16
16
|
import { cp, mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
17
17
|
import { basename, isAbsolute, join } from "node:path";
|
|
18
|
-
import { buildPhasePrompt, buildSkillPrompt,
|
|
18
|
+
import { buildPhasePrompt, buildSkillPrompt, buildValidationSummary, canonicalPath, completeValidatedPhase, createEmptyStatus, DEFAULT_PIPELINE_PATH, deriveSlug, discoverLibrary, getNextEligiblePhase, getPipelineLabel, getWorkspaceState, isValidSlug, listEntries, listSkillNames, loadCodecartoConfig, loadYamlFile, normalizeForComparison, PACKAGE_VERSION, packagedWorkspaceDir, pathExists, PhasePreflightError, publishEntry, reindex as libraryReindex, resolvePhase, resolvePipelineChoice, stringifySimpleYaml, validatePhaseOutput, } from "../core/index.js";
|
|
19
19
|
// ---------- input helpers ----------
|
|
20
20
|
async function validateCwd(cwd) {
|
|
21
21
|
if (typeof cwd !== "string" || !cwd.trim()) {
|
|
@@ -46,6 +46,17 @@ function textResult(text, structured) {
|
|
|
46
46
|
result.structuredContent = structured;
|
|
47
47
|
return result;
|
|
48
48
|
}
|
|
49
|
+
async function buildMcpPhasePrompt(state, phase, forced) {
|
|
50
|
+
try {
|
|
51
|
+
return await buildPhasePrompt(state, phase, forced);
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
if (error instanceof PhasePreflightError) {
|
|
55
|
+
throw new McpError(ErrorCode.InvalidRequest, error.message);
|
|
56
|
+
}
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
49
60
|
// ---------- handlers ----------
|
|
50
61
|
export async function handleInit(args) {
|
|
51
62
|
const cwd = await validateCwd(args.cwd);
|
|
@@ -101,12 +112,16 @@ export async function handleStatus(args) {
|
|
|
101
112
|
const completed = state.pipeline.phase_order.filter((id) => state.status.phases[id]?.status === "complete").length;
|
|
102
113
|
const totalCarryForward = Object.values(state.status.phases).reduce((sum, phase) => sum + (phase.carry_forward?.length ?? 0), 0);
|
|
103
114
|
const currentOpenQuestions = currentPhase === "complete" ? 0 : state.status.phases[currentPhase]?.open_questions.length ?? 0;
|
|
115
|
+
const terminalOpenQuestions = Object.values(state.status.phases).reduce((sum, phase) => sum + (phase.open_questions?.length ?? 0), 0);
|
|
116
|
+
const postPipelinePending = state.status.post_pipeline.filter((entry) => entry.status !== "resolved").length;
|
|
104
117
|
const summary = [
|
|
105
118
|
`Phase: ${currentPhase}`,
|
|
119
|
+
`Pipeline state: ${currentPhase === "complete" ? "complete" : "in progress"}`,
|
|
106
120
|
`Pipeline: ${getPipelineLabel(state.status.pipeline)} (${state.status.pipeline})`,
|
|
107
121
|
`Progress: ${completed}/${state.pipeline.phase_order.length} complete`,
|
|
108
|
-
`Open questions (
|
|
109
|
-
`Carry-forward (
|
|
122
|
+
`Open questions (terminal unresolved): ${terminalOpenQuestions}`,
|
|
123
|
+
`Carry-forward (pipeline phases): ${totalCarryForward}`,
|
|
124
|
+
`Post-pipeline work: ${postPipelinePending} pending`,
|
|
110
125
|
`Next: ${state.status.next_actions[0] ?? (nextPhase ? `Begin ${nextPhase.id}` : "All phases complete.")}`,
|
|
111
126
|
].join("\n");
|
|
112
127
|
return textResult(summary, {
|
|
@@ -116,7 +131,9 @@ export async function handleStatus(args) {
|
|
|
116
131
|
completed,
|
|
117
132
|
total: state.pipeline.phase_order.length,
|
|
118
133
|
openQuestionsCurrentPhase: currentOpenQuestions,
|
|
134
|
+
openQuestionsTerminal: terminalOpenQuestions,
|
|
119
135
|
carryForwardTotal: totalCarryForward,
|
|
136
|
+
postPipelinePending,
|
|
120
137
|
nextActions: state.status.next_actions,
|
|
121
138
|
});
|
|
122
139
|
}
|
|
@@ -129,7 +146,7 @@ export async function handleNext(args) {
|
|
|
129
146
|
complete: true,
|
|
130
147
|
});
|
|
131
148
|
}
|
|
132
|
-
const prompt = await
|
|
149
|
+
const prompt = await buildMcpPhasePrompt(state, phase, false);
|
|
133
150
|
return textResult(prompt, { phase: phase.id, forced: false });
|
|
134
151
|
}
|
|
135
152
|
export async function handlePhase(args) {
|
|
@@ -142,7 +159,7 @@ export async function handlePhase(args) {
|
|
|
142
159
|
if (!phase) {
|
|
143
160
|
throw new McpError(ErrorCode.InvalidParams, `Unknown phase: ${args.phase}`);
|
|
144
161
|
}
|
|
145
|
-
const prompt = await
|
|
162
|
+
const prompt = await buildMcpPhasePrompt(state, phase, true);
|
|
146
163
|
return textResult(prompt, { phase: phase.id, forced: true });
|
|
147
164
|
}
|
|
148
165
|
export async function handleValidate(args) {
|
|
@@ -172,70 +189,9 @@ export async function handleComplete(args) {
|
|
|
172
189
|
if (validation.overall === "FAIL" || validation.overall === "MISSING") {
|
|
173
190
|
throw new McpError(ErrorCode.InvalidRequest, `Cannot complete ${validation.phaseId}: validation is ${validation.overall}.\n${buildValidationSummary(validation).join("\n")}`);
|
|
174
191
|
}
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
const phase = resolvePhase(lockedState, validation.phaseId);
|
|
178
|
-
if (!phase?.primary_output) {
|
|
179
|
-
throw new Error(`Phase ${validation.phaseId} is missing primary_output.`);
|
|
180
|
-
}
|
|
181
|
-
const nextStatus = normalizeStatus(lockedState.status, lockedState.pipeline, lockedState.status.pipeline, lockedState.cwd);
|
|
182
|
-
const existingPhase = nextStatus.phases[validation.phaseId] ?? {
|
|
183
|
-
status: "pending",
|
|
184
|
-
owner_notes: [],
|
|
185
|
-
outputs_present: [],
|
|
186
|
-
open_questions: [],
|
|
187
|
-
carry_forward: [],
|
|
188
|
-
};
|
|
189
|
-
const gapEntries = validation.rows
|
|
190
|
-
.filter((row) => row.result.toUpperCase().includes("PARTIAL"))
|
|
191
|
-
.map((row) => ({
|
|
192
|
-
kind: "needs-maintainer-decision",
|
|
193
|
-
description: row.criterion || "Partial validation gap",
|
|
194
|
-
deferred_reason: row.evidence || "Marked PARTIAL by validation",
|
|
195
|
-
}));
|
|
196
|
-
const mergedOpenQuestions = [...existingPhase.open_questions];
|
|
197
|
-
for (const candidate of gapEntries) {
|
|
198
|
-
const dupe = mergedOpenQuestions.some((entry) => entry.description === candidate.description && entry.deferred_reason === candidate.deferred_reason);
|
|
199
|
-
if (!dupe)
|
|
200
|
-
mergedOpenQuestions.push(candidate);
|
|
201
|
-
}
|
|
202
|
-
nextStatus.phases[validation.phaseId] = {
|
|
203
|
-
status: "complete",
|
|
204
|
-
owner_notes: uniqueStrings([
|
|
205
|
-
...existingPhase.owner_notes,
|
|
206
|
-
`Completed via codecarto_complete on ${completionTimestamp}.`,
|
|
207
|
-
`Primary output: .codecarto/${validation.primaryOutput}`,
|
|
208
|
-
`Validation: ${validation.overall}`,
|
|
209
|
-
]).slice(-3),
|
|
210
|
-
outputs_present: uniqueStrings([...existingPhase.outputs_present, validation.primaryOutput]),
|
|
211
|
-
open_questions: mergedOpenQuestions,
|
|
212
|
-
carry_forward: existingPhase.carry_forward ?? [],
|
|
213
|
-
};
|
|
214
|
-
nextStatus.last_updated = completionTimestamp;
|
|
215
|
-
const updatedWorkspaceState = {
|
|
216
|
-
...lockedState,
|
|
217
|
-
status: nextStatus,
|
|
218
|
-
};
|
|
219
|
-
const nextEligible = getNextEligiblePhase(updatedWorkspaceState);
|
|
220
|
-
nextStatus.current_phase = nextEligible?.id ?? "complete";
|
|
221
|
-
nextStatus.next_actions = nextEligible
|
|
222
|
-
? [`Begin ${nextEligible.id} phase by producing ${nextEligible.primary_output ?? `findings/${nextEligible.id}/`}`]
|
|
223
|
-
: ["All phases complete. Review findings, open questions, and downstream implementation notes."];
|
|
224
|
-
return {
|
|
225
|
-
state: { ...updatedWorkspaceState, status: nextStatus },
|
|
226
|
-
threadLogEntry: buildThreadLogEntry(validation.phaseId, validation, completionTimestamp),
|
|
227
|
-
};
|
|
192
|
+
const { updatedState, closeoutNotice } = await completeValidatedPhase(cwd, validation, "codecarto_complete").catch((error) => {
|
|
193
|
+
throw new McpError(ErrorCode.InvalidParams, error instanceof Error ? error.message : String(error));
|
|
228
194
|
});
|
|
229
|
-
let closeoutNotice;
|
|
230
|
-
try {
|
|
231
|
-
const created = await ensureCloseoutStub(updatedState.workspaceDir, validation.phaseId, completionTimestamp);
|
|
232
|
-
if (created) {
|
|
233
|
-
closeoutNotice = `Closeout stub created: .codecarto/closeouts/${closeoutFileName(dateOnly(completionTimestamp), validation.phaseId)} (fill it in)`;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
catch (error) {
|
|
237
|
-
closeoutNotice = `Closeout stub not created: ${error instanceof Error ? error.message : String(error)}`;
|
|
238
|
-
}
|
|
239
195
|
const lines = [
|
|
240
196
|
`Marked ${validation.phaseId} complete (validation: ${validation.overall}).`,
|
|
241
197
|
`Next phase: ${updatedState.status.current_phase}`,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codecartographer-pi",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "CodeCartographer packaged for Pi as an extension-driven workflow wrapper.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -37,13 +37,14 @@
|
|
|
37
37
|
"build": "tsc",
|
|
38
38
|
"prepublishOnly": "npm run build",
|
|
39
39
|
"test": "node --experimental-strip-types --disable-warning=ExperimentalWarning --test tests/*.test.mjs",
|
|
40
|
-
"smoke": "node scripts/smoke-mcp.mjs"
|
|
40
|
+
"smoke": "node scripts/smoke-mcp.mjs",
|
|
41
|
+
"demo:synthesis": "npm run build && node scripts/create-synthesis-demo.mjs"
|
|
41
42
|
},
|
|
42
43
|
"dependencies": {
|
|
43
44
|
"@modelcontextprotocol/sdk": "^1.29.0"
|
|
44
45
|
},
|
|
45
46
|
"peerDependencies": {
|
|
46
|
-
"@earendil-works/pi-coding-agent": "
|
|
47
|
+
"@earendil-works/pi-coding-agent": "^0.80.10",
|
|
47
48
|
"@sinclair/typebox": "*"
|
|
48
49
|
},
|
|
49
50
|
"pi": {
|