truecourse 0.6.0-next.5 → 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.
Files changed (3) hide show
  1. package/cli.mjs +32 -9
  2. package/package.json +1 -1
  3. 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.5";
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
- for (const issue of missing) {
147778
- const slice3 = findSliceForMissing(issue.artifactKey, slices);
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
- log2.push(`repair: missing ${issue.artifactKey} \u2014 re-prompting "${slice3.headingPath.join(" \u2192 ")}".`);
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
- for (const [k, issues] of grouped) {
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
- log2.push(`repair: incomplete ${k} (${issues.length} issue${issues.length === 1 ? "" : "s"}) \u2014 re-prompting.`);
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) => ({
@@ -149129,6 +149146,11 @@ async function runContractsGenerate(options = {}) {
149129
149146
  },
149130
149147
  onSliceCacheHit: (s) => {
149131
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}`);
149132
149154
  }
149133
149155
  });
149134
149156
  } catch (e) {
@@ -149159,6 +149181,7 @@ async function runContractsGenerate(options = {}) {
149159
149181
  process.exit(1);
149160
149182
  }
149161
149183
  for (const d3 of result.mergeDiagnostics) {
149184
+ if (d3.artifactKey === "repair" && d3.message.includes("re-prompting")) continue;
149162
149185
  O2.warn(d3.message);
149163
149186
  }
149164
149187
  const LIST_CAP = 20;
@@ -152795,7 +152818,7 @@ async function runHooksRun() {
152795
152818
 
152796
152819
  // tools/cli/src/index.ts
152797
152820
  var program2 = new Command();
152798
- program2.name("truecourse").version("0.6.0-next.5").description("TrueCourse CLI \u2014 analyze your repository and open the dashboard");
152821
+ program2.name("truecourse").version("0.6.0-next.6").description("TrueCourse CLI \u2014 analyze your repository and open the dashboard");
152799
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) => {
152800
152823
  if (options.service && options.console) {
152801
152824
  console.error("error: --service and --console are mutually exclusive");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "truecourse",
3
- "version": "0.6.0-next.5",
3
+ "version": "0.6.0-next.6",
4
4
  "description": "Visualize your codebase architecture as an interactive graph",
5
5
  "type": "module",
6
6
  "bin": {
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.5";
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
- for (const issue of missing) {
164560
- const slice3 = findSliceForMissing(issue.artifactKey, slices);
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
- log2.push(`repair: missing ${issue.artifactKey} \u2014 re-prompting "${slice3.headingPath.join(" \u2192 ")}".`);
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
- for (const [k, issues] of grouped) {
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
- log2.push(`repair: incomplete ${k} (${issues.length} issue${issues.length === 1 ? "" : "s"}) \u2014 re-prompting.`);
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) => ({