@doccov/cli 0.28.0 → 0.28.2

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/cli.js +228 -810
  2. package/package.json +2 -3
package/dist/cli.js CHANGED
@@ -87,26 +87,75 @@ import {
87
87
  parseExamplesFlag,
88
88
  resolveTarget
89
89
  } from "@doccov/sdk";
90
- import chalk7 from "chalk";
90
+ import chalk6 from "chalk";
91
91
 
92
- // ../cli-utils/dist/index.js
92
+ // src/utils/filter-options.ts
93
+ import { mergeFilters, parseListFlag } from "@doccov/sdk";
93
94
  import chalk from "chalk";
95
+ var parseVisibilityFlag = (value) => {
96
+ if (!value)
97
+ return;
98
+ const validTags = ["public", "beta", "alpha", "internal"];
99
+ const parsed = parseListFlag(value);
100
+ if (!parsed)
101
+ return;
102
+ const result = [];
103
+ for (const tag of parsed) {
104
+ const lower = tag.toLowerCase();
105
+ if (validTags.includes(lower)) {
106
+ result.push(lower);
107
+ }
108
+ }
109
+ return result.length > 0 ? result : undefined;
110
+ };
111
+ var formatList = (label, values) => `${label}: ${values.map((value) => chalk.cyan(value)).join(", ")}`;
112
+ var mergeFilterOptions = (config, cliOptions) => {
113
+ const messages = [];
114
+ if (config?.include) {
115
+ messages.push(formatList("include filters from config", config.include));
116
+ }
117
+ if (config?.exclude) {
118
+ messages.push(formatList("exclude filters from config", config.exclude));
119
+ }
120
+ if (cliOptions.include) {
121
+ messages.push(formatList("apply include filters from CLI", cliOptions.include));
122
+ }
123
+ if (cliOptions.exclude) {
124
+ messages.push(formatList("apply exclude filters from CLI", cliOptions.exclude));
125
+ }
126
+ if (cliOptions.visibility) {
127
+ messages.push(formatList("apply visibility filter from CLI", cliOptions.visibility));
128
+ }
129
+ const resolved = mergeFilters(config, cliOptions);
130
+ if (!resolved.include && !resolved.exclude && !cliOptions.visibility) {
131
+ return { messages };
132
+ }
133
+ const source = resolved.source === "override" ? "cli" : resolved.source;
134
+ return {
135
+ include: resolved.include,
136
+ exclude: resolved.exclude,
137
+ visibility: cliOptions.visibility,
138
+ source,
139
+ messages
140
+ };
141
+ };
142
+
143
+ // src/utils/progress/colors.ts
94
144
  import chalk2 from "chalk";
95
- import { Worker } from "node:worker_threads";
96
145
  var colors = {
97
- success: chalk.green,
98
- error: chalk.red,
99
- warning: chalk.yellow,
100
- info: chalk.cyan,
101
- muted: chalk.gray,
102
- bold: chalk.bold,
103
- dim: chalk.dim,
104
- underline: chalk.underline,
105
- primary: chalk.cyan,
106
- secondary: chalk.magenta,
107
- path: chalk.cyan,
108
- number: chalk.yellow,
109
- code: chalk.gray
146
+ success: chalk2.green,
147
+ error: chalk2.red,
148
+ warning: chalk2.yellow,
149
+ info: chalk2.cyan,
150
+ muted: chalk2.gray,
151
+ bold: chalk2.bold,
152
+ dim: chalk2.dim,
153
+ underline: chalk2.underline,
154
+ primary: chalk2.cyan,
155
+ secondary: chalk2.magenta,
156
+ path: chalk2.cyan,
157
+ number: chalk2.yellow,
158
+ code: chalk2.gray
110
159
  };
111
160
  var symbols = {
112
161
  success: "✓",
@@ -145,6 +194,10 @@ var prefix = {
145
194
  warning: colors.warning(symbols.warning),
146
195
  info: colors.info(symbols.info)
147
196
  };
197
+ // src/utils/progress/spinner.ts
198
+ import chalk3 from "chalk";
199
+
200
+ // src/utils/progress/utils.ts
148
201
  function isTTY() {
149
202
  return Boolean(process.stdout.isTTY);
150
203
  }
@@ -166,18 +219,6 @@ function getTerminalWidth() {
166
219
  const width = process.stdout.columns || DEFAULT_TERMINAL_WIDTH;
167
220
  return Math.max(width, MIN_TERMINAL_WIDTH);
168
221
  }
169
- function formatDuration(ms) {
170
- if (ms < 1000) {
171
- return `${ms}ms`;
172
- }
173
- const seconds = ms / 1000;
174
- if (seconds < 60) {
175
- return `${seconds.toFixed(1)}s`;
176
- }
177
- const minutes = Math.floor(seconds / 60);
178
- const remainingSeconds = Math.floor(seconds % 60);
179
- return `${minutes}m ${remainingSeconds}s`;
180
- }
181
222
  var cursor = {
182
223
  hide: "\x1B[?25l",
183
224
  show: "\x1B[?25h",
@@ -196,11 +237,6 @@ function clearLine() {
196
237
  process.stdout.write(cursor.clearLine + cursor.left);
197
238
  }
198
239
  }
199
- function moveCursorUp(lines = 1) {
200
- if (isTTY()) {
201
- process.stdout.write(cursor.up(lines));
202
- }
203
- }
204
240
  function hideCursor() {
205
241
  if (isTTY()) {
206
242
  process.stdout.write(cursor.hide);
@@ -221,391 +257,15 @@ function stripAnsi(text) {
221
257
  return text.replace(ANSI_REGEX, "");
222
258
  }
223
259
 
224
- class MultiProgress {
225
- bars = new Map;
226
- barOrder = [];
227
- options;
228
- spinnerFrames;
229
- spinnerIndex = 0;
230
- timer = null;
231
- lastRenderedLines = 0;
232
- symbols = getSymbols(supportsUnicode());
233
- sigintHandler = null;
234
- filledChar;
235
- emptyChar;
236
- constructor(options = {}) {
237
- this.options = {
238
- barWidth: options.barWidth,
239
- showPercent: options.showPercent ?? true,
240
- showCount: options.showCount ?? true,
241
- spinnerInterval: options.spinnerInterval ?? 80
242
- };
243
- this.spinnerFrames = supportsUnicode() ? ["◐", "◓", "◑", "◒"] : ["-", "\\", "|", "/"];
244
- const unicode = supportsUnicode();
245
- this.filledChar = unicode ? "█" : "#";
246
- this.emptyChar = unicode ? "░" : "-";
247
- }
248
- start() {
249
- if (!isInteractive())
250
- return this;
251
- hideCursor();
252
- this.setupSignalHandler();
253
- this.timer = setInterval(() => {
254
- if (this.bars.size > 0 && [...this.bars.values()].some((b) => b.status === "active")) {
255
- this.spinnerIndex = (this.spinnerIndex + 1) % this.spinnerFrames.length;
256
- this.render();
257
- }
258
- }, this.options.spinnerInterval);
259
- return this;
260
- }
261
- add(config) {
262
- const state = {
263
- id: config.id,
264
- label: config.label,
265
- total: config.total ?? 100,
266
- current: config.current ?? 0,
267
- status: "active",
268
- startTime: Date.now()
269
- };
270
- this.bars.set(config.id, state);
271
- if (!this.barOrder.includes(config.id)) {
272
- this.barOrder.push(config.id);
273
- }
274
- if (!isInteractive()) {
275
- console.log(`${this.symbols.bullet} ${config.label}`);
276
- } else {
277
- this.render();
278
- }
279
- return this;
280
- }
281
- update(id, current, label) {
282
- const bar = this.bars.get(id);
283
- if (!bar)
284
- return this;
285
- bar.current = Math.min(current, bar.total);
286
- if (label !== undefined)
287
- bar.label = label;
288
- if (isInteractive()) {
289
- this.render();
290
- }
291
- return this;
292
- }
293
- increment(id, amount = 1) {
294
- const bar = this.bars.get(id);
295
- if (!bar)
296
- return this;
297
- return this.update(id, bar.current + amount);
298
- }
299
- complete(id, label) {
300
- const bar = this.bars.get(id);
301
- if (!bar)
302
- return this;
303
- bar.status = "completed";
304
- bar.current = bar.total;
305
- if (label !== undefined)
306
- bar.label = label;
307
- if (!isInteractive()) {
308
- console.log(`${colors.success(this.symbols.success)} ${bar.label}`);
309
- } else {
310
- this.render();
311
- }
312
- return this;
313
- }
314
- fail(id, label) {
315
- const bar = this.bars.get(id);
316
- if (!bar)
317
- return this;
318
- bar.status = "failed";
319
- if (label !== undefined)
320
- bar.label = label;
321
- if (!isInteractive()) {
322
- console.log(`${colors.error(this.symbols.error)} ${bar.label}`);
323
- } else {
324
- this.render();
325
- }
326
- return this;
327
- }
328
- remove(id) {
329
- this.bars.delete(id);
330
- this.barOrder = this.barOrder.filter((i) => i !== id);
331
- if (isInteractive()) {
332
- this.render();
333
- }
334
- return this;
335
- }
336
- get(id) {
337
- return this.bars.get(id);
338
- }
339
- get allDone() {
340
- if (this.bars.size === 0)
341
- return true;
342
- return [...this.bars.values()].every((b) => b.status !== "active");
343
- }
344
- stop() {
345
- if (this.timer) {
346
- clearInterval(this.timer);
347
- this.timer = null;
348
- }
349
- this.cleanup();
350
- return this;
351
- }
352
- render() {
353
- if (!isTTY())
354
- return;
355
- this.clearOutput();
356
- const width = getTerminalWidth();
357
- const lines = [];
358
- for (const id of this.barOrder) {
359
- const bar = this.bars.get(id);
360
- if (!bar)
361
- continue;
362
- const line = this.renderBar(bar, width);
363
- lines.push(line);
364
- }
365
- if (lines.length > 0) {
366
- process.stdout.write(lines.join(`
367
- `));
368
- this.lastRenderedLines = lines.length;
369
- }
370
- }
371
- renderBar(bar, termWidth) {
372
- const parts = [];
373
- let symbol;
374
- switch (bar.status) {
375
- case "completed":
376
- symbol = colors.success(this.symbols.success);
377
- break;
378
- case "failed":
379
- symbol = colors.error(this.symbols.error);
380
- break;
381
- default:
382
- symbol = colors.primary(this.spinnerFrames[this.spinnerIndex]);
383
- }
384
- parts.push(symbol);
385
- parts.push(bar.label);
386
- const suffixParts = [];
387
- if (this.options.showPercent) {
388
- const pct = bar.total === 0 ? 0 : Math.round(bar.current / bar.total * 100);
389
- suffixParts.push(`${pct}%`);
390
- }
391
- if (this.options.showCount) {
392
- suffixParts.push(`${bar.current}/${bar.total}`);
393
- }
394
- const suffix = suffixParts.length > 0 ? ` ${suffixParts.join(" ")}` : "";
395
- const labelLen = stripAnsi(parts.join(" ")).length + 1;
396
- const bracketLen = 2;
397
- const suffixLen = stripAnsi(suffix).length;
398
- const minBarWidth = 10;
399
- const availableWidth = termWidth - labelLen - bracketLen - suffixLen - 1;
400
- const barWidth = this.options.barWidth ?? Math.max(minBarWidth, Math.min(30, availableWidth));
401
- const filledWidth = Math.round(bar.current / bar.total * barWidth);
402
- const emptyWidth = barWidth - filledWidth;
403
- const barViz = `[${this.filledChar.repeat(filledWidth)}${this.emptyChar.repeat(emptyWidth)}]`;
404
- parts.push(barViz);
405
- return truncate(parts.join(" ") + suffix, termWidth);
406
- }
407
- clearOutput() {
408
- if (!isTTY() || this.lastRenderedLines === 0)
409
- return;
410
- for (let i = 0;i < this.lastRenderedLines; i++) {
411
- if (i > 0)
412
- process.stdout.write(cursor.up(1));
413
- clearLine();
414
- }
415
- this.lastRenderedLines = 0;
416
- }
417
- setupSignalHandler() {
418
- this.sigintHandler = () => {
419
- this.cleanup();
420
- process.exit(130);
421
- };
422
- process.on("SIGINT", this.sigintHandler);
423
- }
424
- cleanup() {
425
- if (this.sigintHandler) {
426
- process.removeListener("SIGINT", this.sigintHandler);
427
- this.sigintHandler = null;
428
- }
429
- showCursor();
430
- if (isTTY() && this.lastRenderedLines > 0) {
431
- process.stdout.write(`
432
- `);
433
- }
434
- }
435
- }
436
- class ProgressBar {
437
- total;
438
- current;
439
- label;
440
- width;
441
- showPercent;
442
- showCount;
443
- showETA;
444
- filledChar;
445
- emptyChar;
446
- startTime = null;
447
- lastRender = "";
448
- symbols = getSymbols(supportsUnicode());
449
- sigintHandler = null;
450
- isComplete = false;
451
- constructor(options = {}) {
452
- this.total = options.total ?? 100;
453
- this.current = options.current ?? 0;
454
- this.label = options.label ?? "";
455
- this.width = options.width;
456
- this.showPercent = options.showPercent ?? true;
457
- this.showCount = options.showCount ?? true;
458
- this.showETA = options.showETA ?? true;
459
- const unicode = supportsUnicode();
460
- this.filledChar = options.chars?.filled ?? (unicode ? "█" : "#");
461
- this.emptyChar = options.chars?.empty ?? (unicode ? "░" : "-");
462
- }
463
- start(label) {
464
- if (label !== undefined)
465
- this.label = label;
466
- this.startTime = Date.now();
467
- this.current = 0;
468
- this.isComplete = false;
469
- if (!isInteractive()) {
470
- console.log(`${this.symbols.bullet} ${this.label}`);
471
- return this;
472
- }
473
- hideCursor();
474
- this.setupSignalHandler();
475
- this.render();
476
- return this;
477
- }
478
- update(current) {
479
- this.current = Math.min(current, this.total);
480
- if (isInteractive()) {
481
- this.render();
482
- }
483
- return this;
484
- }
485
- increment(amount = 1) {
486
- return this.update(this.current + amount);
487
- }
488
- setLabel(label) {
489
- this.label = label;
490
- if (isInteractive()) {
491
- this.render();
492
- }
493
- return this;
494
- }
495
- setTotal(total) {
496
- this.total = total;
497
- if (isInteractive()) {
498
- this.render();
499
- }
500
- return this;
501
- }
502
- complete(label) {
503
- if (label !== undefined)
504
- this.label = label;
505
- this.current = this.total;
506
- this.isComplete = true;
507
- if (!isInteractive()) {
508
- console.log(`${colors.success(this.symbols.success)} ${this.label}`);
509
- } else {
510
- clearLine();
511
- process.stdout.write(`${colors.success(this.symbols.success)} ${this.label}
512
- `);
513
- }
514
- this.cleanup();
515
- return this;
516
- }
517
- fail(label) {
518
- if (label !== undefined)
519
- this.label = label;
520
- this.isComplete = true;
521
- if (!isInteractive()) {
522
- console.log(`${colors.error(this.symbols.error)} ${this.label}`);
523
- } else {
524
- clearLine();
525
- process.stdout.write(`${colors.error(this.symbols.error)} ${this.label}
526
- `);
527
- }
528
- this.cleanup();
529
- return this;
530
- }
531
- get percentage() {
532
- return this.total === 0 ? 0 : Math.round(this.current / this.total * 100);
533
- }
534
- get isDone() {
535
- return this.isComplete || this.current >= this.total;
536
- }
537
- render() {
538
- if (!isTTY())
539
- return;
540
- const termWidth = getTerminalWidth();
541
- const parts = [];
542
- if (this.label) {
543
- parts.push(this.label);
544
- }
545
- const suffixParts = [];
546
- if (this.showPercent) {
547
- suffixParts.push(`${this.percentage}%`);
548
- }
549
- if (this.showCount) {
550
- suffixParts.push(`${this.current}/${this.total}`);
551
- }
552
- if (this.showETA && this.startTime) {
553
- const eta = this.calculateETA();
554
- if (eta)
555
- suffixParts.push(eta);
556
- }
557
- const suffix = suffixParts.length > 0 ? ` ${suffixParts.join(" ")}` : "";
558
- const labelLen = this.label ? stripAnsi(this.label).length + 1 : 0;
559
- const bracketLen = 2;
560
- const suffixLen = stripAnsi(suffix).length;
561
- const minBarWidth = 10;
562
- const availableWidth = termWidth - labelLen - bracketLen - suffixLen - 1;
563
- const barWidth = this.width ?? Math.max(minBarWidth, Math.min(40, availableWidth));
564
- const filledWidth = Math.round(this.current / this.total * barWidth);
565
- const emptyWidth = barWidth - filledWidth;
566
- const bar = `[${this.filledChar.repeat(filledWidth)}${this.emptyChar.repeat(emptyWidth)}]`;
567
- parts.push(bar);
568
- const line = truncate(parts.join(" ") + suffix, termWidth);
569
- if (line !== this.lastRender) {
570
- clearLine();
571
- process.stdout.write(line);
572
- this.lastRender = line;
573
- }
574
- }
575
- calculateETA() {
576
- if (!this.startTime || this.current === 0)
577
- return null;
578
- const elapsed = Date.now() - this.startTime;
579
- if (elapsed < 1000)
580
- return null;
581
- const rate = this.current / elapsed;
582
- const remaining = this.total - this.current;
583
- const etaMs = remaining / rate;
584
- return `ETA ${formatDuration(etaMs)}`;
585
- }
586
- setupSignalHandler() {
587
- this.sigintHandler = () => {
588
- this.cleanup();
589
- process.exit(130);
590
- };
591
- process.on("SIGINT", this.sigintHandler);
592
- }
593
- cleanup() {
594
- if (this.sigintHandler) {
595
- process.removeListener("SIGINT", this.sigintHandler);
596
- this.sigintHandler = null;
597
- }
598
- showCursor();
599
- }
600
- }
260
+ // src/utils/progress/spinner.ts
601
261
  var spinnerColors = {
602
- cyan: chalk2.cyan,
603
- yellow: chalk2.yellow,
604
- green: chalk2.green,
605
- red: chalk2.red,
606
- magenta: chalk2.magenta,
607
- blue: chalk2.blue,
608
- white: chalk2.white
262
+ cyan: chalk3.cyan,
263
+ yellow: chalk3.yellow,
264
+ green: chalk3.green,
265
+ red: chalk3.red,
266
+ magenta: chalk3.magenta,
267
+ blue: chalk3.blue,
268
+ white: chalk3.white
609
269
  };
610
270
  var FRAME_SETS = {
611
271
  dots: ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"],
@@ -625,13 +285,11 @@ class Spinner {
625
285
  symbols = getSymbols(supportsUnicode());
626
286
  lastRenderedLines = 0;
627
287
  sigintHandler = null;
628
- animate;
629
288
  constructor(options = {}) {
630
289
  this.label = options.label ?? "";
631
290
  this.detail = options.detail;
632
291
  this.interval = options.interval ?? 80;
633
292
  this.colorFn = spinnerColors[options.color ?? "cyan"];
634
- this.animate = options.animate ?? true;
635
293
  const style = options.style ?? "circle";
636
294
  this.frames = supportsUnicode() ? FRAME_SETS[style] : ASCII_FRAME_SET;
637
295
  }
@@ -643,7 +301,7 @@ class Spinner {
643
301
  this.state = "spinning";
644
302
  this.frameIndex = 0;
645
303
  this.lastRenderedLines = 0;
646
- if (!isInteractive() || !this.animate) {
304
+ if (!isInteractive()) {
647
305
  console.log(`${this.symbols.bullet} ${this.label}`);
648
306
  return this;
649
307
  }
@@ -701,12 +359,14 @@ class Spinner {
701
359
  this.timer = null;
702
360
  }
703
361
  this.state = state;
704
- const symbol = state === "success" ? this.symbols.success : this.symbols.error;
705
- const colorFn = state === "success" ? colors.success : colors.error;
706
- if (!isInteractive() || !this.animate) {
362
+ if (!isInteractive()) {
363
+ const symbol = state === "success" ? this.symbols.success : this.symbols.error;
364
+ const colorFn = state === "success" ? colors.success : colors.error;
707
365
  console.log(`${colorFn(symbol)} ${this.label}`);
708
366
  } else {
709
367
  this.clearOutput();
368
+ const symbol = state === "success" ? this.symbols.success : this.symbols.error;
369
+ const colorFn = state === "success" ? colors.success : colors.error;
710
370
  process.stdout.write(`${colorFn(symbol)} ${this.label}
711
371
  `);
712
372
  }
@@ -756,206 +416,7 @@ ${detailLine}`);
756
416
  function spinner(label, options) {
757
417
  return new Spinner({ ...options, label }).start();
758
418
  }
759
-
760
- class StepProgress {
761
- steps = [];
762
- showNumbers;
763
- spinnerInterval;
764
- spinnerFrames;
765
- spinnerIndex = 0;
766
- timer = null;
767
- symbols = getSymbols(supportsUnicode());
768
- lastRenderedLines = 0;
769
- sigintHandler = null;
770
- constructor(options = {}) {
771
- this.showNumbers = options.showNumbers ?? true;
772
- this.spinnerInterval = options.spinnerInterval ?? 80;
773
- this.spinnerFrames = supportsUnicode() ? ["◐", "◓", "◑", "◒"] : ["-", "\\", "|", "/"];
774
- if (options.steps) {
775
- this.steps = options.steps.map((label) => ({ label, status: "pending" }));
776
- }
777
- }
778
- start() {
779
- if (!isInteractive())
780
- return this;
781
- hideCursor();
782
- this.setupSignalHandler();
783
- this.render();
784
- this.timer = setInterval(() => {
785
- if (this.steps.some((s) => s.status === "active")) {
786
- this.spinnerIndex = (this.spinnerIndex + 1) % this.spinnerFrames.length;
787
- this.render();
788
- }
789
- }, this.spinnerInterval);
790
- return this;
791
- }
792
- addStep(label) {
793
- this.steps.push({ label, status: "pending" });
794
- if (isInteractive())
795
- this.render();
796
- return this;
797
- }
798
- startStep(index) {
799
- if (index >= 0 && index < this.steps.length) {
800
- this.steps[index].status = "active";
801
- this.steps[index].startTime = Date.now();
802
- if (isInteractive()) {
803
- this.render();
804
- } else {
805
- const step = this.steps[index];
806
- const prefix2 = this.showNumbers ? `[${index + 1}/${this.steps.length}] ` : "";
807
- console.log(`${this.symbols.bullet} ${prefix2}${step.label}...`);
808
- }
809
- }
810
- return this;
811
- }
812
- completeStep(index) {
813
- if (index >= 0 && index < this.steps.length) {
814
- this.steps[index].status = "completed";
815
- this.steps[index].endTime = Date.now();
816
- if (isInteractive()) {
817
- this.render();
818
- } else {
819
- const step = this.steps[index];
820
- const duration = this.getStepDuration(step);
821
- const prefix2 = this.showNumbers ? `[${index + 1}/${this.steps.length}] ` : "";
822
- console.log(`${colors.success(this.symbols.success)} ${prefix2}${step.label}${duration}`);
823
- }
824
- }
825
- return this;
826
- }
827
- failStep(index) {
828
- if (index >= 0 && index < this.steps.length) {
829
- this.steps[index].status = "failed";
830
- this.steps[index].endTime = Date.now();
831
- if (isInteractive()) {
832
- this.render();
833
- } else {
834
- const step = this.steps[index];
835
- const prefix2 = this.showNumbers ? `[${index + 1}/${this.steps.length}] ` : "";
836
- console.log(`${colors.error(this.symbols.error)} ${prefix2}${step.label}`);
837
- }
838
- }
839
- return this;
840
- }
841
- skipStep(index) {
842
- if (index >= 0 && index < this.steps.length) {
843
- this.steps[index].status = "skipped";
844
- if (isInteractive())
845
- this.render();
846
- }
847
- return this;
848
- }
849
- async run(tasks) {
850
- this.steps = tasks.map((t) => ({ label: t.label, status: "pending" }));
851
- this.start();
852
- const results = [];
853
- let failed = false;
854
- for (let i = 0;i < tasks.length; i++) {
855
- if (failed) {
856
- this.skipStep(i);
857
- continue;
858
- }
859
- this.startStep(i);
860
- try {
861
- results.push(await tasks[i].task());
862
- this.completeStep(i);
863
- } catch {
864
- this.failStep(i);
865
- failed = true;
866
- }
867
- }
868
- this.stop();
869
- return { results, failed };
870
- }
871
- stop() {
872
- if (this.timer) {
873
- clearInterval(this.timer);
874
- this.timer = null;
875
- }
876
- this.cleanup();
877
- return this;
878
- }
879
- get currentStepIndex() {
880
- const activeIdx = this.steps.findIndex((s) => s.status === "active");
881
- if (activeIdx >= 0)
882
- return activeIdx;
883
- return this.steps.findIndex((s) => s.status === "pending");
884
- }
885
- render() {
886
- if (!isTTY())
887
- return;
888
- if (this.lastRenderedLines > 0) {
889
- moveCursorUp(this.lastRenderedLines - 1);
890
- for (let i = 0;i < this.lastRenderedLines; i++) {
891
- clearLine();
892
- if (i < this.lastRenderedLines - 1) {
893
- process.stdout.write(cursor.down(1));
894
- }
895
- }
896
- moveCursorUp(this.lastRenderedLines - 1);
897
- }
898
- const width = getTerminalWidth();
899
- const lines = [];
900
- for (let i = 0;i < this.steps.length; i++) {
901
- const step = this.steps[i];
902
- const prefix2 = this.showNumbers ? `[${i + 1}/${this.steps.length}] ` : "";
903
- const duration = this.getStepDuration(step);
904
- let symbol;
905
- let text;
906
- switch (step.status) {
907
- case "completed":
908
- symbol = colors.success(this.symbols.success);
909
- text = `${prefix2}${step.label}${duration}`;
910
- break;
911
- case "failed":
912
- symbol = colors.error(this.symbols.error);
913
- text = `${prefix2}${step.label}`;
914
- break;
915
- case "active":
916
- symbol = colors.primary(this.spinnerFrames[this.spinnerIndex]);
917
- text = `${prefix2}${step.label}`;
918
- break;
919
- case "skipped":
920
- symbol = colors.muted(this.symbols.bullet);
921
- text = colors.muted(`${prefix2}${step.label} (skipped)`);
922
- break;
923
- default:
924
- symbol = colors.muted("○");
925
- text = colors.muted(`${prefix2}${step.label}`);
926
- }
927
- lines.push(truncate(`${symbol} ${text}`, width));
928
- }
929
- process.stdout.write(lines.join(`
930
- `));
931
- this.lastRenderedLines = lines.length;
932
- }
933
- getStepDuration(step) {
934
- if (step.startTime && step.endTime) {
935
- const ms = step.endTime - step.startTime;
936
- return colors.muted(` (${formatDuration(ms)})`);
937
- }
938
- return "";
939
- }
940
- setupSignalHandler() {
941
- this.sigintHandler = () => {
942
- this.cleanup();
943
- process.exit(130);
944
- };
945
- process.on("SIGINT", this.sigintHandler);
946
- }
947
- cleanup() {
948
- if (this.sigintHandler) {
949
- process.removeListener("SIGINT", this.sigintHandler);
950
- this.sigintHandler = null;
951
- }
952
- showCursor();
953
- if (isTTY() && this.lastRenderedLines > 0) {
954
- process.stdout.write(`
955
- `);
956
- }
957
- }
958
- }
419
+ // src/utils/progress/summary.ts
959
420
  class Summary {
960
421
  items = [];
961
422
  title;
@@ -1078,58 +539,6 @@ class Summary {
1078
539
  function summary(options) {
1079
540
  return new Summary(options);
1080
541
  }
1081
-
1082
- // src/utils/filter-options.ts
1083
- import { mergeFilters, parseListFlag } from "@doccov/sdk";
1084
- import chalk3 from "chalk";
1085
- var parseVisibilityFlag = (value) => {
1086
- if (!value)
1087
- return;
1088
- const validTags = ["public", "beta", "alpha", "internal"];
1089
- const parsed = parseListFlag(value);
1090
- if (!parsed)
1091
- return;
1092
- const result = [];
1093
- for (const tag of parsed) {
1094
- const lower = tag.toLowerCase();
1095
- if (validTags.includes(lower)) {
1096
- result.push(lower);
1097
- }
1098
- }
1099
- return result.length > 0 ? result : undefined;
1100
- };
1101
- var formatList = (label, values) => `${label}: ${values.map((value) => chalk3.cyan(value)).join(", ")}`;
1102
- var mergeFilterOptions = (config, cliOptions) => {
1103
- const messages = [];
1104
- if (config?.include) {
1105
- messages.push(formatList("include filters from config", config.include));
1106
- }
1107
- if (config?.exclude) {
1108
- messages.push(formatList("exclude filters from config", config.exclude));
1109
- }
1110
- if (cliOptions.include) {
1111
- messages.push(formatList("apply include filters from CLI", cliOptions.include));
1112
- }
1113
- if (cliOptions.exclude) {
1114
- messages.push(formatList("apply exclude filters from CLI", cliOptions.exclude));
1115
- }
1116
- if (cliOptions.visibility) {
1117
- messages.push(formatList("apply visibility filter from CLI", cliOptions.visibility));
1118
- }
1119
- const resolved = mergeFilters(config, cliOptions);
1120
- if (!resolved.include && !resolved.exclude && !cliOptions.visibility) {
1121
- return { messages };
1122
- }
1123
- const source = resolved.source === "override" ? "cli" : resolved.source;
1124
- return {
1125
- include: resolved.include,
1126
- exclude: resolved.exclude,
1127
- visibility: cliOptions.visibility,
1128
- source,
1129
- messages
1130
- };
1131
- };
1132
-
1133
542
  // src/utils/validation.ts
1134
543
  function clampPercentage(value, fallback = 80) {
1135
544
  if (Number.isNaN(value))
@@ -1157,7 +566,7 @@ import {
1157
566
  previewForgottenExportFixes,
1158
567
  serializeJSDoc
1159
568
  } from "@doccov/sdk";
1160
- import chalk5 from "chalk";
569
+ import chalk4 from "chalk";
1161
570
 
1162
571
  // src/commands/check/utils.ts
1163
572
  import * as fs from "node:fs";
@@ -1231,13 +640,13 @@ async function handleFixes(openpkg, doccov, options, deps) {
1231
640
  }
1232
641
  const { fixable, nonFixable } = categorizeDrifts(allDrifts.map((d) => d.drift));
1233
642
  if (fixable.length === 0) {
1234
- log(chalk5.yellow(`Found ${nonFixable.length} drift issue(s), but none are auto-fixable.`));
643
+ log(chalk4.yellow(`Found ${nonFixable.length} drift issue(s), but none are auto-fixable.`));
1235
644
  return { fixedDriftKeys, editsApplied: 0, filesModified: 0, forgottenExportsFixed: 0 };
1236
645
  }
1237
646
  log("");
1238
- log(chalk5.bold(`Found ${fixable.length} fixable issue(s)`));
647
+ log(chalk4.bold(`Found ${fixable.length} fixable issue(s)`));
1239
648
  if (nonFixable.length > 0) {
1240
- log(chalk5.gray(`(${nonFixable.length} non-fixable issue(s) skipped)`));
649
+ log(chalk4.gray(`(${nonFixable.length} non-fixable issue(s) skipped)`));
1241
650
  }
1242
651
  log("");
1243
652
  const groupedDrifts = groupByExport(allDrifts.filter((d) => fixable.includes(d.drift)));
@@ -1270,20 +679,20 @@ async function handleFixes(openpkg, doccov, options, deps) {
1270
679
  const applyResult = await applyEdits(edits);
1271
680
  if (applyResult.errors.length > 0) {
1272
681
  for (const err of applyResult.errors) {
1273
- error(chalk5.red(` ${err.file}: ${err.error}`));
682
+ error(chalk4.red(` ${err.file}: ${err.error}`));
1274
683
  }
1275
684
  }
1276
685
  const totalFixes = Array.from(editsByFile.values()).reduce((sum, fileEdits) => sum + fileEdits.reduce((s, e) => s + e.fixes.length, 0), 0);
1277
686
  log("");
1278
- log(chalk5.green(`✓ Applied ${totalFixes} fix(es) to ${applyResult.filesModified} file(s)`));
687
+ log(chalk4.green(`✓ Applied ${totalFixes} fix(es) to ${applyResult.filesModified} file(s)`));
1279
688
  for (const [filePath, fileEdits] of editsByFile) {
1280
689
  const relativePath = path3.relative(targetDir, filePath);
1281
690
  const fixCount = fileEdits.reduce((s, e) => s + e.fixes.length, 0);
1282
- log(chalk5.dim(` ${relativePath} (${fixCount} fixes)`));
691
+ log(chalk4.dim(` ${relativePath} (${fixCount} fixes)`));
1283
692
  }
1284
693
  if (options.healthScore !== undefined) {
1285
694
  log("");
1286
- log(chalk5.cyan("Run doccov check again to see updated health score"));
695
+ log(chalk4.cyan("Run doccov check again to see updated health score"));
1287
696
  }
1288
697
  return {
1289
698
  fixedDriftKeys,
@@ -1310,7 +719,7 @@ async function handleForgottenExportFixes(doccov, options, deps) {
1310
719
  return { fixesApplied: 0, filesModified: 0 };
1311
720
  }
1312
721
  log("");
1313
- log(chalk5.bold(`Found ${fixes.length} forgotten export(s) to fix`));
722
+ log(chalk4.bold(`Found ${fixes.length} forgotten export(s) to fix`));
1314
723
  if (isPreview) {
1315
724
  displayForgottenExportPreview(fixes, targetDir, log);
1316
725
  return { fixesApplied: 0, filesModified: 0 };
@@ -1318,12 +727,12 @@ async function handleForgottenExportFixes(doccov, options, deps) {
1318
727
  const result = await applyForgottenExportFixes(fixes);
1319
728
  if (result.errors.length > 0) {
1320
729
  for (const err of result.errors) {
1321
- error(chalk5.red(` ${err.file}: ${err.error}`));
730
+ error(chalk4.red(` ${err.file}: ${err.error}`));
1322
731
  }
1323
732
  }
1324
733
  if (result.fixesApplied > 0) {
1325
734
  log("");
1326
- log(chalk5.green(`✓ Added ${result.fixesApplied} export(s) to ${result.filesModified} file(s)`));
735
+ log(chalk4.green(`✓ Added ${result.fixesApplied} export(s) to ${result.filesModified} file(s)`));
1327
736
  const grouped = new Map;
1328
737
  for (const fix of fixes) {
1329
738
  const relativePath = path3.relative(targetDir, fix.targetFile);
@@ -1332,45 +741,45 @@ async function handleForgottenExportFixes(doccov, options, deps) {
1332
741
  grouped.set(relativePath, types);
1333
742
  }
1334
743
  for (const [file, types] of grouped) {
1335
- log(chalk5.dim(` ${file}: ${types.join(", ")}`));
744
+ log(chalk4.dim(` ${file}: ${types.join(", ")}`));
1336
745
  }
1337
746
  }
1338
747
  return { fixesApplied: result.fixesApplied, filesModified: result.filesModified };
1339
748
  }
1340
749
  function displayForgottenExportPreview(fixes, targetDir, log) {
1341
- log(chalk5.bold("Preview - forgotten exports that would be added:"));
750
+ log(chalk4.bold("Preview - forgotten exports that would be added:"));
1342
751
  log("");
1343
752
  const previews = previewForgottenExportFixes(fixes);
1344
753
  for (const [filePath, preview] of previews) {
1345
754
  const relativePath = path3.relative(targetDir, filePath);
1346
- log(chalk5.cyan(`${relativePath}:${preview.insertLine + 1}`));
755
+ log(chalk4.cyan(`${relativePath}:${preview.insertLine + 1}`));
1347
756
  log("");
1348
757
  for (const stmt of preview.statements) {
1349
- log(chalk5.green(` + ${stmt}`));
758
+ log(chalk4.green(` + ${stmt}`));
1350
759
  }
1351
760
  log("");
1352
761
  }
1353
- log(chalk5.yellow(`${fixes.length} export(s) would be added.`));
1354
- log(chalk5.gray("Run with --fix to apply these changes."));
762
+ log(chalk4.yellow(`${fixes.length} export(s) would be added.`));
763
+ log(chalk4.gray("Run with --fix to apply these changes."));
1355
764
  }
1356
765
  function generateEditForExport(exp, drifts, targetDir, log) {
1357
766
  if (!exp.source?.file) {
1358
- log(chalk5.gray(` Skipping ${exp.name}: no source location`));
767
+ log(chalk4.gray(` Skipping ${exp.name}: no source location`));
1359
768
  return null;
1360
769
  }
1361
770
  if (exp.source.file.endsWith(".d.ts")) {
1362
- log(chalk5.gray(` Skipping ${exp.name}: declaration file`));
771
+ log(chalk4.gray(` Skipping ${exp.name}: declaration file`));
1363
772
  return null;
1364
773
  }
1365
774
  const filePath = path3.resolve(targetDir, exp.source.file);
1366
775
  if (!fs2.existsSync(filePath)) {
1367
- log(chalk5.gray(` Skipping ${exp.name}: file not found`));
776
+ log(chalk4.gray(` Skipping ${exp.name}: file not found`));
1368
777
  return null;
1369
778
  }
1370
779
  const sourceFile = createSourceFile(filePath);
1371
780
  const location = findJSDocLocation(sourceFile, exp.name, exp.source.line);
1372
781
  if (!location) {
1373
- log(chalk5.gray(` Skipping ${exp.name}: could not find declaration`));
782
+ log(chalk4.gray(` Skipping ${exp.name}: could not find declaration`));
1374
783
  return null;
1375
784
  }
1376
785
  let existingPatch = {};
@@ -1395,13 +804,13 @@ function generateEditForExport(exp, drifts, targetDir, log) {
1395
804
  return { filePath, edit, fixes, existingPatch };
1396
805
  }
1397
806
  function displayPreview(editsByFile, targetDir, log) {
1398
- log(chalk5.bold("Preview - changes that would be made:"));
807
+ log(chalk4.bold("Preview - changes that would be made:"));
1399
808
  log("");
1400
809
  for (const [filePath, fileEdits] of editsByFile) {
1401
810
  const relativePath = path3.relative(targetDir, filePath);
1402
811
  for (const { export: exp, edit, fixes } of fileEdits) {
1403
- log(chalk5.cyan(`${relativePath}:${edit.startLine + 1}`));
1404
- log(chalk5.bold(` ${exp.name}`));
812
+ log(chalk4.cyan(`${relativePath}:${edit.startLine + 1}`));
813
+ log(chalk4.bold(` ${exp.name}`));
1405
814
  log("");
1406
815
  if (edit.hasExisting && edit.existingJSDoc) {
1407
816
  const oldLines = edit.existingJSDoc.split(`
@@ -1409,26 +818,26 @@ function displayPreview(editsByFile, targetDir, log) {
1409
818
  const newLines = edit.newJSDoc.split(`
1410
819
  `);
1411
820
  for (const line of oldLines) {
1412
- log(chalk5.red(` - ${line}`));
821
+ log(chalk4.red(` - ${line}`));
1413
822
  }
1414
823
  for (const line of newLines) {
1415
- log(chalk5.green(` + ${line}`));
824
+ log(chalk4.green(` + ${line}`));
1416
825
  }
1417
826
  } else {
1418
827
  const newLines = edit.newJSDoc.split(`
1419
828
  `);
1420
829
  for (const line of newLines) {
1421
- log(chalk5.green(` + ${line}`));
830
+ log(chalk4.green(` + ${line}`));
1422
831
  }
1423
832
  }
1424
833
  log("");
1425
- log(chalk5.dim(` Fixes: ${fixes.map((f) => f.description).join(", ")}`));
834
+ log(chalk4.dim(` Fixes: ${fixes.map((f) => f.description).join(", ")}`));
1426
835
  log("");
1427
836
  }
1428
837
  }
1429
838
  const totalFixes = Array.from(editsByFile.values()).reduce((sum, fileEdits) => sum + fileEdits.reduce((s, e) => s + e.fixes.length, 0), 0);
1430
- log(chalk5.yellow(`${totalFixes} fix(es) across ${editsByFile.size} file(s) would be applied.`));
1431
- log(chalk5.gray("Run with --fix to apply these changes."));
839
+ log(chalk4.yellow(`${totalFixes} fix(es) across ${editsByFile.size} file(s) would be applied.`));
840
+ log(chalk4.gray("Run with --fix to apply these changes."));
1432
841
  }
1433
842
 
1434
843
  // src/commands/check/output.ts
@@ -1885,7 +1294,7 @@ function computeStats(openpkg, doccov) {
1885
1294
  import * as fs3 from "node:fs";
1886
1295
  import * as path5 from "node:path";
1887
1296
  import { DEFAULT_REPORT_DIR, getReportPath } from "@doccov/sdk";
1888
- import chalk6 from "chalk";
1297
+ import chalk5 from "chalk";
1889
1298
  function writeReport(options) {
1890
1299
  const { format, content, outputPath, cwd = process.cwd(), silent = false } = options;
1891
1300
  const reportPath = outputPath ? path5.resolve(cwd, outputPath) : path5.resolve(cwd, getReportPath(format));
@@ -1896,7 +1305,7 @@ function writeReport(options) {
1896
1305
  fs3.writeFileSync(reportPath, content);
1897
1306
  const relativePath = path5.relative(cwd, reportPath);
1898
1307
  if (!silent) {
1899
- console.log(chalk6.green(`✓ Wrote ${format} report to ${relativePath}`));
1308
+ console.log(chalk5.green(`✓ Wrote ${format} report to ${relativePath}`));
1900
1309
  }
1901
1310
  return { path: reportPath, format, relativePath };
1902
1311
  }
@@ -1943,7 +1352,7 @@ function displayHealthTree(health, log) {
1943
1352
  const completenessLabel = missingTotal > 0 ? `${health.completeness.score}% (${missingTotal} missing docs)` : `${health.completeness.score}%`;
1944
1353
  const completenessColor = getHealthColor(getHealthStatus(health.completeness.score));
1945
1354
  log(`${tree.branch} ${colors.muted("completeness")} ${completenessColor(completenessLabel)}`);
1946
- const accuracyLabel = health.accuracy.issues > 0 ? `${health.accuracy.score}% (${health.accuracy.issues} drift issues${health.accuracy.fixable > 0 ? `, ${health.accuracy.fixable} fixable` : ""})` : `${health.accuracy.score}%`;
1355
+ const accuracyLabel = health.accuracy.fixable > 0 ? `${health.accuracy.score}% (${health.accuracy.fixable} fixable with --fix)` : `${health.accuracy.score}%`;
1947
1356
  const accuracyColor = getHealthColor(getHealthStatus(health.accuracy.score));
1948
1357
  const lastBranch = !health.examples ? tree.corner : tree.branch;
1949
1358
  log(`${lastBranch} ${colors.muted("accuracy")} ${accuracyColor(accuracyLabel)}`);
@@ -1992,6 +1401,7 @@ function displayTextOutput(options, deps) {
1992
1401
  warnBelowApiSurface,
1993
1402
  driftExports,
1994
1403
  typecheckErrors,
1404
+ runtimeErrors,
1995
1405
  staleRefs,
1996
1406
  specWarnings,
1997
1407
  specInfos,
@@ -2011,6 +1421,7 @@ function displayTextOutput(options, deps) {
2011
1421
  const apiSurfaceFailed = minApiSurface !== undefined && apiSurfaceScore < minApiSurface;
2012
1422
  const apiSurfaceWarn = warnBelowApiSurface !== undefined && apiSurfaceScore < warnBelowApiSurface && !apiSurfaceFailed;
2013
1423
  const hasTypecheckErrors = typecheckErrors.length > 0;
1424
+ const hasRuntimeErrors = runtimeErrors > 0;
2014
1425
  if (specWarnings.length > 0 || specInfos.length > 0) {
2015
1426
  log("");
2016
1427
  for (const diag of specWarnings) {
@@ -2105,7 +1516,7 @@ function displayTextOutput(options, deps) {
2105
1516
  }
2106
1517
  }
2107
1518
  log("");
2108
- const failed = healthFailed || apiSurfaceFailed || hasTypecheckErrors || hasStaleRefs;
1519
+ const failed = healthFailed || apiSurfaceFailed || hasTypecheckErrors || hasRuntimeErrors || hasStaleRefs;
2109
1520
  if (!failed) {
2110
1521
  const thresholdParts = [];
2111
1522
  thresholdParts.push(`health ${healthScore}% ≥ ${minHealth}%`);
@@ -2130,6 +1541,9 @@ function displayTextOutput(options, deps) {
2130
1541
  if (hasTypecheckErrors) {
2131
1542
  log(colors.error(`${sym.error} ${typecheckErrors.length} example type errors`));
2132
1543
  }
1544
+ if (hasRuntimeErrors) {
1545
+ log(colors.error(`${sym.error} ${runtimeErrors} example runtime errors`));
1546
+ }
2133
1547
  if (hasStaleRefs) {
2134
1548
  log(colors.error(`${sym.error} ${staleRefs.length} stale references in docs`));
2135
1549
  }
@@ -2147,6 +1561,7 @@ function handleNonTextOutput(options, deps) {
2147
1561
  minHealth,
2148
1562
  minApiSurface,
2149
1563
  typecheckErrors,
1564
+ runtimeErrors,
2150
1565
  limit,
2151
1566
  stdout,
2152
1567
  outputPath,
@@ -2183,7 +1598,8 @@ function handleNonTextOutput(options, deps) {
2183
1598
  const apiSurfaceScore = doccov.apiSurface?.completeness ?? 100;
2184
1599
  const apiSurfaceFailed = minApiSurface !== undefined && apiSurfaceScore < minApiSurface;
2185
1600
  const hasTypecheckErrors = typecheckErrors.length > 0;
2186
- return !(healthFailed || apiSurfaceFailed || hasTypecheckErrors);
1601
+ const hasRuntimeErrors = runtimeErrors > 0;
1602
+ return !(healthFailed || apiSurfaceFailed || hasTypecheckErrors || hasRuntimeErrors);
2187
1603
  }
2188
1604
  function displayApiSurfaceOutput(doccov, deps) {
2189
1605
  const { log } = deps;
@@ -2356,7 +1772,7 @@ function registerCheckCommand(program, dependencies = {}) {
2356
1772
  };
2357
1773
  const resolvedFilters = mergeFilterOptions(config, cliFilters);
2358
1774
  if (resolvedFilters.visibility) {
2359
- log(chalk7.dim(`Filtering by visibility: ${resolvedFilters.visibility.join(", ")}`));
1775
+ log(chalk6.dim(`Filtering by visibility: ${resolvedFilters.visibility.join(", ")}`));
2360
1776
  }
2361
1777
  const resolveExternalTypes = !options.skipResolve;
2362
1778
  const analyzer = createDocCov({
@@ -2433,6 +1849,7 @@ function registerCheckCommand(program, dependencies = {}) {
2433
1849
  minHealth,
2434
1850
  minApiSurface,
2435
1851
  typecheckErrors,
1852
+ runtimeErrors: runtimeDrifts.length,
2436
1853
  limit: parseInt(options.limit, 10) || 20,
2437
1854
  stdout: options.stdout,
2438
1855
  outputPath: options.output,
@@ -2452,6 +1869,7 @@ function registerCheckCommand(program, dependencies = {}) {
2452
1869
  warnBelowApiSurface,
2453
1870
  driftExports,
2454
1871
  typecheckErrors,
1872
+ runtimeErrors: runtimeDrifts.length,
2455
1873
  staleRefs,
2456
1874
  specWarnings,
2457
1875
  specInfos,
@@ -2461,7 +1879,7 @@ function registerCheckCommand(program, dependencies = {}) {
2461
1879
  process.exit(1);
2462
1880
  }
2463
1881
  } catch (commandError) {
2464
- error(chalk7.red("Error:"), commandError instanceof Error ? commandError.message : commandError);
1882
+ error(chalk6.red("Error:"), commandError instanceof Error ? commandError.message : commandError);
2465
1883
  process.exit(1);
2466
1884
  }
2467
1885
  });
@@ -2479,7 +1897,7 @@ import {
2479
1897
  parseMarkdownFiles as parseMarkdownFiles2
2480
1898
  } from "@doccov/sdk";
2481
1899
  import { calculateNextVersion, recommendSemverBump } from "@openpkg-ts/spec";
2482
- import chalk8 from "chalk";
1900
+ import chalk7 from "chalk";
2483
1901
  import { glob as glob2 } from "glob";
2484
1902
  var defaultDependencies2 = {
2485
1903
  readFileSync: fs4.readFileSync,
@@ -2554,9 +1972,9 @@ function registerDiffCommand(program, dependencies = {}) {
2554
1972
  }, null, 2));
2555
1973
  } else {
2556
1974
  log("");
2557
- log(chalk8.bold("Semver Recommendation"));
1975
+ log(chalk7.bold("Semver Recommendation"));
2558
1976
  log(` Current version: ${currentVersion}`);
2559
- log(` Recommended: ${chalk8.cyan(nextVersion)} (${chalk8.yellow(recommendation.bump.toUpperCase())})`);
1977
+ log(` Recommended: ${chalk7.cyan(nextVersion)} (${chalk7.yellow(recommendation.bump.toUpperCase())})`);
2560
1978
  log(` Reason: ${recommendation.reason}`);
2561
1979
  }
2562
1980
  return;
@@ -2586,8 +2004,8 @@ function registerDiffCommand(program, dependencies = {}) {
2586
2004
  silent: true
2587
2005
  });
2588
2006
  }
2589
- const cacheNote = fromCache ? chalk8.cyan(" (cached)") : "";
2590
- log(chalk8.dim(`Report: ${jsonPath}`) + cacheNote);
2007
+ const cacheNote = fromCache ? chalk7.cyan(" (cached)") : "";
2008
+ log(chalk7.dim(`Report: ${jsonPath}`) + cacheNote);
2591
2009
  }
2592
2010
  break;
2593
2011
  case "json": {
@@ -2645,18 +2063,18 @@ function registerDiffCommand(program, dependencies = {}) {
2645
2063
  checks
2646
2064
  });
2647
2065
  if (failures.length > 0) {
2648
- log(chalk8.red(`
2066
+ log(chalk7.red(`
2649
2067
  ✗ Check failed`));
2650
2068
  for (const f of failures) {
2651
- log(chalk8.red(` - ${f}`));
2069
+ log(chalk7.red(` - ${f}`));
2652
2070
  }
2653
2071
  process.exitCode = 1;
2654
2072
  } else if (options.strict || minCoverage !== undefined || maxDrift !== undefined) {
2655
- log(chalk8.green(`
2073
+ log(chalk7.green(`
2656
2074
  ✓ All checks passed`));
2657
2075
  }
2658
2076
  } catch (commandError) {
2659
- error(chalk8.red("Error:"), commandError instanceof Error ? commandError.message : commandError);
2077
+ error(chalk7.red("Error:"), commandError instanceof Error ? commandError.message : commandError);
2660
2078
  process.exitCode = 1;
2661
2079
  }
2662
2080
  });
@@ -2683,7 +2101,7 @@ async function generateDiff(baseSpec, headSpec, options, config, log) {
2683
2101
  if (!docsPatterns || docsPatterns.length === 0) {
2684
2102
  if (config?.docs?.include) {
2685
2103
  docsPatterns = config.docs.include;
2686
- log(chalk8.gray(`Using docs patterns from config: ${docsPatterns.join(", ")}`));
2104
+ log(chalk7.gray(`Using docs patterns from config: ${docsPatterns.join(", ")}`));
2687
2105
  }
2688
2106
  }
2689
2107
  if (docsPatterns && docsPatterns.length > 0) {
@@ -2706,37 +2124,37 @@ function loadSpec(filePath, readFileSync3) {
2706
2124
  }
2707
2125
  function printSummary(diff, baseName, headName, fromCache, log) {
2708
2126
  log("");
2709
- const cacheIndicator = fromCache ? chalk8.cyan(" (cached)") : "";
2710
- log(chalk8.bold(`Comparing: ${baseName} → ${headName}`) + cacheIndicator);
2127
+ const cacheIndicator = fromCache ? chalk7.cyan(" (cached)") : "";
2128
+ log(chalk7.bold(`Comparing: ${baseName} → ${headName}`) + cacheIndicator);
2711
2129
  log("─".repeat(40));
2712
2130
  log("");
2713
- const coverageColor = diff.coverageDelta > 0 ? chalk8.green : diff.coverageDelta < 0 ? chalk8.red : chalk8.gray;
2131
+ const coverageColor = diff.coverageDelta > 0 ? chalk7.green : diff.coverageDelta < 0 ? chalk7.red : chalk7.gray;
2714
2132
  const coverageSign = diff.coverageDelta > 0 ? "+" : "";
2715
2133
  log(` Coverage: ${diff.oldCoverage}% → ${diff.newCoverage}% ${coverageColor(`(${coverageSign}${diff.coverageDelta}%)`)}`);
2716
2134
  const breakingCount = diff.breaking.length;
2717
2135
  const highSeverity = diff.categorizedBreaking?.filter((c) => c.severity === "high").length ?? 0;
2718
2136
  if (breakingCount > 0) {
2719
- const severityNote = highSeverity > 0 ? chalk8.red(` (${highSeverity} high severity)`) : "";
2720
- log(` Breaking: ${chalk8.red(breakingCount)} changes${severityNote}`);
2137
+ const severityNote = highSeverity > 0 ? chalk7.red(` (${highSeverity} high severity)`) : "";
2138
+ log(` Breaking: ${chalk7.red(breakingCount)} changes${severityNote}`);
2721
2139
  } else {
2722
- log(` Breaking: ${chalk8.green("0")} changes`);
2140
+ log(` Breaking: ${chalk7.green("0")} changes`);
2723
2141
  }
2724
2142
  const newCount = diff.nonBreaking.length;
2725
2143
  const undocCount = diff.newUndocumented.length;
2726
2144
  if (newCount > 0) {
2727
- const undocNote = undocCount > 0 ? chalk8.yellow(` (${undocCount} undocumented)`) : "";
2728
- log(` New: ${chalk8.green(newCount)} exports${undocNote}`);
2145
+ const undocNote = undocCount > 0 ? chalk7.yellow(` (${undocCount} undocumented)`) : "";
2146
+ log(` New: ${chalk7.green(newCount)} exports${undocNote}`);
2729
2147
  }
2730
2148
  if (diff.driftIntroduced > 0 || diff.driftResolved > 0) {
2731
2149
  const parts = [];
2732
2150
  if (diff.driftIntroduced > 0)
2733
- parts.push(chalk8.red(`+${diff.driftIntroduced}`));
2151
+ parts.push(chalk7.red(`+${diff.driftIntroduced}`));
2734
2152
  if (diff.driftResolved > 0)
2735
- parts.push(chalk8.green(`-${diff.driftResolved}`));
2153
+ parts.push(chalk7.green(`-${diff.driftResolved}`));
2736
2154
  log(` Drift: ${parts.join(", ")}`);
2737
2155
  }
2738
2156
  const recommendation = recommendSemverBump(diff);
2739
- const bumpColor = recommendation.bump === "major" ? chalk8.red : recommendation.bump === "minor" ? chalk8.yellow : chalk8.green;
2157
+ const bumpColor = recommendation.bump === "major" ? chalk7.red : recommendation.bump === "minor" ? chalk7.yellow : chalk7.green;
2740
2158
  log(` Semver: ${bumpColor(recommendation.bump.toUpperCase())} (${recommendation.reason})`);
2741
2159
  log("");
2742
2160
  }
@@ -2819,7 +2237,7 @@ function printGitHubAnnotations(diff, log) {
2819
2237
  // src/commands/init.ts
2820
2238
  import * as fs5 from "node:fs";
2821
2239
  import * as path7 from "node:path";
2822
- import chalk9 from "chalk";
2240
+ import chalk8 from "chalk";
2823
2241
  var defaultDependencies3 = {
2824
2242
  fileExists: fs5.existsSync,
2825
2243
  writeFileSync: fs5.writeFileSync,
@@ -2837,7 +2255,7 @@ function registerInitCommand(program, dependencies = {}) {
2837
2255
  const cwd = path7.resolve(options.cwd);
2838
2256
  const existing = findExistingConfig(cwd, fileExists2);
2839
2257
  if (existing) {
2840
- error(chalk9.red(`A DocCov config already exists at ${path7.relative(cwd, existing) || "./doccov.config.*"}.`));
2258
+ error(chalk8.red(`A DocCov config already exists at ${path7.relative(cwd, existing) || "./doccov.config.*"}.`));
2841
2259
  process.exitCode = 1;
2842
2260
  return;
2843
2261
  }
@@ -2846,7 +2264,7 @@ function registerInitCommand(program, dependencies = {}) {
2846
2264
  const fileName = `doccov.config.${targetFormat}`;
2847
2265
  const outputPath = path7.join(cwd, fileName);
2848
2266
  if (fileExists2(outputPath)) {
2849
- error(chalk9.red(`Cannot create ${fileName}; file already exists.`));
2267
+ error(chalk8.red(`Cannot create ${fileName}; file already exists.`));
2850
2268
  process.exitCode = 1;
2851
2269
  return;
2852
2270
  }
@@ -2867,16 +2285,16 @@ function registerInitCommand(program, dependencies = {}) {
2867
2285
  }
2868
2286
  const repoInfo = detectRepoInfo(cwd, fileExists2, readFileSync4);
2869
2287
  log("");
2870
- log(chalk9.bold("Add this badge to your README:"));
2288
+ log(chalk8.bold("Add this badge to your README:"));
2871
2289
  log("");
2872
2290
  if (repoInfo) {
2873
- log(chalk9.cyan(`[![DocCov](https://doccov.dev/badge/${repoInfo.owner}/${repoInfo.repo})](https://doccov.dev/${repoInfo.owner}/${repoInfo.repo})`));
2291
+ log(chalk8.cyan(`[![DocCov](https://doccov.dev/badge/${repoInfo.owner}/${repoInfo.repo})](https://doccov.dev/${repoInfo.owner}/${repoInfo.repo})`));
2874
2292
  } else {
2875
- log(chalk9.cyan(`[![DocCov](https://doccov.dev/badge/OWNER/REPO)](https://doccov.dev/OWNER/REPO)`));
2876
- log(chalk9.dim(" Replace OWNER/REPO with your GitHub repo"));
2293
+ log(chalk8.cyan(`[![DocCov](https://doccov.dev/badge/OWNER/REPO)](https://doccov.dev/OWNER/REPO)`));
2294
+ log(chalk8.dim(" Replace OWNER/REPO with your GitHub repo"));
2877
2295
  }
2878
2296
  log("");
2879
- log(chalk9.dim("Run `doccov check` to verify your documentation coverage"));
2297
+ log(chalk8.dim("Run `doccov check` to verify your documentation coverage"));
2880
2298
  });
2881
2299
  }
2882
2300
  var findExistingConfig = (cwd, fileExists2) => {
@@ -3015,7 +2433,7 @@ import {
3015
2433
  normalize,
3016
2434
  validateSpec
3017
2435
  } from "@openpkg-ts/spec";
3018
- import chalk10 from "chalk";
2436
+ import chalk9 from "chalk";
3019
2437
  var defaultDependencies4 = {
3020
2438
  createDocCov: (options) => new DocCov2(options),
3021
2439
  writeFileSync: fs6.writeFileSync,
@@ -3028,7 +2446,7 @@ function getArrayLength(value) {
3028
2446
  function formatDiagnosticOutput(prefix2, diagnostic, baseDir) {
3029
2447
  const location = diagnostic.location;
3030
2448
  const relativePath = location?.file ? path8.relative(baseDir, location.file) || location.file : undefined;
3031
- const locationText = location && relativePath ? chalk10.gray(`${relativePath}:${location.line ?? 1}:${location.column ?? 1}`) : null;
2449
+ const locationText = location && relativePath ? chalk9.gray(`${relativePath}:${location.line ?? 1}:${location.column ?? 1}`) : null;
3032
2450
  const locationPrefix = locationText ? `${locationText} ` : "";
3033
2451
  return `${prefix2} ${locationPrefix}${diagnostic.message}`;
3034
2452
  }
@@ -3052,7 +2470,7 @@ function registerSpecCommand(program, dependencies = {}) {
3052
2470
  config = await loadDocCovConfig(targetDir);
3053
2471
  } catch (configError) {
3054
2472
  spin.fail("Failed to load config");
3055
- error(chalk10.red("Failed to load DocCov config:"), configError instanceof Error ? configError.message : configError);
2473
+ error(chalk9.red("Failed to load DocCov config:"), configError instanceof Error ? configError.message : configError);
3056
2474
  process.exit(1);
3057
2475
  }
3058
2476
  const cliFilters = {
@@ -3085,9 +2503,9 @@ function registerSpecCommand(program, dependencies = {}) {
3085
2503
  const validation = validateSpec(normalized);
3086
2504
  if (!validation.ok) {
3087
2505
  spin.fail("Validation failed");
3088
- error(chalk10.red("Spec failed schema validation"));
2506
+ error(chalk9.red("Spec failed schema validation"));
3089
2507
  for (const err of validation.errors) {
3090
- error(chalk10.red(`schema: ${err.instancePath || "/"} ${err.message}`));
2508
+ error(chalk9.red(`schema: ${err.instancePath || "/"} ${err.message}`));
3091
2509
  }
3092
2510
  process.exit(1);
3093
2511
  }
@@ -3102,9 +2520,9 @@ function registerSpecCommand(program, dependencies = {}) {
3102
2520
  const doccovValidation = validateDocCovSpec(doccovSpec);
3103
2521
  if (!doccovValidation.ok) {
3104
2522
  spin.fail("DocCov validation failed");
3105
- error(chalk10.red("DocCov spec failed schema validation"));
2523
+ error(chalk9.red("DocCov spec failed schema validation"));
3106
2524
  for (const err of doccovValidation.errors) {
3107
- error(chalk10.red(`doccov: ${err.instancePath || "/"} ${err.message}`));
2525
+ error(chalk9.red(`doccov: ${err.instancePath || "/"} ${err.message}`));
3108
2526
  }
3109
2527
  process.exit(1);
3110
2528
  }
@@ -3124,12 +2542,12 @@ function registerSpecCommand(program, dependencies = {}) {
3124
2542
  const doccovPath = path8.join(outputDir, "doccov.json");
3125
2543
  writeFileSync4(doccovPath, JSON.stringify(doccovSpec, null, 2));
3126
2544
  spin.success(`Generated ${options.output}/`);
3127
- log(chalk10.gray(` openpkg.json: ${getArrayLength(normalized.exports)} exports`));
3128
- log(chalk10.gray(` doccov.json: ${doccovSpec.summary.score}% coverage, ${doccovSpec.summary.drift.total} drift issues`));
2545
+ log(chalk9.gray(` openpkg.json: ${getArrayLength(normalized.exports)} exports`));
2546
+ log(chalk9.gray(` doccov.json: ${doccovSpec.summary.score}% coverage, ${doccovSpec.summary.drift.total} drift issues`));
3129
2547
  } else {
3130
2548
  spin.success(`Generated ${options.output}/openpkg.json`);
3131
- log(chalk10.gray(` ${getArrayLength(normalized.exports)} exports`));
3132
- log(chalk10.gray(` ${getArrayLength(normalized.types)} types`));
2549
+ log(chalk9.gray(` ${getArrayLength(normalized.exports)} exports`));
2550
+ log(chalk9.gray(` ${getArrayLength(normalized.types)} types`));
3133
2551
  }
3134
2552
  }
3135
2553
  const isFullGenerationInfo = (gen) => {
@@ -3141,62 +2559,62 @@ function registerSpecCommand(program, dependencies = {}) {
3141
2559
  const pm = await detectPackageManager(fileSystem);
3142
2560
  const buildCmd = pm.name === "npm" ? "npm run build" : `${pm.name} run build`;
3143
2561
  log("");
3144
- log(chalk10.yellow("⚠ Runtime extraction requested but no schemas extracted."));
3145
- log(chalk10.yellow(` Ensure project is built (${buildCmd}) and dist/ exists.`));
2562
+ log(chalk9.yellow("⚠ Runtime extraction requested but no schemas extracted."));
2563
+ log(chalk9.yellow(` Ensure project is built (${buildCmd}) and dist/ exists.`));
3146
2564
  }
3147
2565
  if (options.verbose && fullGen) {
3148
2566
  log("");
3149
- log(chalk10.bold("Generation Info"));
3150
- log(chalk10.gray(` Timestamp: ${fullGen.timestamp}`));
3151
- log(chalk10.gray(` Generator: ${fullGen.generator.name}@${fullGen.generator.version}`));
3152
- log(chalk10.gray(` Entry point: ${fullGen.analysis.entryPoint}`));
3153
- log(chalk10.gray(` Detected via: ${fullGen.analysis.entryPointSource}`));
3154
- log(chalk10.gray(` Declaration only: ${fullGen.analysis.isDeclarationOnly ? "yes" : "no"}`));
3155
- log(chalk10.gray(` External types: ${fullGen.analysis.resolvedExternalTypes ? "resolved" : "skipped"}`));
2567
+ log(chalk9.bold("Generation Info"));
2568
+ log(chalk9.gray(` Timestamp: ${fullGen.timestamp}`));
2569
+ log(chalk9.gray(` Generator: ${fullGen.generator.name}@${fullGen.generator.version}`));
2570
+ log(chalk9.gray(` Entry point: ${fullGen.analysis.entryPoint}`));
2571
+ log(chalk9.gray(` Detected via: ${fullGen.analysis.entryPointSource}`));
2572
+ log(chalk9.gray(` Declaration only: ${fullGen.analysis.isDeclarationOnly ? "yes" : "no"}`));
2573
+ log(chalk9.gray(` External types: ${fullGen.analysis.resolvedExternalTypes ? "resolved" : "skipped"}`));
3156
2574
  if (fullGen.analysis.maxTypeDepth) {
3157
- log(chalk10.gray(` Max type depth: ${fullGen.analysis.maxTypeDepth}`));
2575
+ log(chalk9.gray(` Max type depth: ${fullGen.analysis.maxTypeDepth}`));
3158
2576
  }
3159
2577
  if (fullGen.analysis.schemaExtraction) {
3160
2578
  const se = fullGen.analysis.schemaExtraction;
3161
- log(chalk10.gray(` Schema extraction: ${se.method}`));
2579
+ log(chalk9.gray(` Schema extraction: ${se.method}`));
3162
2580
  if (se.runtimeCount) {
3163
- log(chalk10.gray(` Runtime schemas: ${se.runtimeCount} (${se.vendors?.join(", ")})`));
2581
+ log(chalk9.gray(` Runtime schemas: ${se.runtimeCount} (${se.vendors?.join(", ")})`));
3164
2582
  }
3165
2583
  }
3166
2584
  log("");
3167
- log(chalk10.bold("Environment"));
3168
- log(chalk10.gray(` node_modules: ${fullGen.environment.hasNodeModules ? "found" : "not found"}`));
2585
+ log(chalk9.bold("Environment"));
2586
+ log(chalk9.gray(` node_modules: ${fullGen.environment.hasNodeModules ? "found" : "not found"}`));
3169
2587
  if (fullGen.environment.packageManager) {
3170
- log(chalk10.gray(` Package manager: ${fullGen.environment.packageManager}`));
2588
+ log(chalk9.gray(` Package manager: ${fullGen.environment.packageManager}`));
3171
2589
  }
3172
2590
  if (fullGen.environment.isMonorepo) {
3173
- log(chalk10.gray(` Monorepo: yes`));
2591
+ log(chalk9.gray(` Monorepo: yes`));
3174
2592
  }
3175
2593
  if (fullGen.environment.targetPackage) {
3176
- log(chalk10.gray(` Target package: ${fullGen.environment.targetPackage}`));
2594
+ log(chalk9.gray(` Target package: ${fullGen.environment.targetPackage}`));
3177
2595
  }
3178
2596
  if (fullGen.issues.length > 0) {
3179
2597
  log("");
3180
- log(chalk10.bold("Issues"));
2598
+ log(chalk9.bold("Issues"));
3181
2599
  for (const issue of fullGen.issues) {
3182
- const prefix2 = issue.severity === "error" ? chalk10.red(">") : issue.severity === "warning" ? chalk10.yellow(">") : chalk10.cyan(">");
2600
+ const prefix2 = issue.severity === "error" ? chalk9.red(">") : issue.severity === "warning" ? chalk9.yellow(">") : chalk9.cyan(">");
3183
2601
  log(`${prefix2} [${issue.code}] ${issue.message}`);
3184
2602
  if (issue.suggestion) {
3185
- log(chalk10.gray(` ${issue.suggestion}`));
2603
+ log(chalk9.gray(` ${issue.suggestion}`));
3186
2604
  }
3187
2605
  }
3188
2606
  }
3189
2607
  }
3190
2608
  if (options.showDiagnostics && result.diagnostics.length > 0) {
3191
2609
  log("");
3192
- log(chalk10.bold("Diagnostics"));
2610
+ log(chalk9.bold("Diagnostics"));
3193
2611
  for (const diagnostic of result.diagnostics) {
3194
- const prefix2 = diagnostic.severity === "error" ? chalk10.red(">") : diagnostic.severity === "warning" ? chalk10.yellow(">") : chalk10.cyan(">");
2612
+ const prefix2 = diagnostic.severity === "error" ? chalk9.red(">") : diagnostic.severity === "warning" ? chalk9.yellow(">") : chalk9.cyan(">");
3195
2613
  log(formatDiagnosticOutput(prefix2, diagnostic, targetDir));
3196
2614
  }
3197
2615
  }
3198
2616
  } catch (commandError) {
3199
- error(chalk10.red("Error:"), commandError instanceof Error ? commandError.message : commandError);
2617
+ error(chalk9.red("Error:"), commandError instanceof Error ? commandError.message : commandError);
3200
2618
  process.exit(1);
3201
2619
  }
3202
2620
  });
@@ -3214,7 +2632,7 @@ import {
3214
2632
  renderSparkline,
3215
2633
  saveSnapshot
3216
2634
  } from "@doccov/sdk";
3217
- import chalk11 from "chalk";
2635
+ import chalk10 from "chalk";
3218
2636
  function formatDate(timestamp) {
3219
2637
  const date = new Date(timestamp);
3220
2638
  return date.toLocaleDateString("en-US", {
@@ -3227,19 +2645,19 @@ function formatDate(timestamp) {
3227
2645
  }
3228
2646
  function getColorForScore(score) {
3229
2647
  if (score >= 90)
3230
- return chalk11.green;
2648
+ return chalk10.green;
3231
2649
  if (score >= 70)
3232
- return chalk11.yellow;
2650
+ return chalk10.yellow;
3233
2651
  if (score >= 50)
3234
- return chalk11.hex("#FFA500");
3235
- return chalk11.red;
2652
+ return chalk10.hex("#FFA500");
2653
+ return chalk10.red;
3236
2654
  }
3237
2655
  function formatSnapshot(snapshot) {
3238
2656
  const color = getColorForScore(snapshot.coverageScore);
3239
2657
  const date = formatDate(snapshot.timestamp);
3240
2658
  const version = snapshot.version ? ` v${snapshot.version}` : "";
3241
- const commit = snapshot.commit ? chalk11.gray(` (${snapshot.commit.slice(0, 7)})`) : "";
3242
- return `${chalk11.gray(date)} ${color(`${snapshot.coverageScore}%`)} ${snapshot.documentedExports}/${snapshot.totalExports} exports${version}${commit}`;
2659
+ const commit = snapshot.commit ? chalk10.gray(` (${snapshot.commit.slice(0, 7)})`) : "";
2660
+ return `${chalk10.gray(date)} ${color(`${snapshot.coverageScore}%`)} ${snapshot.documentedExports}/${snapshot.totalExports} exports${version}${commit}`;
3243
2661
  }
3244
2662
  function formatWeekDate(timestamp) {
3245
2663
  const date = new Date(timestamp);
@@ -3247,10 +2665,10 @@ function formatWeekDate(timestamp) {
3247
2665
  }
3248
2666
  function formatVelocity(velocity) {
3249
2667
  if (velocity > 0)
3250
- return chalk11.green(`+${velocity}%/day`);
2668
+ return chalk10.green(`+${velocity}%/day`);
3251
2669
  if (velocity < 0)
3252
- return chalk11.red(`${velocity}%/day`);
3253
- return chalk11.gray("0%/day");
2670
+ return chalk10.red(`${velocity}%/day`);
2671
+ return chalk10.gray("0%/day");
3254
2672
  }
3255
2673
  function registerTrendsCommand(program) {
3256
2674
  program.command("trends").description("Show coverage trends over time").option("--cwd <dir>", "Working directory", process.cwd()).option("-n, --limit <count>", "Number of snapshots to show", "10").option("--prune <count>", "Prune history to keep only N snapshots").option("--record", "Record current coverage to history").option("--json", "Output as JSON").option("--extended", "Show extended trend analysis (velocity, projections)").option("--weekly", "Show weekly summary breakdown").action(async (options) => {
@@ -3259,14 +2677,14 @@ function registerTrendsCommand(program) {
3259
2677
  const keepCount = parseInt(options.prune, 10);
3260
2678
  if (!Number.isNaN(keepCount)) {
3261
2679
  const deleted = pruneHistory(cwd, keepCount);
3262
- console.log(chalk11.green(`Pruned ${deleted} old snapshots, kept ${keepCount} most recent`));
2680
+ console.log(chalk10.green(`Pruned ${deleted} old snapshots, kept ${keepCount} most recent`));
3263
2681
  }
3264
2682
  return;
3265
2683
  }
3266
2684
  if (options.record) {
3267
2685
  const specPath = path9.resolve(cwd, "openpkg.json");
3268
2686
  if (!fs7.existsSync(specPath)) {
3269
- console.error(chalk11.red("No openpkg.json found. Run `doccov spec` first to generate a spec."));
2687
+ console.error(chalk10.red("No openpkg.json found. Run `doccov spec` first to generate a spec."));
3270
2688
  process.exit(1);
3271
2689
  }
3272
2690
  const spin = spinner("Recording coverage snapshot");
@@ -3279,21 +2697,21 @@ function registerTrendsCommand(program) {
3279
2697
  console.log(formatSnapshot(trend.current));
3280
2698
  if (trend.delta !== undefined) {
3281
2699
  const deltaStr = formatDelta2(trend.delta);
3282
- const deltaColor = trend.delta > 0 ? chalk11.green : trend.delta < 0 ? chalk11.red : chalk11.gray;
3283
- console.log(chalk11.gray("Change from previous:"), deltaColor(deltaStr));
2700
+ const deltaColor = trend.delta > 0 ? chalk10.green : trend.delta < 0 ? chalk10.red : chalk10.gray;
2701
+ console.log(chalk10.gray("Change from previous:"), deltaColor(deltaStr));
3284
2702
  }
3285
2703
  return;
3286
2704
  } catch (error) {
3287
2705
  spin.fail("Failed to record snapshot");
3288
- console.error(chalk11.red("Failed to read openpkg.json:"), error instanceof Error ? error.message : error);
2706
+ console.error(chalk10.red("Failed to read openpkg.json:"), error instanceof Error ? error.message : error);
3289
2707
  process.exit(1);
3290
2708
  }
3291
2709
  }
3292
2710
  const snapshots = loadSnapshots(cwd);
3293
2711
  const limit = parseInt(options.limit ?? "10", 10);
3294
2712
  if (snapshots.length === 0) {
3295
- console.log(chalk11.yellow("No coverage history found."));
3296
- console.log(chalk11.gray("Run `doccov trends --record` to save the current coverage."));
2713
+ console.log(chalk10.yellow("No coverage history found."));
2714
+ console.log(chalk10.gray("Run `doccov trends --record` to save the current coverage."));
3297
2715
  return;
3298
2716
  }
3299
2717
  if (options.json) {
@@ -3308,17 +2726,17 @@ function registerTrendsCommand(program) {
3308
2726
  }
3309
2727
  const sparklineData = snapshots.slice(0, 10).map((s) => s.coverageScore).reverse();
3310
2728
  const sparkline = renderSparkline(sparklineData);
3311
- console.log(chalk11.bold("Coverage Trends"));
3312
- console.log(chalk11.gray(`Package: ${snapshots[0].package}`));
3313
- console.log(chalk11.gray(`Sparkline: ${sparkline}`));
2729
+ console.log(chalk10.bold("Coverage Trends"));
2730
+ console.log(chalk10.gray(`Package: ${snapshots[0].package}`));
2731
+ console.log(chalk10.gray(`Sparkline: ${sparkline}`));
3314
2732
  console.log("");
3315
2733
  if (snapshots.length >= 2) {
3316
2734
  const oldest = snapshots[snapshots.length - 1];
3317
2735
  const newest = snapshots[0];
3318
2736
  const overallDelta = newest.coverageScore - oldest.coverageScore;
3319
2737
  const deltaStr = formatDelta2(overallDelta);
3320
- const deltaColor = overallDelta > 0 ? chalk11.green : overallDelta < 0 ? chalk11.red : chalk11.gray;
3321
- console.log(chalk11.gray("Overall trend:"), deltaColor(deltaStr), chalk11.gray(`(${snapshots.length} snapshots)`));
2738
+ const deltaColor = overallDelta > 0 ? chalk10.green : overallDelta < 0 ? chalk10.red : chalk10.gray;
2739
+ console.log(chalk10.gray("Overall trend:"), deltaColor(deltaStr), chalk10.gray(`(${snapshots.length} snapshots)`));
3322
2740
  console.log("");
3323
2741
  }
3324
2742
  if (options.extended) {
@@ -3328,55 +2746,55 @@ function registerTrendsCommand(program) {
3328
2746
  const specContent = fs7.readFileSync(specPath, "utf-8");
3329
2747
  const spec = JSON.parse(specContent);
3330
2748
  const extended = getExtendedTrend(spec, cwd);
3331
- console.log(chalk11.bold("Extended Analysis"));
3332
- console.log(chalk11.gray("90-day retention"));
2749
+ console.log(chalk10.bold("Extended Analysis"));
2750
+ console.log(chalk10.gray("90-day retention"));
3333
2751
  console.log("");
3334
2752
  console.log(" Velocity:");
3335
2753
  console.log(` 7-day: ${formatVelocity(extended.velocity7d)}`);
3336
2754
  console.log(` 30-day: ${formatVelocity(extended.velocity30d)}`);
3337
2755
  console.log(` 90-day: ${formatVelocity(extended.velocity90d)}`);
3338
2756
  console.log("");
3339
- const projColor = extended.projected30d >= extended.trend.current.coverageScore ? chalk11.green : chalk11.red;
2757
+ const projColor = extended.projected30d >= extended.trend.current.coverageScore ? chalk10.green : chalk10.red;
3340
2758
  console.log(` Projected (30d): ${projColor(`${extended.projected30d}%`)}`);
3341
- console.log(` All-time high: ${chalk11.green(`${extended.allTimeHigh}%`)}`);
3342
- console.log(` All-time low: ${chalk11.red(`${extended.allTimeLow}%`)}`);
2759
+ console.log(` All-time high: ${chalk10.green(`${extended.allTimeHigh}%`)}`);
2760
+ console.log(` All-time low: ${chalk10.red(`${extended.allTimeLow}%`)}`);
3343
2761
  if (extended.dataRange) {
3344
2762
  const startDate = formatWeekDate(extended.dataRange.start);
3345
2763
  const endDate = formatWeekDate(extended.dataRange.end);
3346
- console.log(chalk11.gray(` Data range: ${startDate} - ${endDate}`));
2764
+ console.log(chalk10.gray(` Data range: ${startDate} - ${endDate}`));
3347
2765
  }
3348
2766
  console.log("");
3349
2767
  if (options.weekly && extended.weeklySummaries.length > 0) {
3350
- console.log(chalk11.bold("Weekly Summary"));
2768
+ console.log(chalk10.bold("Weekly Summary"));
3351
2769
  const weekLimit = Math.min(extended.weeklySummaries.length, 8);
3352
2770
  for (let i = 0;i < weekLimit; i++) {
3353
2771
  const week = extended.weeklySummaries[i];
3354
2772
  const weekStart = formatWeekDate(week.weekStart);
3355
2773
  const weekEnd = formatWeekDate(week.weekEnd);
3356
- const deltaColor = week.delta > 0 ? chalk11.green : week.delta < 0 ? chalk11.red : chalk11.gray;
2774
+ const deltaColor = week.delta > 0 ? chalk10.green : week.delta < 0 ? chalk10.red : chalk10.gray;
3357
2775
  const deltaStr = week.delta > 0 ? `+${week.delta}%` : `${week.delta}%`;
3358
2776
  console.log(` ${weekStart} - ${weekEnd}: ${week.avgCoverage}% avg ${deltaColor(deltaStr)} (${week.snapshotCount} snapshots)`);
3359
2777
  }
3360
2778
  if (extended.weeklySummaries.length > weekLimit) {
3361
- console.log(chalk11.gray(` ... and ${extended.weeklySummaries.length - weekLimit} more weeks`));
2779
+ console.log(chalk10.gray(` ... and ${extended.weeklySummaries.length - weekLimit} more weeks`));
3362
2780
  }
3363
2781
  console.log("");
3364
2782
  }
3365
2783
  } catch {
3366
- console.log(chalk11.yellow("Could not load openpkg.json for extended analysis"));
2784
+ console.log(chalk10.yellow("Could not load openpkg.json for extended analysis"));
3367
2785
  console.log("");
3368
2786
  }
3369
2787
  }
3370
2788
  }
3371
- console.log(chalk11.bold("History"));
2789
+ console.log(chalk10.bold("History"));
3372
2790
  const displaySnapshots = snapshots.slice(0, limit);
3373
2791
  for (let i = 0;i < displaySnapshots.length; i++) {
3374
2792
  const snapshot = displaySnapshots[i];
3375
- const prefix2 = i === 0 ? chalk11.cyan("→") : " ";
2793
+ const prefix2 = i === 0 ? chalk10.cyan("→") : " ";
3376
2794
  console.log(`${prefix2} ${formatSnapshot(snapshot)}`);
3377
2795
  }
3378
2796
  if (snapshots.length > limit) {
3379
- console.log(chalk11.gray(` ... and ${snapshots.length - limit} more`));
2797
+ console.log(chalk10.gray(` ... and ${snapshots.length - limit} more`));
3380
2798
  }
3381
2799
  });
3382
2800
  }