codecartographer-pi 0.20.0 → 0.21.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 +1 -1
- package/.codecarto/broadside/SKILL.md +7 -3
- package/.codecarto/broadside/config.yaml +17 -9
- package/.codecarto/findings/contracts/SKILL.md +4 -1
- package/.codecarto/findings/defect-scan/SKILL.md +10 -0
- package/.codecarto/findings/defect-scan-mechanical/SKILL.md +6 -0
- package/.codecarto/findings/defect-scan-semantic/SKILL.md +8 -1
- package/.codecarto/findings/porting/SKILL.md +4 -0
- package/.codecarto/findings/protocols/SKILL.md +4 -0
- package/.codecarto/templates/mechanical-defects.md +15 -0
- package/.codecarto/templates/reimplementation-spec.md +5 -3
- package/.codecarto/templates/reverse-engineering-bundle.md +10 -1
- package/.codecarto/templates/semantic-defects.md +15 -0
- package/.codecarto/workflow/VALIDATE.md +1 -1
- package/.codecarto/workflow/scaffold-version.yaml +1 -1
- package/README.md +3 -3
- package/dist/core/amendment.js +9 -4
- package/dist/core/broadside.d.ts +49 -0
- package/dist/core/broadside.js +131 -30
- package/dist/core/completion.js +7 -1
- package/dist/core/library.js +5 -3
- package/dist/core/pipeline.d.ts +39 -3
- package/dist/core/pipeline.js +61 -7
- package/dist/core/prompts.js +10 -3
- package/dist/core/status.d.ts +8 -0
- package/dist/core/status.js +39 -17
- package/dist/core/utils.d.ts +7 -0
- package/dist/core/utils.js +7 -0
- package/dist/core/workspace.js +2 -2
- package/dist/core/yaml.js +8 -1
- package/dist/extensions/codecarto/auto-runner.d.ts +1 -1
- package/dist/extensions/codecarto/auto-runner.js +18 -3
- package/dist/extensions/codecarto/broadside-flags.d.ts +3 -1
- package/dist/extensions/codecarto/broadside-flags.js +12 -0
- package/dist/extensions/codecarto/index.js +95 -31
- package/dist/extensions/codecarto/phase-compaction.js +5 -1
- package/dist/mcp-server/server.d.ts +3 -1
- package/dist/mcp-server/server.js +99 -29
- package/package.json +1 -1
|
@@ -17,7 +17,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
17
17
|
import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError, } from "@modelcontextprotocol/sdk/types.js";
|
|
18
18
|
import { mkdir, readFile, readdir, rename, writeFile } from "node:fs/promises";
|
|
19
19
|
import { basename, isAbsolute, join } from "node:path";
|
|
20
|
-
import { buildPhasePrompt, buildSkillPrompt, buildValidationSummary, BROADSIDE_DIR, broadsideDirFor, BROADSIDE_LENS_IDS, BROADSIDE_SKILL_NAME, backupWorkspaceState, canonicalPath, copyPackagedWorkspace, collectResultText, completeValidatedPhase, computePerPhaseTotals, computeTotals, createEmptyStatus, DEFAULT_PIPELINE_PATH, deriveSlug, discoverLibrary, describeScaffoldStaleness, detectProvenanceConflicts, estimateSubmitText, getLens, describeDanglingCarryForward, describeMissingCompletedOutputs,
|
|
20
|
+
import { buildPhasePrompt, buildSkillPrompt, buildValidationSummary, BROADSIDE_DIR, broadsideDirFor, BROADSIDE_LENS_IDS, BROADSIDE_SKILL_NAME, BroadsideConfigError, defaultBroadsideConfig, backupWorkspaceState, canonicalPath, copyPackagedWorkspace, collectResultText, completeValidatedPhase, computePerPhaseTotals, computeTotals, createEmptyStatus, DEFAULT_PIPELINE_PATH, deriveSlug, discoverLibrary, describeScaffoldStaleness, detectProvenanceConflicts, estimateSubmitText, getLens, describeDanglingCarryForward, describeMissingCompletedOutputs, describeStuckPipeline, getPipelineLabel, getWorkspaceState, isValidSlug, isWithinPathResolved, listBatchModels, listEntries, listGuideTopics, loadBroadsideConfig, modelsText, readGuide, listMissingCompletedOutputs, listSkillNames, resolvePipelineOutcome, resolveSkillName, loadCodecartoConfig, loadUsage, loadYamlFile, normalizeForComparison, PACKAGE_VERSION, packagedWorkspaceDir, pathExists, PhasePreflightError, previewPublishVersion, publishEntry, reindex as libraryReindex, refreshScaffold, resolvePhase, resolvePipelineChoice, readBroadsideSkill, runBroadsideCollect, runBroadsideStatus, runBroadsideSubmit, seedOrchestratorFiles, statusText, stringifySimpleYaml, switchPipeline, validatePhaseOutput, writeLibraryConfig, writeDashboard, } from "../core/index.js";
|
|
21
21
|
import { applyAmendment } from "../core/amendment.js";
|
|
22
22
|
import { appendUsageRun } from "../core/usage.js";
|
|
23
23
|
import { initLibrary } from "../core/library.js";
|
|
@@ -69,8 +69,12 @@ async function optionalCwd(cwd) {
|
|
|
69
69
|
return validateCwd(cwd.trim());
|
|
70
70
|
}
|
|
71
71
|
async function requireWorkspace(cwd) {
|
|
72
|
+
// What getWorkspaceState throws is the user's to fix — a status.yaml that
|
|
73
|
+
// does not parse, a missing `pipeline:`, a pipeline file that is not there
|
|
74
|
+
// — so it is InvalidRequest, not the InternalError a host would retry or
|
|
75
|
+
// report as a server bug (self-audit mech 2.8).
|
|
72
76
|
const state = await getWorkspaceState(cwd).catch((error) => {
|
|
73
|
-
throw new McpError(ErrorCode.
|
|
77
|
+
throw new McpError(ErrorCode.InvalidRequest, error instanceof Error ? error.message : String(error));
|
|
74
78
|
});
|
|
75
79
|
if (!state) {
|
|
76
80
|
throw new McpError(ErrorCode.InvalidRequest, `No CodeCartographer workspace at ${cwd}. Call codecarto_init first.`);
|
|
@@ -89,9 +93,9 @@ function textResult(text, structured) {
|
|
|
89
93
|
structuredContent: { ...structured, text },
|
|
90
94
|
};
|
|
91
95
|
}
|
|
92
|
-
async function buildMcpPhasePrompt(state, phase, forced) {
|
|
96
|
+
async function buildMcpPhasePrompt(state, phase, forced, auto = false) {
|
|
93
97
|
try {
|
|
94
|
-
return await buildPhasePrompt(state, phase, forced);
|
|
98
|
+
return await buildPhasePrompt(state, phase, forced, { auto });
|
|
95
99
|
}
|
|
96
100
|
catch (error) {
|
|
97
101
|
if (error instanceof PhasePreflightError) {
|
|
@@ -188,8 +192,11 @@ export async function handleInit(args) {
|
|
|
188
192
|
export async function handleStatus(args) {
|
|
189
193
|
const cwd = await validateCwd(args.cwd);
|
|
190
194
|
const state = await requireWorkspace(cwd);
|
|
191
|
-
const
|
|
192
|
-
const
|
|
195
|
+
const outcome = resolvePipelineOutcome(state);
|
|
196
|
+
const nextPhase = outcome.kind === "eligible" ? outcome.phase : null;
|
|
197
|
+
// "complete" is the terminal marker; a stuck pipeline sits on its first
|
|
198
|
+
// blocked phase and says so below (#228).
|
|
199
|
+
const currentPhase = outcome.kind === "eligible" ? outcome.phase.id : outcome.kind === "stuck" ? outcome.blocked[0].phaseId : "complete";
|
|
193
200
|
const completed = state.pipeline.phase_order.filter((id) => state.status.phases[id]?.status === "complete").length;
|
|
194
201
|
const totalCarryForward = Object.values(state.status.phases).reduce((sum, phase) => sum + (phase.carry_forward?.length ?? 0), 0);
|
|
195
202
|
const currentOpenQuestions = currentPhase === "complete" ? 0 : state.status.phases[currentPhase]?.open_questions?.length ?? 0;
|
|
@@ -199,7 +206,7 @@ export async function handleStatus(args) {
|
|
|
199
206
|
const missingOutputs = await listMissingCompletedOutputs(state);
|
|
200
207
|
const summaryLines = [
|
|
201
208
|
`Phase: ${currentPhase}`,
|
|
202
|
-
`Pipeline state: ${
|
|
209
|
+
`Pipeline state: ${outcome.kind === "eligible" ? "in progress" : outcome.kind}`,
|
|
203
210
|
`Pipeline: ${getPipelineLabel(state.status.pipeline)} (${state.status.pipeline})`,
|
|
204
211
|
`Progress: ${completed}/${state.pipeline.phase_order.length} complete`,
|
|
205
212
|
`Open questions (terminal unresolved): ${terminalOpenQuestions}`,
|
|
@@ -212,6 +219,8 @@ export async function handleStatus(args) {
|
|
|
212
219
|
? state.status.next_actions.map((action, index) => `${index === 0 ? "Next: " : " "}${action}`)
|
|
213
220
|
: [`Next: ${nextPhase ? `Begin ${nextPhase.id}` : "All phases complete."}`]),
|
|
214
221
|
];
|
|
222
|
+
if (outcome.kind === "stuck")
|
|
223
|
+
summaryLines.push(describeStuckPipeline(outcome.blocked));
|
|
215
224
|
if (scaffoldNotice)
|
|
216
225
|
summaryLines.push(`Scaffold: ${scaffoldNotice}`);
|
|
217
226
|
summaryLines.push(...describeMissingCompletedOutputs(missingOutputs));
|
|
@@ -219,6 +228,8 @@ export async function handleStatus(args) {
|
|
|
219
228
|
return textResult(summary, {
|
|
220
229
|
...(scaffoldNotice ? { scaffoldNotice } : {}),
|
|
221
230
|
...(missingOutputs.length > 0 ? { missingOutputs } : {}),
|
|
231
|
+
...(outcome.kind === "stuck" ? { stuck: outcome.blocked } : {}),
|
|
232
|
+
pipelineState: outcome.kind === "eligible" ? "in progress" : outcome.kind,
|
|
222
233
|
currentPhase,
|
|
223
234
|
pipeline: state.status.pipeline,
|
|
224
235
|
pipelineLabel: getPipelineLabel(state.status.pipeline),
|
|
@@ -271,14 +282,24 @@ export async function handleSwitchPipeline(args) {
|
|
|
271
282
|
export async function handleNext(args) {
|
|
272
283
|
const cwd = await validateCwd(args.cwd);
|
|
273
284
|
const state = await requireWorkspace(cwd);
|
|
274
|
-
const
|
|
275
|
-
if (
|
|
285
|
+
const outcome = resolvePipelineOutcome(state);
|
|
286
|
+
if (outcome.kind === "stuck") {
|
|
287
|
+
// Not a result: a host looping on codecarto_next would read a text
|
|
288
|
+
// answer as "done" (#228). There is no prompt to hand out until the
|
|
289
|
+
// pipeline file is fixed.
|
|
290
|
+
throw new McpError(ErrorCode.InvalidRequest, describeStuckPipeline(outcome.blocked));
|
|
291
|
+
}
|
|
292
|
+
if (outcome.kind === "complete") {
|
|
276
293
|
return textResult("All CodeCartographer phases are complete. Run codecarto_skill for post-pipeline work.", {
|
|
277
294
|
complete: true,
|
|
278
295
|
});
|
|
279
296
|
}
|
|
280
|
-
|
|
281
|
-
|
|
297
|
+
// `unattended` is the MCP spelling of Pi's --auto: nobody is there to
|
|
298
|
+
// answer the reimplementation-spec phase's Strategic Alignment Hook, so
|
|
299
|
+
// the prompt carries the auto-default instruction instead (#270).
|
|
300
|
+
const unattended = args.unattended === true;
|
|
301
|
+
const prompt = await buildMcpPhasePrompt(state, outcome.phase, false, unattended);
|
|
302
|
+
return textResult(prompt, { phase: outcome.phase.id, forced: false, unattended });
|
|
282
303
|
}
|
|
283
304
|
export async function handlePhase(args) {
|
|
284
305
|
if (typeof args.phase !== "string" || !args.phase.trim()) {
|
|
@@ -290,8 +311,9 @@ export async function handlePhase(args) {
|
|
|
290
311
|
if (!phase) {
|
|
291
312
|
throw new McpError(ErrorCode.InvalidParams, `Unknown phase: ${args.phase}`);
|
|
292
313
|
}
|
|
293
|
-
const
|
|
294
|
-
|
|
314
|
+
const unattended = args.unattended === true;
|
|
315
|
+
const prompt = await buildMcpPhasePrompt(state, phase, true, unattended);
|
|
316
|
+
return textResult(prompt, { phase: phase.id, forced: true, unattended });
|
|
295
317
|
}
|
|
296
318
|
export async function handleValidate(args) {
|
|
297
319
|
const cwd = await validateCwd(args.cwd);
|
|
@@ -391,9 +413,12 @@ export async function handleSkill(args) {
|
|
|
391
413
|
return textResult(skill.content, { skill: BROADSIDE_SKILL_NAME, path: skill.path, postPipeline: false });
|
|
392
414
|
}
|
|
393
415
|
const state = await requireWorkspace(cwd);
|
|
394
|
-
const
|
|
395
|
-
if (
|
|
396
|
-
throw new McpError(ErrorCode.InvalidRequest, `Cannot run skill: pipeline is not complete (next phase: ${
|
|
416
|
+
const outcome = resolvePipelineOutcome(state);
|
|
417
|
+
if (outcome.kind === "eligible") {
|
|
418
|
+
throw new McpError(ErrorCode.InvalidRequest, `Cannot run skill: pipeline is not complete (next phase: ${outcome.phase.id}). Finish the pipeline first.`);
|
|
419
|
+
}
|
|
420
|
+
if (outcome.kind === "stuck") {
|
|
421
|
+
throw new McpError(ErrorCode.InvalidRequest, `Cannot run skill: the pipeline is not complete. ${describeStuckPipeline(outcome.blocked)}`);
|
|
397
422
|
}
|
|
398
423
|
// Resolve against the installed list only: the name is never joined onto a
|
|
399
424
|
// path, so a traversal like `../findings/architecture` cannot splice a
|
|
@@ -883,8 +908,16 @@ export async function handleOpen(args) {
|
|
|
883
908
|
throw new McpError(ErrorCode.InvalidRequest, "No existing CodeCartographer workspace found. Run codecarto_init first.");
|
|
884
909
|
}
|
|
885
910
|
const state = await requireWorkspace(cwd);
|
|
886
|
-
const
|
|
887
|
-
|
|
911
|
+
const outcome = resolvePipelineOutcome(state);
|
|
912
|
+
const nextPhase = outcome.kind === "eligible" ? outcome.phase.id : outcome.kind === "stuck" ? `${outcome.blocked[0].phaseId} (stuck)` : "complete";
|
|
913
|
+
const lines = [`Opened existing CodeCartographer workspace: ${getPipelineLabel(state.status.pipeline)}. Current phase: ${nextPhase}.`];
|
|
914
|
+
if (outcome.kind === "stuck")
|
|
915
|
+
lines.push(describeStuckPipeline(outcome.blocked));
|
|
916
|
+
return textResult(lines.join("\n"), {
|
|
917
|
+
pipeline: getPipelineLabel(state.status.pipeline),
|
|
918
|
+
currentPhase: nextPhase,
|
|
919
|
+
...(outcome.kind === "stuck" ? { stuck: outcome.blocked } : {}),
|
|
920
|
+
});
|
|
888
921
|
}
|
|
889
922
|
export async function handleUsage(args) {
|
|
890
923
|
const cwd = await validateCwd(args.cwd);
|
|
@@ -1007,18 +1040,40 @@ export async function handleBroadside(args) {
|
|
|
1007
1040
|
if (!["submit", "collect", "status", "models"].includes(action)) {
|
|
1008
1041
|
throw new McpError(ErrorCode.InvalidParams, `Unknown action: ${action}. Valid actions: submit, collect, status, models.`);
|
|
1009
1042
|
}
|
|
1010
|
-
|
|
1043
|
+
// A config.yaml that exists but cannot be read refuses every action that
|
|
1044
|
+
// would act on it (#232); status only reads recorded runs, so it answers
|
|
1045
|
+
// and says the file is unreadable. A corrupt state.json refuses even that:
|
|
1046
|
+
// there is nothing trustworthy to report and nothing may write over it (#233).
|
|
1047
|
+
let config;
|
|
1048
|
+
let configWarning = null;
|
|
1049
|
+
try {
|
|
1050
|
+
config = await loadBroadsideConfig(broadsideDirFor(cwd));
|
|
1051
|
+
}
|
|
1052
|
+
catch (error) {
|
|
1053
|
+
if (!(error instanceof BroadsideConfigError) || action !== "status") {
|
|
1054
|
+
throw new McpError(ErrorCode.InvalidRequest, error instanceof Error ? error.message : String(error));
|
|
1055
|
+
}
|
|
1056
|
+
config = defaultBroadsideConfig();
|
|
1057
|
+
configWarning = error.message;
|
|
1058
|
+
}
|
|
1011
1059
|
if (action === "status") {
|
|
1012
|
-
const { state } = await runBroadsideStatus(cwd)
|
|
1013
|
-
|
|
1060
|
+
const { state } = await runBroadsideStatus(cwd).catch((error) => {
|
|
1061
|
+
throw new McpError(ErrorCode.InvalidRequest, error instanceof Error ? error.message : String(error));
|
|
1062
|
+
});
|
|
1063
|
+
const lines = [statusText(state)];
|
|
1064
|
+
if (configWarning)
|
|
1065
|
+
lines.push(`Warning: ${configWarning}`);
|
|
1066
|
+
return textResult(lines.join("\n"), { state, ...(configWarning ? { configWarning } : {}) });
|
|
1014
1067
|
}
|
|
1015
1068
|
const apiKey = resolveBroadsideApiKey(args.api_key, config);
|
|
1016
1069
|
// Every run knob resolves the same way: explicit parameter, else the repo's
|
|
1017
1070
|
// config.yaml default, else the shipped default baked into loadBroadsideConfig.
|
|
1018
|
-
|
|
1071
|
+
// An explicit 0 means "poll once and return": it used to fall through to
|
|
1072
|
+
// the config default and, as undefined, to the 25-minute budget (#230).
|
|
1073
|
+
const waitSeconds = typeof args.wait_seconds === "number" && args.wait_seconds >= 0
|
|
1019
1074
|
? args.wait_seconds
|
|
1020
1075
|
: config.waitSeconds;
|
|
1021
|
-
const waitMs = waitSeconds
|
|
1076
|
+
const waitMs = waitSeconds * 1000;
|
|
1022
1077
|
const includeSynthesis = args.include_synthesis ?? config.includeSynthesis;
|
|
1023
1078
|
const includeTriage = args.include_triage ?? config.includeTriage;
|
|
1024
1079
|
const retryTruncated = args.retry_truncated ?? config.retryTruncated;
|
|
@@ -1047,7 +1102,9 @@ export async function handleBroadside(args) {
|
|
|
1047
1102
|
else {
|
|
1048
1103
|
lenses = config.defaultLenses;
|
|
1049
1104
|
}
|
|
1050
|
-
|
|
1105
|
+
// An explicit 0 is "no limit" (#231); absent falls back to config.yaml,
|
|
1106
|
+
// whose own default is BROADSIDE_DEFAULT_MAX_COST.
|
|
1107
|
+
const maxCost = typeof args.max_cost === "number" && args.max_cost >= 0 ? args.max_cost : config.maxCost;
|
|
1051
1108
|
const result = await runBroadsideSubmit(cwd, apiKey, {
|
|
1052
1109
|
lenses,
|
|
1053
1110
|
model: config.model,
|
|
@@ -1084,11 +1141,13 @@ export async function handleBroadside(args) {
|
|
|
1084
1141
|
});
|
|
1085
1142
|
}
|
|
1086
1143
|
// action === "collect"
|
|
1144
|
+
const runId = typeof args.run_id === "string" && args.run_id.trim() ? args.run_id.trim() : undefined;
|
|
1087
1145
|
const collect = await runBroadsideCollect(cwd, apiKey, {
|
|
1088
1146
|
waitMs,
|
|
1089
1147
|
includeSynthesis,
|
|
1090
1148
|
includeTriage,
|
|
1091
1149
|
retryTruncated,
|
|
1150
|
+
...(runId && { runId }),
|
|
1092
1151
|
}).catch((error) => {
|
|
1093
1152
|
throw new McpError(ErrorCode.InvalidRequest, error instanceof Error ? error.message : String(error));
|
|
1094
1153
|
});
|
|
@@ -1156,7 +1215,13 @@ const TOOLS = [
|
|
|
1156
1215
|
description: "Return the prompt text for the next eligible CodeCartographer phase. The host should feed this prompt back to the agent or display it to the user.",
|
|
1157
1216
|
inputSchema: {
|
|
1158
1217
|
type: "object",
|
|
1159
|
-
properties: {
|
|
1218
|
+
properties: {
|
|
1219
|
+
cwd: { type: "string", description: "Absolute path to the target repository." },
|
|
1220
|
+
unattended: {
|
|
1221
|
+
type: "boolean",
|
|
1222
|
+
description: "Set when no user is in the loop to answer the prompt's questions (an autonomous run). The reimplementation-spec prompt then defaults to the language-agnostic variant and records selection: auto-default instead of asking which variant to build, and every interactive hook is suppressed. Same as Pi's /codecarto-next --auto.",
|
|
1223
|
+
},
|
|
1224
|
+
},
|
|
1160
1225
|
required: ["cwd"],
|
|
1161
1226
|
},
|
|
1162
1227
|
},
|
|
@@ -1168,6 +1233,7 @@ const TOOLS = [
|
|
|
1168
1233
|
properties: {
|
|
1169
1234
|
cwd: { type: "string", description: "Absolute path to the target repository." },
|
|
1170
1235
|
phase: { type: "string", description: "Phase id from the active pipeline." },
|
|
1236
|
+
unattended: { type: "boolean", description: "As for codecarto_next: no user is in the loop, so interactive hooks default and record their choice instead of asking." },
|
|
1171
1237
|
},
|
|
1172
1238
|
required: ["cwd", "phase"],
|
|
1173
1239
|
},
|
|
@@ -1186,7 +1252,7 @@ const TOOLS = [
|
|
|
1186
1252
|
},
|
|
1187
1253
|
{
|
|
1188
1254
|
name: "codecarto_complete",
|
|
1189
|
-
description: "Mark a phase complete. Requires the phase output's validation to be PASS or PASS WITH GAPS. Atomically updates status.yaml under a file lock, appends
|
|
1255
|
+
description: "Mark a phase complete. Requires the phase output's validation to be PASS or PASS WITH GAPS and applies the phase handoff at scratch/handoffs/<phase>.yaml. Atomically updates status.yaml under a file lock, appends one THREAD_LOG.md entry, and writes the phase's closeout: the handoff's closeout_content (plus its decisions) overwrites the canonical <date>-<phase>.md when supplied; otherwise a stub is copied from the template only if no closeout exists yet. If phase is omitted, completes the next eligible phase.",
|
|
1190
1256
|
inputSchema: {
|
|
1191
1257
|
type: "object",
|
|
1192
1258
|
properties: {
|
|
@@ -1412,11 +1478,15 @@ const TOOLS = [
|
|
|
1412
1478
|
},
|
|
1413
1479
|
api_key: {
|
|
1414
1480
|
type: "string",
|
|
1415
|
-
description: "OpenRouter API key.
|
|
1481
|
+
description: "OpenRouter API key. A value passed here is recorded wherever the host logs tool calls; prefer the OPENROUTER_API_KEY environment variable of the server process. (api_key in .codecarto/broadside/config.yaml also works, but that file is tracked, so a key there is committed with it.)",
|
|
1482
|
+
},
|
|
1483
|
+
run_id: {
|
|
1484
|
+
type: "string",
|
|
1485
|
+
description: "For collect: the run to collect, as listed by the status action. Defaults to the most recent run; pass this to collect an older run that is still in flight after a newer submit.",
|
|
1416
1486
|
},
|
|
1417
1487
|
wait_seconds: {
|
|
1418
1488
|
type: "number",
|
|
1419
|
-
description: "For submit: after submitting, poll up to this many seconds before returning. For collect: poll up to this many seconds before returning with partial state. Falls back to wait_seconds in .codecarto/broadside/config.yaml.",
|
|
1489
|
+
description: "For submit: after submitting, poll up to this many seconds before returning. For collect: poll up to this many seconds before returning with partial state. 0 polls each in-flight batch once and returns without waiting. Falls back to wait_seconds in .codecarto/broadside/config.yaml (default 0).",
|
|
1420
1490
|
},
|
|
1421
1491
|
include_synthesis: {
|
|
1422
1492
|
type: "boolean",
|
|
@@ -1432,7 +1502,7 @@ const TOOLS = [
|
|
|
1432
1502
|
},
|
|
1433
1503
|
max_cost: {
|
|
1434
1504
|
type: "number",
|
|
1435
|
-
description: "Approximate run expense limit in USD. The submit action estimates the run cost from slice sizes and the configured model's per-token pricing (live OpenRouter lookup, cached 24h) and refuses to submit when the estimate exceeds the limit unless force is true. Falls back to max_cost in .codecarto/broadside/config.yaml.",
|
|
1505
|
+
description: "Approximate run expense limit in USD. The submit action estimates the run cost from slice sizes and the configured model's per-token pricing (live OpenRouter lookup, cached 24h) and refuses to submit when the estimate exceeds the limit unless force is true. Falls back to max_cost in .codecarto/broadside/config.yaml, whose default is $1.00; pass 0 for no limit.",
|
|
1436
1506
|
},
|
|
1437
1507
|
force: {
|
|
1438
1508
|
type: "boolean",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codecartographer-pi",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"mcpName": "io.github.HuginnIndustries/codecartographer",
|
|
5
5
|
"description": "Turn an unfamiliar codebase into a validated reimplementation spec, then synthesize confirmed specs and a product vision into a traceable plan.",
|
|
6
6
|
"type": "module",
|