repowise 0.1.80 → 0.1.82

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 (2) hide show
  1. package/dist/bin/repowise.js +128 -186
  2. package/package.json +1 -1
@@ -1939,31 +1939,6 @@ var CORE_FILES = /* @__PURE__ */ new Set([
1939
1939
  "api-contracts.md",
1940
1940
  "coding-patterns.md"
1941
1941
  ]);
1942
- var FILE_DESCRIPTIONS = {
1943
- // Core
1944
- "project-overview.md": "Project overview & file index",
1945
- "architecture.md": "System design & components",
1946
- "data-models.md": "Schemas, entities & relationships",
1947
- "api-contracts.md": "API endpoints & contracts",
1948
- "coding-patterns.md": "Code conventions & patterns",
1949
- // Tailored
1950
- "domain-knowledge.md": "Business domain & terminology",
1951
- "testing-strategy.md": "Test frameworks & coverage",
1952
- "deployment-workflows.md": "CI/CD & release process",
1953
- "state-management.md": "State & caching patterns",
1954
- "performance-optimization.md": "Performance & optimization",
1955
- "accessibility-patterns.md": "Accessibility & ARIA patterns",
1956
- "tech-stack.md": "Technology inventory & versions",
1957
- "tribal-knowledge.md": "Team knowledge & conventions",
1958
- "development-setup.md": "Dev environment setup",
1959
- "ui-patterns.md": "UI components & design system",
1960
- "ux-patterns.md": "UX interactions & feedback",
1961
- "user-flows.md": "User journeys & navigation",
1962
- "security-patterns.md": "Auth & security patterns",
1963
- "error-handling.md": "Error handling & recovery",
1964
- "integration-patterns.md": "External integrations & APIs",
1965
- "configuration.md": "Config & environment settings"
1966
- };
1967
1942
  var ALL_PERSONAS = ["pm", "architect", "dev", "analyst", "tea", "ux", "sm", "techWriter"];
1968
1943
  var PERSONA_LABELS = {
1969
1944
  pm: "Product Manager",
@@ -1984,14 +1959,16 @@ function computeOverallProgress(syncResult) {
1984
1959
  var ProgressRenderer = class {
1985
1960
  privacyShieldShown = false;
1986
1961
  discoveryShown = false;
1962
+ scanHeaderShown = false;
1987
1963
  scanSummaryShown = false;
1964
+ generationHeaderShown = false;
1965
+ coreSubtitleShown = false;
1966
+ coreCompleteShown = false;
1967
+ tailoredSubtitleShown = false;
1968
+ tailoredCompleteShown = false;
1969
+ validationHeaderShown = false;
1988
1970
  validationShown = false;
1989
- lastValidationSnapshot = "";
1990
- lastValidationLineCount = 0;
1991
1971
  pushShown = false;
1992
- fileStatusHeaderShown = false;
1993
- lastFileStatusSnapshot = "";
1994
- lastFileStatusLineCount = 0;
1995
1972
  renderPrivacyShield(enabled, spinner) {
1996
1973
  if (this.privacyShieldShown) return;
1997
1974
  this.privacyShieldShown = true;
@@ -2078,94 +2055,36 @@ var ProgressRenderer = class {
2078
2055
  printNode(child, "", idx === topLevel.length - 1);
2079
2056
  });
2080
2057
  }
2081
- renderScanSummary(summary, spinner) {
2082
- if (this.scanSummaryShown) return;
2083
- this.scanSummaryShown = true;
2084
- spinner.stop();
2085
- console.log(
2086
- chalk4.dim(
2087
- ` Scan complete: ${summary.totalFiles} files, ${summary.totalFunctions} functions, ${summary.totalClasses} classes, ${summary.totalEndpoints} entry points`
2088
- )
2089
- );
2090
- console.log("");
2091
- spinner.start();
2092
- }
2093
- renderValidation(progress, spinner) {
2094
- const resultMap = new Map(progress.personaResults.map((r) => [r.persona, r.score]));
2095
- const isComplete = progress.status === "complete";
2096
- if (isComplete && this.validationShown) return;
2097
- const snapshot = `${progress.round}:${progress.status}:${progress.personaResults.map((r) => `${r.persona}:${r.score}`).join(",")}`;
2098
- if (snapshot === this.lastValidationSnapshot) return;
2099
- this.lastValidationSnapshot = snapshot;
2100
- if (isComplete) this.validationShown = true;
2101
- spinner.stop();
2102
- if (this.lastValidationLineCount > 0) {
2103
- process.stdout.write(`\x1B[${this.lastValidationLineCount}A`);
2104
- }
2105
- const lines = [];
2106
- const title = isComplete ? "Validation Results" : "Validation";
2107
- lines.push(chalk4.cyan.bold(` \u2500\u2500 ${title} \u2500\u2500`));
2108
- if (!isComplete) {
2109
- lines.push(
2110
- chalk4.dim(
2111
- ` ${ALL_PERSONAS.length} AI reviewers checking context quality \u2014 issues are auto-fixed.`
2112
- )
2113
- );
2058
+ renderScanProgress(progress, spinner) {
2059
+ if (!this.scanHeaderShown) {
2060
+ this.scanHeaderShown = true;
2061
+ spinner.stop();
2062
+ console.log("");
2063
+ console.log(chalk4.cyan.bold(" \u2500\u2500 Code Analysis \u2500\u2500"));
2064
+ console.log(chalk4.dim(" Analyzing your codebase structure, functions, and relationships."));
2065
+ spinner.start();
2114
2066
  }
2115
- const passCount = progress.personaResults.filter((r) => r.score === "PASS").length;
2116
- if (isComplete) {
2117
- const roundInfo = progress.round > 1 ? ` (${progress.round} rounds)` : "";
2118
- lines.push(chalk4.dim(` ${passCount}/${ALL_PERSONAS.length} PASS${roundInfo}`));
2119
- } else if (progress.personaResults.length > 0) {
2120
- const statusSuffix = progress.status === "regenerating" ? chalk4.dim(" \u2014 improving files based on feedback") : "";
2121
- lines.push(
2122
- ` Round ${progress.round}/${progress.maxRounds}: ${passCount}/${ALL_PERSONAS.length} passed${statusSuffix}`
2067
+ if (progress.summary && !this.scanSummaryShown) {
2068
+ this.scanSummaryShown = true;
2069
+ const s = progress.summary;
2070
+ spinner.stop();
2071
+ console.log(
2072
+ ` ${chalk4.green("\u2713")} ${s.totalFiles} files, ${s.totalFunctions} functions, ${s.totalClasses} classes, ${s.totalEndpoints} entry points`
2123
2073
  );
2124
- } else {
2125
- lines.push(chalk4.dim(` Round ${progress.round}/${progress.maxRounds}: validating...`));
2126
- }
2127
- for (const persona of ALL_PERSONAS) {
2128
- const label = PERSONA_LABELS[persona] ?? persona;
2129
- const score = resultMap.get(persona);
2130
- if (score) {
2131
- const icon = score === "PASS" ? chalk4.green("\u2713") : chalk4.red("\u2717");
2132
- const scoreColor = score === "PASS" ? chalk4.green : score === "PARTIAL" ? chalk4.yellow : chalk4.red;
2133
- const fixingSuffix = progress.status === "regenerating" && score !== "PASS" ? chalk4.dim(" \u2192 fixing...") : "";
2134
- lines.push(` ${icon} ${label}: ${scoreColor(score)}${fixingSuffix}`);
2135
- } else {
2136
- lines.push(` ${chalk4.dim("\u25CB")} ${chalk4.dim(label)}`);
2137
- }
2138
- }
2139
- if (isComplete && passCount < ALL_PERSONAS.length) {
2140
- lines.push(chalk4.yellow(" \u26A0 Continuing with best-effort context"));
2141
- }
2142
- lines.push("");
2143
- for (const line of lines) {
2144
- process.stdout.write(`\x1B[2K${line}
2145
- `);
2146
- }
2147
- for (let i = lines.length; i < this.lastValidationLineCount; i++) {
2148
- process.stdout.write("\x1B[2K\n");
2074
+ console.log("");
2075
+ spinner.start();
2149
2076
  }
2150
- this.lastValidationLineCount = lines.length;
2151
- spinner.start();
2152
2077
  }
2153
2078
  renderFileStatuses(fileStatuses, spinner) {
2154
- const snapshot = fileStatuses.map((f) => `${f.fileName}:${f.status}`).join(",");
2155
- if (snapshot === this.lastFileStatusSnapshot) return;
2156
- this.lastFileStatusSnapshot = snapshot;
2157
- spinner.stop();
2158
- if (!this.fileStatusHeaderShown) {
2159
- this.fileStatusHeaderShown = true;
2160
- console.log("");
2161
- console.log(chalk4.cyan.bold(" \u2500\u2500 RepoWise Context Generation \u2500\u2500"));
2162
- console.log(chalk4.dim(" Building AI-optimized context files from your codebase."));
2079
+ if (!this.generationHeaderShown) {
2080
+ this.generationHeaderShown = true;
2081
+ spinner.stop();
2082
+ console.log(chalk4.cyan.bold(" \u2500\u2500 Context Generation \u2500\u2500"));
2163
2083
  console.log(
2164
2084
  chalk4.cyan(" \u2615 This takes a few minutes \u2014 grab a coffee, we'll handle the rest!")
2165
2085
  );
2166
- }
2167
- if (this.lastFileStatusLineCount > 0) {
2168
- process.stdout.write(`\x1B[${this.lastFileStatusLineCount}A`);
2086
+ console.log("");
2087
+ spinner.start();
2169
2088
  }
2170
2089
  const coreFiles = [];
2171
2090
  const tailoredFiles = [];
@@ -2177,96 +2096,116 @@ var ProgressRenderer = class {
2177
2096
  tailoredFiles.push(file);
2178
2097
  }
2179
2098
  }
2180
- const maxCoreLen = coreFiles.reduce((m, f) => Math.max(m, f.fileName.length), 0);
2181
- const maxTailoredLen = tailoredFiles.reduce((m, f) => Math.max(m, f.fileName.length), 0);
2182
- const formatFileLine = (file, padLen) => {
2183
- const baseName = file.fileName.split("/").pop() ?? file.fileName;
2184
- const desc = FILE_DESCRIPTIONS[baseName] ?? baseName.replace(/\.md$/, "").replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
2185
- const padded = file.fileName.padEnd(padLen);
2186
- switch (file.status) {
2187
- case "completed":
2188
- return ` ${chalk4.green("\u2713")} ${padded} ${chalk4.dim(`\u2014 ${desc}`)}`;
2189
- case "generating":
2190
- return ` ${chalk4.cyan("\u27F3")} ${padded} ${chalk4.dim(`\u2014 ${desc}`)}`;
2191
- case "failed":
2192
- return ` ${chalk4.red("\u2717")} ${padded} ${chalk4.dim(`\u2014 ${desc}`)}`;
2193
- case "pending":
2194
- return ` ${chalk4.dim("\u25CB")} ${chalk4.dim(`${padded} \u2014 ${desc}`)}`;
2195
- }
2196
- };
2197
- const lines = [];
2198
2099
  const coreCompleted = coreFiles.filter((f) => f.status === "completed").length;
2199
- const coreGenerating = coreFiles.filter((f) => f.status === "generating");
2200
- if (coreCompleted === coreFiles.length) {
2201
- lines.push(
2202
- ` ${chalk4.bold("Core")} ${chalk4.green("\u2713")} ${coreCompleted}/${coreFiles.length} completed`
2100
+ const coreTotal = coreFiles.length;
2101
+ const coreAllDone = coreCompleted === coreTotal && coreTotal > 0;
2102
+ if (coreTotal > 0 && !this.coreSubtitleShown) {
2103
+ this.coreSubtitleShown = true;
2104
+ spinner.stop();
2105
+ console.log(chalk4.dim(" Generating core context files:"));
2106
+ spinner.start();
2107
+ }
2108
+ if (coreAllDone && !this.coreCompleteShown) {
2109
+ this.coreCompleteShown = true;
2110
+ spinner.stop();
2111
+ console.log(` Core ${chalk4.green("\u2713")} ${coreCompleted}/${coreTotal} completed`);
2112
+ console.log("");
2113
+ spinner.start();
2114
+ }
2115
+ const tailoredCompleted = tailoredFiles.filter((f) => f.status === "completed").length;
2116
+ const tailoredTotal = tailoredFiles.length;
2117
+ const tailoredAllDone = tailoredCompleted === tailoredTotal && tailoredTotal > 0;
2118
+ if (tailoredTotal > 0 && coreAllDone && !this.tailoredSubtitleShown) {
2119
+ this.tailoredSubtitleShown = true;
2120
+ spinner.stop();
2121
+ console.log(chalk4.dim(" Generating tailored context files:"));
2122
+ spinner.start();
2123
+ }
2124
+ if (tailoredAllDone && !this.tailoredCompleteShown) {
2125
+ this.tailoredCompleteShown = true;
2126
+ spinner.stop();
2127
+ console.log(
2128
+ ` Tailored ${chalk4.green("\u2713")} ${tailoredCompleted}/${tailoredTotal} completed`
2203
2129
  );
2204
- } else {
2205
- lines.push(` ${chalk4.bold("Core")} (${coreCompleted}/${coreFiles.length} completed)`);
2206
- for (const file of coreGenerating) {
2207
- lines.push(formatFileLine(file, maxCoreLen));
2208
- }
2130
+ console.log("");
2131
+ spinner.start();
2209
2132
  }
2210
- if (tailoredFiles.length > 0) {
2211
- const tailoredCompleted = tailoredFiles.filter((f) => f.status === "completed").length;
2212
- const tailoredGenerating = tailoredFiles.filter((f) => f.status === "generating");
2213
- lines.push("");
2214
- if (tailoredCompleted === tailoredFiles.length) {
2215
- lines.push(
2216
- ` ${chalk4.bold("Tailored")} ${chalk4.green("\u2713")} ${tailoredCompleted}/${tailoredFiles.length} completed`
2217
- );
2218
- } else {
2219
- lines.push(
2220
- ` ${chalk4.bold("Tailored")} (${tailoredCompleted}/${tailoredFiles.length} completed)`
2221
- );
2222
- for (const file of tailoredGenerating) {
2223
- lines.push(formatFileLine(file, maxTailoredLen));
2133
+ }
2134
+ renderValidation(progress, spinner) {
2135
+ const isComplete = progress.status === "complete";
2136
+ if (isComplete && this.validationShown) return;
2137
+ if (!this.validationHeaderShown) {
2138
+ this.validationHeaderShown = true;
2139
+ spinner.stop();
2140
+ console.log(chalk4.cyan.bold(" \u2500\u2500 Context Validation \u2500\u2500"));
2141
+ console.log(
2142
+ chalk4.dim(
2143
+ ` ${ALL_PERSONAS.length} AI reviewers checking context quality \u2014 issues are auto-fixed.`
2144
+ )
2145
+ );
2146
+ spinner.start();
2147
+ }
2148
+ if (isComplete) {
2149
+ this.validationShown = true;
2150
+ spinner.stop();
2151
+ const passCount = progress.personaResults.filter((r) => r.score === "PASS").length;
2152
+ const roundInfo = progress.round > 1 ? ` (${progress.round} rounds)` : "";
2153
+ console.log(
2154
+ ` ${chalk4.green("\u2713")} ${passCount}/${ALL_PERSONAS.length} PASS${roundInfo}`
2155
+ );
2156
+ const resultMap = new Map(progress.personaResults.map((r) => [r.persona, r.score]));
2157
+ for (const persona of ALL_PERSONAS) {
2158
+ const label = PERSONA_LABELS[persona] ?? persona;
2159
+ const score = resultMap.get(persona);
2160
+ if (score) {
2161
+ const icon = score === "PASS" ? chalk4.green("\u2713") : chalk4.red("\u2717");
2162
+ const scoreColor = score === "PASS" ? chalk4.green : score === "PARTIAL" ? chalk4.yellow : chalk4.red;
2163
+ console.log(` ${icon} ${label}: ${scoreColor(score)}`);
2224
2164
  }
2225
2165
  }
2166
+ if (passCount < ALL_PERSONAS.length) {
2167
+ console.log(chalk4.yellow(" \u26A0 Continuing with best-effort context"));
2168
+ }
2169
+ console.log("");
2170
+ spinner.start();
2226
2171
  }
2227
- lines.push("");
2228
- for (const line of lines) {
2229
- process.stdout.write(`\x1B[2K${line}
2230
- `);
2231
- }
2232
- for (let i = lines.length; i < this.lastFileStatusLineCount; i++) {
2233
- process.stdout.write("\x1B[2K\n");
2234
- }
2235
- this.lastFileStatusLineCount = lines.length;
2236
- spinner.start();
2237
2172
  }
2238
2173
  renderPush(spinner) {
2239
2174
  if (this.pushShown) return;
2240
2175
  this.pushShown = true;
2241
2176
  spinner.stop();
2242
- console.log("");
2243
2177
  console.log(chalk4.cyan.bold(" \u2500\u2500 Saving Context \u2500\u2500"));
2244
2178
  console.log(` ${chalk4.dim("Encrypting and saving context files to RepoWise servers...")}`);
2245
2179
  console.log("");
2246
2180
  spinner.start();
2247
2181
  }
2182
+ /** No-op kept for backward compat with create.ts/sync.ts finalize() calls */
2183
+ finalize() {
2184
+ }
2248
2185
  getSpinnerText(syncResult) {
2249
- const stepLabel = syncResult.stepLabel ?? syncResult.currentStep ?? "Processing";
2250
2186
  const overallPct = computeOverallProgress(syncResult);
2251
- let progressText = stepLabel;
2187
+ const stepLabel = syncResult.stepLabel ?? syncResult.currentStep ?? "Processing";
2252
2188
  if (syncResult.scanProgress && !syncResult.scanProgress.summary) {
2253
- progressText = `Scanning batch ${syncResult.scanProgress.currentBatch}/${syncResult.scanProgress.totalBatches}`;
2254
- } else if (syncResult.validationProgress && syncResult.validationProgress.status !== "complete") {
2189
+ const sp = syncResult.scanProgress;
2190
+ const pct = sp.totalBatches > 0 ? Math.round(sp.currentBatch / sp.totalBatches * 100) : 0;
2191
+ return `Scanning batch ${sp.currentBatch}/${sp.totalBatches} ${chalk4.dim(`(${pct}%)`)}`;
2192
+ }
2193
+ if (syncResult.validationProgress && syncResult.validationProgress.status !== "complete") {
2255
2194
  const vp = syncResult.validationProgress;
2195
+ const passCount = vp.personaResults.filter((r) => r.score === "PASS").length;
2256
2196
  if (vp.status === "regenerating") {
2257
- progressText = `Improving files based on feedback (round ${vp.round})`;
2258
- } else {
2259
- progressText = `Validation round ${vp.round}/${vp.maxRounds}`;
2197
+ return `Improving files based on feedback (round ${vp.round}) ${chalk4.dim(`(${overallPct}%)`)}`;
2260
2198
  }
2261
- } else if (syncResult.generationProgress) {
2199
+ if (vp.personaResults.length > 0) {
2200
+ return `Round ${vp.round}/${vp.maxRounds}: ${passCount}/${ALL_PERSONAS.length} passed ${chalk4.dim(`(${overallPct}%)`)}`;
2201
+ }
2202
+ return `Round ${vp.round}/${vp.maxRounds}: validating... ${chalk4.dim(`(${overallPct}%)`)}`;
2203
+ }
2204
+ if (syncResult.generationProgress) {
2262
2205
  const gp = syncResult.generationProgress;
2263
2206
  if (gp.fileStatuses && gp.fileStatuses.length > 0) {
2264
- const completed = gp.fileStatuses.filter((f) => f.status === "completed").length;
2265
- const total = gp.fileStatuses.length;
2266
2207
  const generating = gp.fileStatuses.find((f) => f.status === "generating");
2267
- if (completed === total) {
2268
- progressText = stepLabel;
2269
- } else if (generating) {
2208
+ if (generating) {
2270
2209
  const genBaseName = generating.fileName.split("/").pop() ?? generating.fileName;
2271
2210
  const isCore = CORE_FILES.has(genBaseName);
2272
2211
  const sectionFiles = gp.fileStatuses.filter((f) => {
@@ -2274,16 +2213,15 @@ var ProgressRenderer = class {
2274
2213
  return isCore ? CORE_FILES.has(bn) : !CORE_FILES.has(bn);
2275
2214
  });
2276
2215
  const sectionCompleted = sectionFiles.filter((f) => f.status === "completed").length;
2277
- const sectionLabel = isCore ? "core" : "tailored";
2278
- progressText = `Generating ${generating.fileName} (${sectionCompleted}/${sectionFiles.length} ${sectionLabel})`;
2279
- } else {
2280
- progressText = `Generating (${completed}/${total})`;
2216
+ return `${generating.fileName} (${sectionCompleted}/${sectionFiles.length}) ${chalk4.dim(`(${overallPct}%)`)}`;
2217
+ }
2218
+ const allDone = gp.fileStatuses.every((f) => f.status === "completed");
2219
+ if (allDone) {
2220
+ return `${stepLabel}... ${chalk4.dim(`(${overallPct}%)`)}`;
2281
2221
  }
2282
- } else {
2283
- progressText = `Generating ${gp.currentFileName} (${gp.currentFile}/${gp.totalFiles})`;
2284
2222
  }
2285
2223
  }
2286
- return `${progressText}... ${chalk4.dim(`(${overallPct}%)`)}`;
2224
+ return `${stepLabel}... ${chalk4.dim(`(${overallPct}%)`)}`;
2287
2225
  }
2288
2226
  update(syncResult, spinner) {
2289
2227
  if (syncResult.privacyShieldEnabled !== void 0) {
@@ -2292,8 +2230,8 @@ var ProgressRenderer = class {
2292
2230
  if (syncResult.discoveryResult) {
2293
2231
  this.renderDiscovery(syncResult.discoveryResult, spinner);
2294
2232
  }
2295
- if (syncResult.scanProgress?.summary && syncResult.scanProgress.summary.totalFiles > 0) {
2296
- this.renderScanSummary(syncResult.scanProgress.summary, spinner);
2233
+ if (syncResult.scanProgress) {
2234
+ this.renderScanProgress(syncResult.scanProgress, spinner);
2297
2235
  }
2298
2236
  if (syncResult.generationProgress?.fileStatuses && syncResult.generationProgress.fileStatuses.length > 0) {
2299
2237
  this.renderFileStatuses(syncResult.generationProgress.fileStatuses, spinner);
@@ -2336,7 +2274,7 @@ var MAX_POLL_ATTEMPTS = 7200;
2336
2274
  var DEFAULT_CONTEXT_FOLDER = "repowise-context";
2337
2275
  async function create() {
2338
2276
  const startTime = Date.now();
2339
- const spinner = ora({ text: "Checking authentication...", stream: process.stdout }).start();
2277
+ const spinner = ora("Checking authentication...").start();
2340
2278
  try {
2341
2279
  let credentials = await getValidCredentials2();
2342
2280
  if (!credentials) {
@@ -2515,6 +2453,7 @@ async function create() {
2515
2453
  continue;
2516
2454
  }
2517
2455
  if (syncResult.status === "completed") {
2456
+ progressRenderer.finalize();
2518
2457
  const generatedFiles = syncResult.filesGenerated ?? [];
2519
2458
  const fileCount = generatedFiles.length;
2520
2459
  if (fileCount > 0) {
@@ -2536,6 +2475,7 @@ async function create() {
2536
2475
  break;
2537
2476
  }
2538
2477
  if (syncResult.status === "failed") {
2478
+ progressRenderer.finalize();
2539
2479
  spinner.fail(chalk5.red(`Pipeline failed: ${syncResult.error ?? "Unknown error"}`));
2540
2480
  process.exitCode = 1;
2541
2481
  return;
@@ -2845,7 +2785,7 @@ function formatElapsed2(ms) {
2845
2785
  }
2846
2786
  async function sync() {
2847
2787
  const startTime = Date.now();
2848
- const spinner = ora3({ text: "Checking authentication...", stream: process.stdout }).start();
2788
+ const spinner = ora3("Checking authentication...").start();
2849
2789
  try {
2850
2790
  let credentials = await getValidCredentials2();
2851
2791
  if (!credentials) {
@@ -2951,6 +2891,7 @@ async function sync() {
2951
2891
  continue;
2952
2892
  }
2953
2893
  if (syncResult.status === "completed") {
2894
+ progressRenderer.finalize();
2954
2895
  const generatedFiles = syncResult.filesGenerated ?? [];
2955
2896
  const fileCount = generatedFiles.length;
2956
2897
  if (fileCount > 0) {
@@ -2961,6 +2902,7 @@ async function sync() {
2961
2902
  break;
2962
2903
  }
2963
2904
  if (syncResult.status === "failed") {
2905
+ progressRenderer.finalize();
2964
2906
  spinner.fail(chalk8.red(`Sync failed: ${syncResult.error ?? "Unknown error"}`));
2965
2907
  process.exitCode = 1;
2966
2908
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "repowise",
3
- "version": "0.1.80",
3
+ "version": "0.1.82",
4
4
  "type": "module",
5
5
  "description": "AI-optimized codebase context generator",
6
6
  "bin": {