codecartographer-pi 0.20.0 → 0.22.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 +15 -4
- package/.codecarto/broadside/config.yaml +26 -10
- 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 +5 -5
- package/agent-skill/codecartographer/references/broadside.md +10 -0
- package/dist/core/amendment.js +9 -4
- package/dist/core/broadside.d.ts +98 -0
- package/dist/core/broadside.js +330 -63
- 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 +7 -1
- package/dist/extensions/codecarto/broadside-flags.js +51 -0
- package/dist/extensions/codecarto/index.js +103 -35
- package/dist/extensions/codecarto/phase-compaction.js +5 -1
- package/dist/mcp-server/server.d.ts +5 -1
- package/dist/mcp-server/server.js +140 -32
- package/package.json +1 -1
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
2
|
-
import { homedir } from "node:os";
|
|
3
2
|
import { basename, dirname, join, resolve } from "node:path";
|
|
4
3
|
import { autoCompletePhase, buildAutoSummary, isPhaseRunning, runAuto, runSinglePhase } from "./auto-runner.js";
|
|
5
4
|
import { disposeAgentsWidget } from "./agent-widget.js";
|
|
@@ -10,7 +9,7 @@ import { parseNextFlags } from "./next-flags.js";
|
|
|
10
9
|
import { buildPiGuideMessage } from "./guide-framing.js";
|
|
11
10
|
import { isCtxLive, notifyCtx } from "./notify.js";
|
|
12
11
|
import { phaseCompactionExtension } from "./phase-compaction.js";
|
|
13
|
-
import { applyAmendment, buildPhasePrompt, buildSkillPrompt, buildValidationSummary, backupWorkspaceState, canonicalPath, copyPackagedWorkspace, computePerPhaseTotals, computeTotals, ConfidentialityMismatchError, createEmptyStatus, DEFAULT_PIPELINE_PATH, describeScaffoldStaleness, deriveSlug, discoverLibrary, describeDanglingCarryForward, describeMissingCompletedOutputs,
|
|
12
|
+
import { applyAmendment, buildPhasePrompt, buildSkillPrompt, buildValidationSummary, backupWorkspaceState, canonicalPath, copyPackagedWorkspace, computePerPhaseTotals, computeTotals, ConfidentialityMismatchError, createEmptyStatus, DEFAULT_PIPELINE_PATH, describeScaffoldStaleness, deriveSlug, discoverLibrary, describeDanglingCarryForward, describeMissingCompletedOutputs, describeStuckPipeline, expandTilde, getPipelineLabel, getWorkspaceState, isWithinPath, resolveExistingPrefix, BROADSIDE_LENS_IDS, BROADSIDE_SKILL_NAME, BroadsideConfigError, defaultBroadsideConfig, BroadsideCancelledError, broadsideDirFor, collectResultText, estimateSubmitText, getLens, listAmendmentNames, listBatchModels, listGuideTopics, listScaffoldRefreshFiles, listMissingCompletedOutputs, listSkillNames, resolvePipelineOutcome, resolveSkillName, loadAmendmentFile, loadBroadsideConfig, modelsText, runBroadsideCollect, runBroadsideStatus, runBroadsideSubmit, statusText, describeConfigProblems, loadCodecartoConfig, loadUsage, loadYamlFile, normalizeForComparison, packagedWorkspaceDir, pathExists, PACKAGE_VERSION, readBroadsideSkill, readGuide, refreshScaffold, PhasePreflightError, PIPELINE_ALIASES, publishEntry, resolvePhase, resolvePipelineChoice, resolvePublishSourceRepo, SourceRepoMismatchError, runPhasePreflight, SCAFFOLD_REFRESH_PROTECTED, seedOrchestratorFiles, stringifySimpleYaml, switchPipeline, validatePhaseOutput, writeLibraryConfig, writeDashboard, } from "../../core/index.js";
|
|
14
13
|
import { initLibrary } from "../../core/library.js";
|
|
15
14
|
import { resolveUserConfigPath } from "../../core/orchestrator-config.js";
|
|
16
15
|
const STATUS_WIDGET_ID = "codecarto-widget";
|
|
@@ -56,9 +55,23 @@ function formatUsageDuration(ms) {
|
|
|
56
55
|
const seconds = Math.floor((ms % 60_000) / 1000);
|
|
57
56
|
return `${minutes}m${seconds.toString().padStart(2, "0")}s`;
|
|
58
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* The phase the status line and session name show: the eligible phase, the
|
|
60
|
+
* first blocked phase when the pipeline is stuck, or "complete" — never
|
|
61
|
+
* "complete" for a pipeline that cannot finish (#228).
|
|
62
|
+
*/
|
|
63
|
+
function currentPhaseLabel(state) {
|
|
64
|
+
const outcome = resolvePipelineOutcome(state);
|
|
65
|
+
if (outcome.kind === "eligible")
|
|
66
|
+
return outcome.phase.id;
|
|
67
|
+
if (outcome.kind === "stuck")
|
|
68
|
+
return outcome.blocked[0]?.phaseId ?? "stuck";
|
|
69
|
+
return "complete";
|
|
70
|
+
}
|
|
59
71
|
function buildStatusLines(state, extraLines = []) {
|
|
60
|
-
const
|
|
61
|
-
const
|
|
72
|
+
const outcome = resolvePipelineOutcome(state);
|
|
73
|
+
const nextPhase = outcome.kind === "eligible" ? outcome.phase : null;
|
|
74
|
+
const currentPhase = currentPhaseLabel(state);
|
|
62
75
|
const pipelineLabel = getPipelineLabel(state.status.pipeline);
|
|
63
76
|
const completedCount = state.pipeline.phase_order.filter((phaseId) => state.status.phases[phaseId]?.status === "complete").length;
|
|
64
77
|
const terminalOpenQuestions = Object.values(state.status.phases).reduce((sum, phase) => sum + (phase.open_questions?.length ?? 0), 0);
|
|
@@ -68,7 +81,7 @@ function buildStatusLines(state, extraLines = []) {
|
|
|
68
81
|
const lines = [
|
|
69
82
|
"CodeCartographer",
|
|
70
83
|
`Phase: ${currentPhase}`,
|
|
71
|
-
`Pipeline state: ${
|
|
84
|
+
`Pipeline state: ${outcome.kind === "eligible" ? "in progress" : outcome.kind}`,
|
|
72
85
|
`Pipeline: ${pipelineLabel}`,
|
|
73
86
|
`Progress: ${completedCount}/${state.pipeline.phase_order.length} complete`,
|
|
74
87
|
`Open questions (terminal unresolved): ${terminalOpenQuestions}`,
|
|
@@ -76,6 +89,8 @@ function buildStatusLines(state, extraLines = []) {
|
|
|
76
89
|
`Post-pipeline work: ${postPipelinePending} pending`,
|
|
77
90
|
`Next: ${nextAction}`,
|
|
78
91
|
];
|
|
92
|
+
if (outcome.kind === "stuck")
|
|
93
|
+
lines.push(describeStuckPipeline(outcome.blocked));
|
|
79
94
|
const scaffoldNotice = describeScaffoldStaleness(state);
|
|
80
95
|
if (scaffoldNotice)
|
|
81
96
|
lines.push(`Scaffold: ${scaffoldNotice}`);
|
|
@@ -93,7 +108,7 @@ function setUiState(ctx, state, extraLines = []) {
|
|
|
93
108
|
return;
|
|
94
109
|
}
|
|
95
110
|
const theme = ctx.ui.theme;
|
|
96
|
-
const currentPhase =
|
|
111
|
+
const currentPhase = currentPhaseLabel(state);
|
|
97
112
|
ctx.ui.setStatus(STATUS_LINE_ID, `${theme.fg("accent", "CC")} ${theme.fg("dim", currentPhase)}`);
|
|
98
113
|
ctx.ui.setWidget(STATUS_WIDGET_ID, buildStatusLines(state, extraLines));
|
|
99
114
|
}
|
|
@@ -291,7 +306,7 @@ export default function codeCartographerExtension(pi) {
|
|
|
291
306
|
const state = await readWorkspaceState(ctx, false);
|
|
292
307
|
setUiState(ctx, state, extraLines ?? lastFeedbackLines);
|
|
293
308
|
if (state) {
|
|
294
|
-
const phaseId =
|
|
309
|
+
const phaseId = currentPhaseLabel(state);
|
|
295
310
|
if (phaseId)
|
|
296
311
|
pi.setSessionName(`CodeCartographer: ${phaseId}`);
|
|
297
312
|
}
|
|
@@ -498,13 +513,17 @@ export default function codeCartographerExtension(pi) {
|
|
|
498
513
|
const state = await ensureWorkspaceState(ctx);
|
|
499
514
|
if (!state)
|
|
500
515
|
return;
|
|
501
|
-
const
|
|
516
|
+
const outcome = resolvePipelineOutcome(state);
|
|
517
|
+
const nextPhase = currentPhaseLabel(state);
|
|
502
518
|
// Same check codecarto_status makes: a phase complete in status.yaml
|
|
503
519
|
// whose report is not on disk (#259).
|
|
504
520
|
const missingOutputs = describeMissingCompletedOutputs(await listMissingCompletedOutputs(state));
|
|
505
521
|
lastFeedbackLines = [`Current phase: ${nextPhase}`, `Pipeline: ${getPipelineLabel(state.status.pipeline)}`, ...missingOutputs];
|
|
506
522
|
setUiState(ctx, state, lastFeedbackLines);
|
|
507
|
-
if (
|
|
523
|
+
if (outcome.kind === "stuck") {
|
|
524
|
+
notifyCtx(ctx, `CodeCartographer phase: ${nextPhase}. ${describeStuckPipeline(outcome.blocked)}`, "error");
|
|
525
|
+
}
|
|
526
|
+
else if (missingOutputs.length > 0) {
|
|
508
527
|
notifyCtx(ctx, `CodeCartographer phase: ${nextPhase}. ${missingOutputs[0]}`, "warning");
|
|
509
528
|
}
|
|
510
529
|
else {
|
|
@@ -608,7 +627,7 @@ export default function codeCartographerExtension(pi) {
|
|
|
608
627
|
// the readout tracks progress live instead of staying frozen
|
|
609
628
|
// at the initial phase until the whole auto run finishes.
|
|
610
629
|
setUiState(ctx, advancedState, [`Auto pipeline${flags.strict ? " (strict)" : ""} running…`]);
|
|
611
|
-
const phaseId =
|
|
630
|
+
const phaseId = currentPhaseLabel(advancedState);
|
|
612
631
|
if (phaseId)
|
|
613
632
|
pi.setSessionName(`CodeCartographer: ${phaseId}`);
|
|
614
633
|
},
|
|
@@ -624,13 +643,21 @@ export default function codeCartographerExtension(pi) {
|
|
|
624
643
|
notifyCtx(ctx, `Auto pipeline ${result.outcome}: ${result.phasesRun.length}/${result.totalPhases} phases.`, result.outcome === "complete" ? "info" : "warning");
|
|
625
644
|
return;
|
|
626
645
|
}
|
|
627
|
-
const
|
|
628
|
-
if (
|
|
646
|
+
const outcome = resolvePipelineOutcome(state);
|
|
647
|
+
if (outcome.kind === "stuck") {
|
|
648
|
+
const message = describeStuckPipeline(outcome.blocked);
|
|
649
|
+
lastFeedbackLines = [message];
|
|
650
|
+
setUiState(ctx, state, lastFeedbackLines);
|
|
651
|
+
notifyCtx(ctx, message, "error");
|
|
652
|
+
return;
|
|
653
|
+
}
|
|
654
|
+
if (outcome.kind === "complete") {
|
|
629
655
|
lastFeedbackLines = ["All phases complete."];
|
|
630
656
|
setUiState(ctx, state, lastFeedbackLines);
|
|
631
657
|
notifyCtx(ctx, "All CodeCartographer phases are complete.", "info");
|
|
632
658
|
return;
|
|
633
659
|
}
|
|
660
|
+
const phase = outcome.phase;
|
|
634
661
|
let preflight;
|
|
635
662
|
try {
|
|
636
663
|
preflight = await runPhasePreflight(state, phase);
|
|
@@ -868,9 +895,13 @@ export default function codeCartographerExtension(pi) {
|
|
|
868
895
|
const state = await ensureWorkspaceState(ctx);
|
|
869
896
|
if (!state)
|
|
870
897
|
return;
|
|
871
|
-
const
|
|
872
|
-
if (
|
|
873
|
-
notifyCtx(ctx, `Cannot run skill: pipeline is not complete (next phase: ${
|
|
898
|
+
const outcome = resolvePipelineOutcome(state);
|
|
899
|
+
if (outcome.kind === "eligible") {
|
|
900
|
+
notifyCtx(ctx, `Cannot run skill: pipeline is not complete (next phase: ${outcome.phase.id}). Finish the pipeline before running post-pipeline skills.`, "error");
|
|
901
|
+
return;
|
|
902
|
+
}
|
|
903
|
+
if (outcome.kind === "stuck") {
|
|
904
|
+
notifyCtx(ctx, `Cannot run skill: the pipeline is not complete. ${describeStuckPipeline(outcome.blocked)}`, "error");
|
|
874
905
|
return;
|
|
875
906
|
}
|
|
876
907
|
// Resolve against the installed list only: the name is never joined
|
|
@@ -908,11 +939,13 @@ export default function codeCartographerExtension(pi) {
|
|
|
908
939
|
const lines = skills.length > 0
|
|
909
940
|
? [`Available skills (${skills.length}):`, ...skills.map((name) => ` - ${name}`)]
|
|
910
941
|
: ["No skills installed."];
|
|
911
|
-
const
|
|
942
|
+
const outcome = resolvePipelineOutcome(state);
|
|
912
943
|
if (skills.length > 0) {
|
|
913
|
-
lines.push(
|
|
914
|
-
? `Post-pipeline skills unlock when the pipeline completes (next phase: ${
|
|
915
|
-
:
|
|
944
|
+
lines.push(outcome.kind === "eligible"
|
|
945
|
+
? `Post-pipeline skills unlock when the pipeline completes (next phase: ${outcome.phase.id}).`
|
|
946
|
+
: outcome.kind === "stuck"
|
|
947
|
+
? `Post-pipeline skills unlock when the pipeline completes, and it cannot: ${describeStuckPipeline(outcome.blocked)}`
|
|
948
|
+
: "Run one with /codecarto-skill <name>.");
|
|
916
949
|
}
|
|
917
950
|
// Broad-Side is listed apart from the post-pipeline set because it
|
|
918
951
|
// answers to /codecarto-skill without the completion gate.
|
|
@@ -967,7 +1000,7 @@ export default function codeCartographerExtension(pi) {
|
|
|
967
1000
|
},
|
|
968
1001
|
});
|
|
969
1002
|
pi.registerCommand("codecarto-broadside", {
|
|
970
|
-
description: "Batch reconnaissance (Broad-Side): /codecarto-broadside [submit|collect|status|models] [lenses…] [flags]",
|
|
1003
|
+
description: "Batch reconnaissance (Broad-Side): /codecarto-broadside [submit|collect|status|models] [lenses…] [--model=ID] [--lens-model=LENS:ID] [flags]",
|
|
971
1004
|
getArgumentCompletions: (prefix) => {
|
|
972
1005
|
const items = KNOWN_BROADSIDE_TOKENS
|
|
973
1006
|
.filter((value) => value.startsWith(prefix))
|
|
@@ -988,7 +1021,23 @@ export default function codeCartographerExtension(pi) {
|
|
|
988
1021
|
// Broad-Side runs on any git repository, with or without a workspace —
|
|
989
1022
|
// so this command never goes through ensureWorkspaceState.
|
|
990
1023
|
const broadsideDir = broadsideDirFor(ctx.cwd);
|
|
991
|
-
|
|
1024
|
+
// A config.yaml that exists but cannot be read refuses every action
|
|
1025
|
+
// that would act on it (#232); status only reads recorded runs, so it
|
|
1026
|
+
// answers and says the file is unreadable.
|
|
1027
|
+
let config;
|
|
1028
|
+
let configWarning = null;
|
|
1029
|
+
try {
|
|
1030
|
+
config = await loadBroadsideConfig(broadsideDir);
|
|
1031
|
+
}
|
|
1032
|
+
catch (error) {
|
|
1033
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1034
|
+
if (!(error instanceof BroadsideConfigError) || flags.action !== "status") {
|
|
1035
|
+
notifyCtx(ctx, `Broad-Side ${flags.action} refused: ${message}`, "error");
|
|
1036
|
+
return;
|
|
1037
|
+
}
|
|
1038
|
+
config = defaultBroadsideConfig();
|
|
1039
|
+
configWarning = message;
|
|
1040
|
+
}
|
|
992
1041
|
const finish = (lines, notice, level = "info") => {
|
|
993
1042
|
lastFeedbackLines = lines;
|
|
994
1043
|
if (codecartoModeActive) {
|
|
@@ -1005,9 +1054,18 @@ export default function codeCartographerExtension(pi) {
|
|
|
1005
1054
|
notifyCtx(ctx, notice, level);
|
|
1006
1055
|
};
|
|
1007
1056
|
if (flags.action === "status") {
|
|
1008
|
-
|
|
1057
|
+
let state;
|
|
1058
|
+
try {
|
|
1059
|
+
({ state } = await runBroadsideStatus(ctx.cwd));
|
|
1060
|
+
}
|
|
1061
|
+
catch (error) {
|
|
1062
|
+
// A corrupt state.json: nothing trustworthy to report, and the
|
|
1063
|
+
// error names the preserved copy (#233).
|
|
1064
|
+
notifyCtx(ctx, `Broad-Side status failed: ${error instanceof Error ? error.message : String(error)}`, "error");
|
|
1065
|
+
return;
|
|
1066
|
+
}
|
|
1009
1067
|
const runs = state.runs.length;
|
|
1010
|
-
finish(statusText(state).split("\n"), runs > 0 ? `Broad-Side: ${runs} recorded run${runs === 1 ? "" : "s"}` : "Broad-Side: no runs recorded yet");
|
|
1068
|
+
finish([...statusText(state).split("\n"), ...(configWarning ? [`Warning: ${configWarning}`] : [])], runs > 0 ? `Broad-Side: ${runs} recorded run${runs === 1 ? "" : "s"}` : "Broad-Side: no runs recorded yet", configWarning ? "warning" : "info");
|
|
1011
1069
|
return;
|
|
1012
1070
|
}
|
|
1013
1071
|
const apiKey = resolveBroadsideKey(config.apiKey);
|
|
@@ -1019,10 +1077,10 @@ export default function codeCartographerExtension(pi) {
|
|
|
1019
1077
|
if (flags.action === "models") {
|
|
1020
1078
|
notifyCtx(ctx, "Fetching the OpenRouter batch-model catalog…", "info");
|
|
1021
1079
|
try {
|
|
1022
|
-
const { entries, benchmarks } = await listBatchModels(broadsideDir, config, apiKey, {
|
|
1080
|
+
const { entries, benchmarks, endpoints } = await listBatchModels(broadsideDir, config, apiKey, {
|
|
1023
1081
|
includeBenchmarks: flags.benchmarks,
|
|
1024
1082
|
});
|
|
1025
|
-
finish(modelsText(entries, { benchmarks, defaultModel: config.model }).split("\n"), `Broad-Side: ${entries.length} batch model${entries.length === 1 ? "" : "s"} listed`);
|
|
1083
|
+
finish(modelsText(entries, { benchmarks, defaultModel: config.model, endpoints }).split("\n"), `Broad-Side: ${entries.length} batch model${entries.length === 1 ? "" : "s"} listed`);
|
|
1026
1084
|
}
|
|
1027
1085
|
catch (error) {
|
|
1028
1086
|
notifyCtx(ctx, `Model catalog lookup failed: ${error instanceof Error ? error.message : String(error)}`, "error");
|
|
@@ -1045,8 +1103,10 @@ export default function codeCartographerExtension(pi) {
|
|
|
1045
1103
|
progress.set(lensId, `${status} (${counts.completed ?? 0}/${counts.total ?? "?"})`);
|
|
1046
1104
|
renderProgress("Polling batches…");
|
|
1047
1105
|
};
|
|
1106
|
+
// An explicit --wait=0 polls once and returns; it used to become
|
|
1107
|
+
// undefined and, in core, the 25-minute budget (#230).
|
|
1048
1108
|
const waitSeconds = flags.waitSeconds ?? config.waitSeconds;
|
|
1049
|
-
const waitMs = waitSeconds
|
|
1109
|
+
const waitMs = waitSeconds * 1000;
|
|
1050
1110
|
const includeSynthesis = flags.includeSynthesis ?? config.includeSynthesis;
|
|
1051
1111
|
const includeTriage = flags.includeTriage ?? config.includeTriage;
|
|
1052
1112
|
const retryTruncated = flags.retryTruncated ?? config.retryTruncated;
|
|
@@ -1057,7 +1117,11 @@ export default function codeCartographerExtension(pi) {
|
|
|
1057
1117
|
try {
|
|
1058
1118
|
submit = await runBroadsideSubmit(ctx.cwd, apiKey, {
|
|
1059
1119
|
lenses,
|
|
1060
|
-
model
|
|
1120
|
+
// --model= and --lens-model= select for this run; the file's
|
|
1121
|
+
// values are the fallback, and core pre-flights either the
|
|
1122
|
+
// same way (#141).
|
|
1123
|
+
model: flags.model ?? config.model,
|
|
1124
|
+
lensModels: flags.lensModels,
|
|
1061
1125
|
maxCost: flags.maxCost ?? config.maxCost,
|
|
1062
1126
|
// `??`, not `||`: --no-incremental parses to false and must beat a
|
|
1063
1127
|
// config-set true, exactly as MCP's `incremental: false` does (#163).
|
|
@@ -1113,6 +1177,7 @@ export default function codeCartographerExtension(pi) {
|
|
|
1113
1177
|
includeTriage,
|
|
1114
1178
|
retryTruncated,
|
|
1115
1179
|
onStatus,
|
|
1180
|
+
...(flags.runId && { runId: flags.runId }),
|
|
1116
1181
|
});
|
|
1117
1182
|
const lines = collectResultText(collect).split("\n");
|
|
1118
1183
|
const done = collect.status === "completed";
|
|
@@ -1255,12 +1320,11 @@ export default function codeCartographerExtension(pi) {
|
|
|
1255
1320
|
notifyCtx(ctx, "Usage: /codecarto-library-init <path> [--namespace <name>]", "warning");
|
|
1256
1321
|
return;
|
|
1257
1322
|
}
|
|
1258
|
-
|
|
1323
|
+
// The same expansion the config loader applies, so `~user/x` and a
|
|
1324
|
+
// bare `~` mean the same thing everywhere (self-audit mech 6.14).
|
|
1325
|
+
const libraryPath = resolve(expandTilde(pathArg));
|
|
1259
1326
|
try {
|
|
1260
|
-
const result = await initLibrary(libraryPath, {
|
|
1261
|
-
namespaced: !!namespace,
|
|
1262
|
-
...(namespace ? {} : {}),
|
|
1263
|
-
});
|
|
1327
|
+
const result = await initLibrary(libraryPath, { namespaced: !!namespace });
|
|
1264
1328
|
// Write library.path (and library.namespace when given) to the
|
|
1265
1329
|
// user-global config and nothing else — not publish_confirm, so
|
|
1266
1330
|
// initializing a library does not change how publish behaves on
|
|
@@ -1459,9 +1523,13 @@ export default function codeCartographerExtension(pi) {
|
|
|
1459
1523
|
notifyCtx(ctx, error instanceof Error ? error.message : String(error), "error");
|
|
1460
1524
|
return;
|
|
1461
1525
|
}
|
|
1462
|
-
const
|
|
1463
|
-
if (
|
|
1464
|
-
notifyCtx(ctx, `Cannot amend: the pipeline is not complete
|
|
1526
|
+
const outcome = resolvePipelineOutcome(state);
|
|
1527
|
+
if (outcome.kind === "stuck") {
|
|
1528
|
+
notifyCtx(ctx, `Cannot amend: the pipeline is not complete. ${describeStuckPipeline(outcome.blocked)}`, "error");
|
|
1529
|
+
return;
|
|
1530
|
+
}
|
|
1531
|
+
if (outcome.kind === "eligible") {
|
|
1532
|
+
notifyCtx(ctx, `Cannot amend: the pipeline is not complete (next phase: ${outcome.phase.id}). `
|
|
1465
1533
|
+ "Resolve open questions and routed items through that phase's handoff (open_question_closures / carry_forward_closures) instead.", "error");
|
|
1466
1534
|
return;
|
|
1467
1535
|
}
|
|
@@ -7,7 +7,11 @@ export function phaseIdFromSessionName(sessionName) {
|
|
|
7
7
|
if (!sessionName?.startsWith(PHASE_SESSION_PREFIX))
|
|
8
8
|
return null;
|
|
9
9
|
const phaseId = sessionName.slice(PHASE_SESSION_PREFIX.length).trim();
|
|
10
|
-
|
|
10
|
+
// The same alphabet assertSafePhaseId admits (core/status.ts). A narrower
|
|
11
|
+
// match here silently dropped the bash block, write confinement, and
|
|
12
|
+
// checkpointing for a custom pipeline whose ids used `.`, `_`, or a capital
|
|
13
|
+
// (self-audit mech 6.11).
|
|
14
|
+
return /^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(phaseId) ? phaseId : null;
|
|
11
15
|
}
|
|
12
16
|
export function buildPhaseCompactionInstructions(phaseId, primaryOutput) {
|
|
13
17
|
const output = primaryOutput ? `.codecarto/${primaryOutput}` : "the phase's declared primary output";
|
|
@@ -37,6 +37,7 @@ export declare function handleSwitchPipeline(args: {
|
|
|
37
37
|
}>;
|
|
38
38
|
export declare function handleNext(args: {
|
|
39
39
|
cwd: string;
|
|
40
|
+
unattended?: boolean;
|
|
40
41
|
}): Promise<{
|
|
41
42
|
content: {
|
|
42
43
|
type: "text";
|
|
@@ -49,6 +50,7 @@ export declare function handleNext(args: {
|
|
|
49
50
|
export declare function handlePhase(args: {
|
|
50
51
|
cwd: string;
|
|
51
52
|
phase: string;
|
|
53
|
+
unattended?: boolean;
|
|
52
54
|
}): Promise<{
|
|
53
55
|
content: {
|
|
54
56
|
type: "text";
|
|
@@ -130,7 +132,6 @@ export declare function handleLibraryInit(args: {
|
|
|
130
132
|
library_path: string;
|
|
131
133
|
name?: string;
|
|
132
134
|
namespace?: string;
|
|
133
|
-
cwd?: string;
|
|
134
135
|
}): Promise<{
|
|
135
136
|
content: {
|
|
136
137
|
type: "text";
|
|
@@ -236,6 +237,7 @@ export declare function handleBroadside(args: {
|
|
|
236
237
|
lenses?: string[];
|
|
237
238
|
api_key?: string;
|
|
238
239
|
wait_seconds?: number;
|
|
240
|
+
run_id?: string;
|
|
239
241
|
include_synthesis?: boolean;
|
|
240
242
|
include_triage?: boolean;
|
|
241
243
|
retry_truncated?: boolean;
|
|
@@ -243,6 +245,8 @@ export declare function handleBroadside(args: {
|
|
|
243
245
|
force?: boolean;
|
|
244
246
|
include_benchmarks?: boolean;
|
|
245
247
|
incremental?: boolean;
|
|
248
|
+
model?: string;
|
|
249
|
+
lens_models?: Record<string, string>;
|
|
246
250
|
}): Promise<{
|
|
247
251
|
content: {
|
|
248
252
|
type: "text";
|