truecourse 0.6.0-next.4 → 0.6.0-next.6
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/cli.mjs +45 -15
- package/package.json +1 -1
- package/server.mjs +25 -8
package/cli.mjs
CHANGED
|
@@ -128242,7 +128242,7 @@ function readToolVersion() {
|
|
|
128242
128242
|
if (cachedVersion)
|
|
128243
128243
|
return cachedVersion;
|
|
128244
128244
|
if (true) {
|
|
128245
|
-
cachedVersion = "0.6.0-next.
|
|
128245
|
+
cachedVersion = "0.6.0-next.6";
|
|
128246
128246
|
return cachedVersion;
|
|
128247
128247
|
}
|
|
128248
128248
|
try {
|
|
@@ -147772,15 +147772,24 @@ async function repair(artifacts, slices, opts = {}) {
|
|
|
147772
147772
|
const modelArgs = buildModelArgs2(opts.model, opts.fallbackModel);
|
|
147773
147773
|
const log2 = [];
|
|
147774
147774
|
const allIssues = [];
|
|
147775
|
+
let done = 0;
|
|
147776
|
+
let total = 0;
|
|
147775
147777
|
const missing = detectMissingArtifacts(artifacts);
|
|
147776
147778
|
allIssues.push(...missing);
|
|
147777
|
-
|
|
147778
|
-
|
|
147779
|
+
const missingTasks = missing.map((issue) => ({
|
|
147780
|
+
issue,
|
|
147781
|
+
slice: findSliceForMissing(issue.artifactKey, slices)
|
|
147782
|
+
}));
|
|
147783
|
+
total += missingTasks.filter((t2) => t2.slice).length;
|
|
147784
|
+
for (const { issue, slice: slice3 } of missingTasks) {
|
|
147779
147785
|
if (!slice3) {
|
|
147780
147786
|
log2.push(`repair: missing ${issue.artifactKey} \u2014 no candidate slice found, skipping.`);
|
|
147781
147787
|
continue;
|
|
147782
147788
|
}
|
|
147783
|
-
|
|
147789
|
+
done += 1;
|
|
147790
|
+
const message = `missing ${issue.artifactKey} \u2014 re-prompting "${slice3.headingPath.join(" \u2192 ")}"`;
|
|
147791
|
+
log2.push(`repair: ${message}.`);
|
|
147792
|
+
opts.onProgress?.({ done, total, message });
|
|
147784
147793
|
const fragments = await runFixOne({ previousArtifact: null, missingKey: issue.artifactKey, slice: slice3, issues: [issue.detail] }, bin, timeoutMs, modelArgs);
|
|
147785
147794
|
if (!fragments) {
|
|
147786
147795
|
log2.push(`repair: re-prompt failed for ${issue.artifactKey}.`);
|
|
@@ -147816,16 +147825,23 @@ async function repair(artifacts, slices, opts = {}) {
|
|
|
147816
147825
|
grouped.set(issue.artifactKey, arr);
|
|
147817
147826
|
}
|
|
147818
147827
|
allIssues.push(...incomplete);
|
|
147819
|
-
|
|
147828
|
+
const incompleteTasks = [...grouped].map(([k, issues]) => {
|
|
147820
147829
|
const artifact = artifacts.find((a) => key(a.kind, a.identity) === k);
|
|
147830
|
+
const slice3 = artifact ? sliceForArtifact(artifact, slices) : void 0;
|
|
147831
|
+
return { k, issues, artifact, slice: slice3 };
|
|
147832
|
+
});
|
|
147833
|
+
total += incompleteTasks.filter((t2) => t2.artifact && t2.slice).length;
|
|
147834
|
+
for (const { k, issues, artifact, slice: slice3 } of incompleteTasks) {
|
|
147821
147835
|
if (!artifact)
|
|
147822
147836
|
continue;
|
|
147823
|
-
const slice3 = sliceForArtifact(artifact, slices);
|
|
147824
147837
|
if (!slice3) {
|
|
147825
147838
|
log2.push(`repair: incomplete ${k} \u2014 could not locate source slice, skipping.`);
|
|
147826
147839
|
continue;
|
|
147827
147840
|
}
|
|
147828
|
-
|
|
147841
|
+
done += 1;
|
|
147842
|
+
const message = `incomplete ${k} (${issues.length} issue${issues.length === 1 ? "" : "s"}) \u2014 re-prompting`;
|
|
147843
|
+
log2.push(`repair: ${message}.`);
|
|
147844
|
+
opts.onProgress?.({ done, total, message });
|
|
147829
147845
|
const fragments = await runFixOne({ previousArtifact: artifact, slice: slice3, issues: issues.map((i) => i.detail) }, bin, timeoutMs, modelArgs);
|
|
147830
147846
|
if (!fragments || fragments.length === 0) {
|
|
147831
147847
|
log2.push(`repair: re-prompt failed for ${k}.`);
|
|
@@ -148193,7 +148209,8 @@ async function generateContracts(opts) {
|
|
|
148193
148209
|
if (slices.length > 0 && !dryRun && !opts.disableRepair) {
|
|
148194
148210
|
const repaired = await repair(merged.artifacts, slices, {
|
|
148195
148211
|
model: models.repair,
|
|
148196
|
-
fallbackModel: models.fallback
|
|
148212
|
+
fallbackModel: models.fallback,
|
|
148213
|
+
onProgress: opts.onRepairProgress
|
|
148197
148214
|
});
|
|
148198
148215
|
merged.artifacts = repaired.artifacts;
|
|
148199
148216
|
merged.diagnostics.push(...repaired.log.map((message) => ({
|
|
@@ -149106,13 +149123,15 @@ async function runContractsGenerate(options = {}) {
|
|
|
149106
149123
|
const repairModel = resolveModel("contract.repair", void 0, repoRoot5);
|
|
149107
149124
|
const fallbackModel = resolveFallbackModel(repoRoot5) ?? void 0;
|
|
149108
149125
|
let totalSlices = 0;
|
|
149109
|
-
let
|
|
149126
|
+
let doneSlices = 0;
|
|
149110
149127
|
const runner = spawnRunner2({
|
|
149111
149128
|
concurrency,
|
|
149112
149129
|
model: extractModel,
|
|
149113
149130
|
fallbackModel,
|
|
149114
|
-
|
|
149115
|
-
O2.step(
|
|
149131
|
+
onSliceDone: (s, ok) => {
|
|
149132
|
+
O2.step(
|
|
149133
|
+
`extracted ${++doneSlices}/${totalSlices} ${s.specPath} :: ${s.headingPath.join(" \u2192 ")}${ok ? "" : " (failed)"}`
|
|
149134
|
+
);
|
|
149116
149135
|
}
|
|
149117
149136
|
});
|
|
149118
149137
|
let result;
|
|
@@ -149126,7 +149145,12 @@ async function runContractsGenerate(options = {}) {
|
|
|
149126
149145
|
totalSlices = t2;
|
|
149127
149146
|
},
|
|
149128
149147
|
onSliceCacheHit: (s) => {
|
|
149129
|
-
O2.message(` cache hit ${++
|
|
149148
|
+
O2.message(` cache hit ${++doneSlices}/${totalSlices} ${s.specPath} :: ${s.headingPath.join(" \u2192 ")}`, { symbol: "\xB7" });
|
|
149149
|
+
},
|
|
149150
|
+
// The repair pass runs sequential `claude` re-prompts after extraction —
|
|
149151
|
+
// stream each one so the terminal isn't silent through the LLM calls.
|
|
149152
|
+
onRepairProgress: (e) => {
|
|
149153
|
+
O2.step(`repairing ${e.done}/${e.total} ${e.message}`);
|
|
149130
149154
|
}
|
|
149131
149155
|
});
|
|
149132
149156
|
} catch (e) {
|
|
@@ -149157,15 +149181,21 @@ async function runContractsGenerate(options = {}) {
|
|
|
149157
149181
|
process.exit(1);
|
|
149158
149182
|
}
|
|
149159
149183
|
for (const d3 of result.mergeDiagnostics) {
|
|
149184
|
+
if (d3.artifactKey === "repair" && d3.message.includes("re-prompting")) continue;
|
|
149160
149185
|
O2.warn(d3.message);
|
|
149161
149186
|
}
|
|
149187
|
+
const LIST_CAP = 20;
|
|
149188
|
+
const printFileList = (files, marker) => {
|
|
149189
|
+
for (const f2 of files.slice(0, LIST_CAP)) console.log(` ${marker} ${path54.relative(repoRoot5, f2)}`);
|
|
149190
|
+
if (files.length > LIST_CAP) console.log(` \u2026 and ${files.length - LIST_CAP} more`);
|
|
149191
|
+
};
|
|
149162
149192
|
if (options.diff) {
|
|
149163
149193
|
if (result.write.proposed.length === 0) {
|
|
149164
149194
|
gt("No changes \u2014 every contract is already up to date.");
|
|
149165
149195
|
return;
|
|
149166
149196
|
}
|
|
149167
149197
|
O2.info(`Would write ${result.write.proposed.length} file${result.write.proposed.length === 1 ? "" : "s"}:`);
|
|
149168
|
-
|
|
149198
|
+
printFileList(result.write.proposed, "+");
|
|
149169
149199
|
gt("Run `truecourse contracts generate` to apply.");
|
|
149170
149200
|
return;
|
|
149171
149201
|
}
|
|
@@ -149175,7 +149205,7 @@ async function runContractsGenerate(options = {}) {
|
|
|
149175
149205
|
return;
|
|
149176
149206
|
}
|
|
149177
149207
|
O2.success(`Wrote ${result.write.written.length} contract file${result.write.written.length === 1 ? "" : "s"}.`);
|
|
149178
|
-
|
|
149208
|
+
printFileList(result.write.written, "\u2022");
|
|
149179
149209
|
syncShippedTcSyntax();
|
|
149180
149210
|
gt(`Run \`truecourse verify\` to check code against the new contracts.`);
|
|
149181
149211
|
}
|
|
@@ -152788,7 +152818,7 @@ async function runHooksRun() {
|
|
|
152788
152818
|
|
|
152789
152819
|
// tools/cli/src/index.ts
|
|
152790
152820
|
var program2 = new Command();
|
|
152791
|
-
program2.name("truecourse").version("0.6.0-next.
|
|
152821
|
+
program2.name("truecourse").version("0.6.0-next.6").description("TrueCourse CLI \u2014 analyze your repository and open the dashboard");
|
|
152792
152822
|
var dashboardCmd = program2.command("dashboard").description("Start the TrueCourse dashboard and open it in your browser").option("--reconfigure", "Re-prompt for console vs background service mode").option("--service", "Run as a background service (skips mode prompt)").option("--console", "Run in this terminal (skips mode prompt)").action(async (options) => {
|
|
152793
152823
|
if (options.service && options.console) {
|
|
152794
152824
|
console.error("error: --service and --console are mutually exclusive");
|
package/package.json
CHANGED
package/server.mjs
CHANGED
|
@@ -156920,7 +156920,7 @@ function readToolVersion() {
|
|
|
156920
156920
|
if (cachedVersion)
|
|
156921
156921
|
return cachedVersion;
|
|
156922
156922
|
if (true) {
|
|
156923
|
-
cachedVersion = "0.6.0-next.
|
|
156923
|
+
cachedVersion = "0.6.0-next.6";
|
|
156924
156924
|
return cachedVersion;
|
|
156925
156925
|
}
|
|
156926
156926
|
try {
|
|
@@ -164554,15 +164554,24 @@ async function repair(artifacts, slices, opts = {}) {
|
|
|
164554
164554
|
const modelArgs = buildModelArgs2(opts.model, opts.fallbackModel);
|
|
164555
164555
|
const log2 = [];
|
|
164556
164556
|
const allIssues = [];
|
|
164557
|
+
let done = 0;
|
|
164558
|
+
let total = 0;
|
|
164557
164559
|
const missing = detectMissingArtifacts(artifacts);
|
|
164558
164560
|
allIssues.push(...missing);
|
|
164559
|
-
|
|
164560
|
-
|
|
164561
|
+
const missingTasks = missing.map((issue) => ({
|
|
164562
|
+
issue,
|
|
164563
|
+
slice: findSliceForMissing(issue.artifactKey, slices)
|
|
164564
|
+
}));
|
|
164565
|
+
total += missingTasks.filter((t) => t.slice).length;
|
|
164566
|
+
for (const { issue, slice: slice3 } of missingTasks) {
|
|
164561
164567
|
if (!slice3) {
|
|
164562
164568
|
log2.push(`repair: missing ${issue.artifactKey} \u2014 no candidate slice found, skipping.`);
|
|
164563
164569
|
continue;
|
|
164564
164570
|
}
|
|
164565
|
-
|
|
164571
|
+
done += 1;
|
|
164572
|
+
const message = `missing ${issue.artifactKey} \u2014 re-prompting "${slice3.headingPath.join(" \u2192 ")}"`;
|
|
164573
|
+
log2.push(`repair: ${message}.`);
|
|
164574
|
+
opts.onProgress?.({ done, total, message });
|
|
164566
164575
|
const fragments = await runFixOne({ previousArtifact: null, missingKey: issue.artifactKey, slice: slice3, issues: [issue.detail] }, bin, timeoutMs, modelArgs);
|
|
164567
164576
|
if (!fragments) {
|
|
164568
164577
|
log2.push(`repair: re-prompt failed for ${issue.artifactKey}.`);
|
|
@@ -164598,16 +164607,23 @@ async function repair(artifacts, slices, opts = {}) {
|
|
|
164598
164607
|
grouped.set(issue.artifactKey, arr);
|
|
164599
164608
|
}
|
|
164600
164609
|
allIssues.push(...incomplete);
|
|
164601
|
-
|
|
164610
|
+
const incompleteTasks = [...grouped].map(([k, issues]) => {
|
|
164602
164611
|
const artifact = artifacts.find((a) => key(a.kind, a.identity) === k);
|
|
164612
|
+
const slice3 = artifact ? sliceForArtifact(artifact, slices) : void 0;
|
|
164613
|
+
return { k, issues, artifact, slice: slice3 };
|
|
164614
|
+
});
|
|
164615
|
+
total += incompleteTasks.filter((t) => t.artifact && t.slice).length;
|
|
164616
|
+
for (const { k, issues, artifact, slice: slice3 } of incompleteTasks) {
|
|
164603
164617
|
if (!artifact)
|
|
164604
164618
|
continue;
|
|
164605
|
-
const slice3 = sliceForArtifact(artifact, slices);
|
|
164606
164619
|
if (!slice3) {
|
|
164607
164620
|
log2.push(`repair: incomplete ${k} \u2014 could not locate source slice, skipping.`);
|
|
164608
164621
|
continue;
|
|
164609
164622
|
}
|
|
164610
|
-
|
|
164623
|
+
done += 1;
|
|
164624
|
+
const message = `incomplete ${k} (${issues.length} issue${issues.length === 1 ? "" : "s"}) \u2014 re-prompting`;
|
|
164625
|
+
log2.push(`repair: ${message}.`);
|
|
164626
|
+
opts.onProgress?.({ done, total, message });
|
|
164611
164627
|
const fragments = await runFixOne({ previousArtifact: artifact, slice: slice3, issues: issues.map((i) => i.detail) }, bin, timeoutMs, modelArgs);
|
|
164612
164628
|
if (!fragments || fragments.length === 0) {
|
|
164613
164629
|
log2.push(`repair: re-prompt failed for ${k}.`);
|
|
@@ -175613,7 +175629,8 @@ async function generateContracts(opts) {
|
|
|
175613
175629
|
if (slices.length > 0 && !dryRun && !opts.disableRepair) {
|
|
175614
175630
|
const repaired = await repair(merged.artifacts, slices, {
|
|
175615
175631
|
model: models.repair,
|
|
175616
|
-
fallbackModel: models.fallback
|
|
175632
|
+
fallbackModel: models.fallback,
|
|
175633
|
+
onProgress: opts.onRepairProgress
|
|
175617
175634
|
});
|
|
175618
175635
|
merged.artifacts = repaired.artifacts;
|
|
175619
175636
|
merged.diagnostics.push(...repaired.log.map((message) => ({
|