@vertaaux/cli 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (223) hide show
  1. package/CHANGELOG.md +97 -0
  2. package/MIGRATION.md +239 -0
  3. package/README.md +34 -16
  4. package/dist/app/interactive-app.d.ts +101 -0
  5. package/dist/app/interactive-app.d.ts.map +1 -0
  6. package/dist/app/interactive-app.js +309 -0
  7. package/dist/app/layout/canvas.d.ts +23 -0
  8. package/dist/app/layout/canvas.d.ts.map +1 -0
  9. package/dist/app/layout/canvas.js +36 -0
  10. package/dist/app/layout/footer.d.ts +31 -0
  11. package/dist/app/layout/footer.d.ts.map +1 -0
  12. package/dist/app/layout/footer.js +41 -0
  13. package/dist/app/layout/header.d.ts +20 -0
  14. package/dist/app/layout/header.d.ts.map +1 -0
  15. package/dist/app/layout/header.js +27 -0
  16. package/dist/app/menu/categories.d.ts +20 -0
  17. package/dist/app/menu/categories.d.ts.map +1 -0
  18. package/dist/app/menu/categories.js +181 -0
  19. package/dist/app/menu/filter.d.ts +17 -0
  20. package/dist/app/menu/filter.d.ts.map +1 -0
  21. package/dist/app/menu/filter.js +33 -0
  22. package/dist/app/menu/menu-view.d.ts +35 -0
  23. package/dist/app/menu/menu-view.d.ts.map +1 -0
  24. package/dist/app/menu/menu-view.js +230 -0
  25. package/dist/app/menu/recent.d.ts +24 -0
  26. package/dist/app/menu/recent.d.ts.map +1 -0
  27. package/dist/app/menu/recent.js +49 -0
  28. package/dist/app/types.d.ts +43 -0
  29. package/dist/app/types.d.ts.map +1 -0
  30. package/dist/app/types.js +7 -0
  31. package/dist/app/views/command-runner.d.ts +36 -0
  32. package/dist/app/views/command-runner.d.ts.map +1 -0
  33. package/dist/app/views/command-runner.js +372 -0
  34. package/dist/app/views/help-overlay.d.ts +21 -0
  35. package/dist/app/views/help-overlay.d.ts.map +1 -0
  36. package/dist/app/views/help-overlay.js +45 -0
  37. package/dist/auth/ci-token.d.ts +8 -2
  38. package/dist/auth/ci-token.d.ts.map +1 -1
  39. package/dist/auth/ci-token.js +15 -30
  40. package/dist/auth/device-flow.d.ts +2 -1
  41. package/dist/auth/device-flow.d.ts.map +1 -1
  42. package/dist/auth/device-flow.js +13 -10
  43. package/dist/auth/token-store.d.ts.map +1 -1
  44. package/dist/auth/token-store.js +12 -2
  45. package/dist/baseline/diff.d.ts +2 -2
  46. package/dist/baseline/diff.d.ts.map +1 -1
  47. package/dist/baseline/diff.js +15 -34
  48. package/dist/commands/a11y.d.ts +9 -0
  49. package/dist/commands/a11y.d.ts.map +1 -0
  50. package/dist/commands/a11y.js +76 -0
  51. package/dist/commands/audit/artifacts.d.ts +27 -0
  52. package/dist/commands/audit/artifacts.d.ts.map +1 -0
  53. package/dist/commands/audit/artifacts.js +158 -0
  54. package/dist/commands/audit/ci-detection.d.ts +18 -0
  55. package/dist/commands/audit/ci-detection.d.ts.map +1 -0
  56. package/dist/commands/audit/ci-detection.js +71 -0
  57. package/dist/commands/audit/explain.d.ts +11 -0
  58. package/dist/commands/audit/explain.d.ts.map +1 -0
  59. package/dist/commands/audit/explain.js +45 -0
  60. package/dist/commands/audit/filters.d.ts +17 -0
  61. package/dist/commands/audit/filters.d.ts.map +1 -0
  62. package/dist/commands/audit/filters.js +40 -0
  63. package/dist/commands/audit/index.d.ts +18 -0
  64. package/dist/commands/audit/index.d.ts.map +1 -0
  65. package/dist/commands/audit/index.js +564 -0
  66. package/dist/commands/audit/output.d.ts +32 -0
  67. package/dist/commands/audit/output.d.ts.map +1 -0
  68. package/dist/commands/audit/output.js +130 -0
  69. package/dist/commands/audit/policy.d.ts +19 -0
  70. package/dist/commands/audit/policy.d.ts.map +1 -0
  71. package/dist/commands/audit/policy.js +102 -0
  72. package/dist/commands/audit/scoring.d.ts +23 -0
  73. package/dist/commands/audit/scoring.d.ts.map +1 -0
  74. package/dist/commands/audit/scoring.js +70 -0
  75. package/dist/commands/audit/types.d.ts +88 -0
  76. package/dist/commands/audit/types.d.ts.map +1 -0
  77. package/dist/commands/audit/types.js +8 -0
  78. package/dist/commands/audit.d.ts +2 -60
  79. package/dist/commands/audit.d.ts.map +1 -1
  80. package/dist/commands/audit.js +2 -1097
  81. package/dist/commands/baseline.d.ts +1 -0
  82. package/dist/commands/baseline.d.ts.map +1 -1
  83. package/dist/commands/baseline.js +205 -121
  84. package/dist/commands/comment.d.ts +22 -0
  85. package/dist/commands/comment.d.ts.map +1 -1
  86. package/dist/commands/comment.js +122 -58
  87. package/dist/commands/compare.d.ts +17 -0
  88. package/dist/commands/compare.d.ts.map +1 -1
  89. package/dist/commands/compare.js +287 -180
  90. package/dist/commands/diff.d.ts +5 -0
  91. package/dist/commands/diff.d.ts.map +1 -1
  92. package/dist/commands/diff.js +168 -141
  93. package/dist/commands/doc.d.ts +10 -0
  94. package/dist/commands/doc.d.ts.map +1 -1
  95. package/dist/commands/doc.js +134 -76
  96. package/dist/commands/doctor.d.ts +2 -0
  97. package/dist/commands/doctor.d.ts.map +1 -1
  98. package/dist/commands/doctor.js +164 -17
  99. package/dist/commands/download.d.ts +10 -0
  100. package/dist/commands/download.d.ts.map +1 -1
  101. package/dist/commands/download.js +169 -112
  102. package/dist/commands/explain.d.ts +5 -0
  103. package/dist/commands/explain.d.ts.map +1 -1
  104. package/dist/commands/explain.js +241 -155
  105. package/dist/commands/fix-all.d.ts +25 -0
  106. package/dist/commands/fix-all.d.ts.map +1 -0
  107. package/dist/commands/fix-all.js +206 -0
  108. package/dist/commands/fix-plan.d.ts +9 -0
  109. package/dist/commands/fix-plan.d.ts.map +1 -1
  110. package/dist/commands/fix-plan.js +152 -89
  111. package/dist/commands/fix.d.ts +17 -0
  112. package/dist/commands/fix.d.ts.map +1 -0
  113. package/dist/commands/fix.js +111 -0
  114. package/dist/commands/init.d.ts +11 -0
  115. package/dist/commands/init.d.ts.map +1 -1
  116. package/dist/commands/init.js +94 -42
  117. package/dist/commands/login.d.ts +18 -0
  118. package/dist/commands/login.d.ts.map +1 -1
  119. package/dist/commands/login.js +263 -92
  120. package/dist/commands/patch-review.d.ts +11 -0
  121. package/dist/commands/patch-review.d.ts.map +1 -1
  122. package/dist/commands/patch-review.js +159 -97
  123. package/dist/commands/policy.d.ts +31 -0
  124. package/dist/commands/policy.d.ts.map +1 -1
  125. package/dist/commands/policy.js +269 -124
  126. package/dist/commands/release-notes.d.ts +10 -0
  127. package/dist/commands/release-notes.d.ts.map +1 -1
  128. package/dist/commands/release-notes.js +127 -73
  129. package/dist/commands/scan.d.ts +13 -0
  130. package/dist/commands/scan.d.ts.map +1 -0
  131. package/dist/commands/scan.js +133 -0
  132. package/dist/commands/status.d.ts +9 -0
  133. package/dist/commands/status.d.ts.map +1 -0
  134. package/dist/commands/status.js +81 -0
  135. package/dist/commands/suggest.d.ts +10 -0
  136. package/dist/commands/suggest.d.ts.map +1 -1
  137. package/dist/commands/suggest.js +153 -82
  138. package/dist/commands/triage.d.ts +35 -0
  139. package/dist/commands/triage.d.ts.map +1 -1
  140. package/dist/commands/triage.js +206 -81
  141. package/dist/commands/upload.d.ts +9 -0
  142. package/dist/commands/upload.d.ts.map +1 -1
  143. package/dist/commands/upload.js +140 -101
  144. package/dist/commands/verify.d.ts +13 -0
  145. package/dist/commands/verify.d.ts.map +1 -0
  146. package/dist/commands/verify.js +118 -0
  147. package/dist/index.d.ts +3 -2
  148. package/dist/index.d.ts.map +1 -1
  149. package/dist/index.js +125 -990
  150. package/dist/interactive/fix-wizard.d.ts +3 -0
  151. package/dist/interactive/fix-wizard.d.ts.map +1 -1
  152. package/dist/interactive/fix-wizard.js +130 -112
  153. package/dist/interactive/init-wizard.d.ts +3 -1
  154. package/dist/interactive/init-wizard.d.ts.map +1 -1
  155. package/dist/interactive/init-wizard.js +207 -138
  156. package/dist/interactive/prompts.d.ts +7 -3
  157. package/dist/interactive/prompts.d.ts.map +1 -1
  158. package/dist/interactive/prompts.js +44 -23
  159. package/dist/output/envelope.d.ts +2 -0
  160. package/dist/output/envelope.d.ts.map +1 -1
  161. package/dist/output/envelope.js +18 -2
  162. package/dist/output/factory.d.ts +2 -1
  163. package/dist/output/factory.d.ts.map +1 -1
  164. package/dist/output/html.d.ts +2 -1
  165. package/dist/output/html.d.ts.map +1 -1
  166. package/dist/output/html.js +3 -2
  167. package/dist/output/human.d.ts +2 -1
  168. package/dist/output/human.d.ts.map +1 -1
  169. package/dist/output/human.js +3 -2
  170. package/dist/output/json.d.ts +2 -1
  171. package/dist/output/json.d.ts.map +1 -1
  172. package/dist/output/junit.d.ts +2 -1
  173. package/dist/output/junit.d.ts.map +1 -1
  174. package/dist/output/sarif.d.ts +2 -1
  175. package/dist/output/sarif.d.ts.map +1 -1
  176. package/dist/types.d.ts +74 -0
  177. package/dist/types.d.ts.map +1 -0
  178. package/dist/types.js +5 -0
  179. package/dist/ui/banner.d.ts +34 -0
  180. package/dist/ui/banner.d.ts.map +1 -1
  181. package/dist/ui/banner.js +97 -5
  182. package/dist/ui/diagnostics.d.ts +9 -4
  183. package/dist/ui/diagnostics.d.ts.map +1 -1
  184. package/dist/ui/diagnostics.js +32 -82
  185. package/dist/ui/strings.d.ts +373 -0
  186. package/dist/ui/strings.d.ts.map +1 -0
  187. package/dist/ui/strings.js +499 -0
  188. package/dist/ui/table.d.ts +0 -2
  189. package/dist/ui/table.d.ts.map +1 -1
  190. package/dist/ui/table.js +3 -4
  191. package/dist/utils/api-client.d.ts +46 -0
  192. package/dist/utils/api-client.d.ts.map +1 -0
  193. package/dist/utils/api-client.js +170 -0
  194. package/dist/utils/client.d.ts +29 -18
  195. package/dist/utils/client.d.ts.map +1 -1
  196. package/dist/utils/client.js +102 -12
  197. package/dist/utils/formatters.d.ts +38 -0
  198. package/dist/utils/formatters.d.ts.map +1 -0
  199. package/dist/utils/formatters.js +277 -0
  200. package/dist/utils/url-classify.d.ts.map +1 -1
  201. package/dist/utils/url-classify.js +24 -3
  202. package/node_modules/@vertaaux/tui/dist/index.cjs +713 -20
  203. package/node_modules/@vertaaux/tui/dist/index.cjs.map +1 -1
  204. package/node_modules/@vertaaux/tui/dist/index.d.cts +361 -4
  205. package/node_modules/@vertaaux/tui/dist/index.d.ts +361 -4
  206. package/node_modules/@vertaaux/tui/dist/index.js +689 -21
  207. package/node_modules/@vertaaux/tui/dist/index.js.map +1 -1
  208. package/package.json +13 -5
  209. package/dist/commands/client.d.ts +0 -14
  210. package/dist/commands/client.d.ts.map +0 -1
  211. package/dist/commands/client.js +0 -362
  212. package/dist/commands/drift.d.ts +0 -15
  213. package/dist/commands/drift.d.ts.map +0 -1
  214. package/dist/commands/drift.js +0 -309
  215. package/dist/commands/protect.d.ts +0 -16
  216. package/dist/commands/protect.d.ts.map +0 -1
  217. package/dist/commands/protect.js +0 -323
  218. package/dist/commands/report.d.ts +0 -15
  219. package/dist/commands/report.d.ts.map +0 -1
  220. package/dist/commands/report.js +0 -214
  221. package/dist/policy/sync.d.ts +0 -67
  222. package/dist/policy/sync.d.ts.map +0 -1
  223. package/dist/policy/sync.js +0 -147
@@ -152,6 +152,13 @@ declare function boldColor(text: string, hex: string): string;
152
152
  declare function dim$1(text: string): string;
153
153
  /** Apply bold styling */
154
154
  declare function bold$1(text: string): string;
155
+ /**
156
+ * Get colored severity label for a severity level.
157
+ * High-severity levels (critical, error, serious, warning) are bold; others are plain colored.
158
+ */
159
+ declare function severityColor(level: string | undefined): string;
160
+ /** Apply background hex color to text */
161
+ declare function bgColor(text: string, hex: string): string;
155
162
  /** Apply gradient across text characters */
156
163
  declare function applyGradient(text: string, colors?: readonly string[]): string;
157
164
 
@@ -175,13 +182,104 @@ declare function isStdinTTY(): boolean;
175
182
  * Priority: NO_COLOR > FORCE_COLOR > CI (off) > TTY detection
176
183
  */
177
184
  declare function shouldUseColor(): boolean;
178
- /** Get terminal width from stderr (where UI renders). Falls back to 80. */
185
+ /** Get terminal width from stderr (where UI renders). Falls back to 80.
186
+ *
187
+ * Checks COLUMNS env var first so that non-PTY subprocesses (e.g. snapshot
188
+ * test harness) can set a deterministic width for reproducible output.
189
+ */
179
190
  declare function getTerminalWidth(): number;
180
191
  /** Get terminal height from stderr. Falls back to 24. */
181
192
  declare function getTerminalHeight(): number;
182
193
  /** Check if terminal supports Unicode (not dumb terminal). */
183
194
  declare function supportsUnicode(): boolean;
184
195
 
196
+ /**
197
+ * Plain mode state management.
198
+ *
199
+ * --plain is a superset of --no-color: it also replaces Unicode box-drawing
200
+ * chars and status symbols with ASCII equivalents, making output
201
+ * grep/awk/pipe-friendly (PLAIN-01, PLAIN-02).
202
+ *
203
+ * Circular dependency note: symbols.ts does NOT import from plain.ts.
204
+ * This module calls setSymbolTier() directly. detectSymbolTier() accepts
205
+ * a plainMode option parameter to receive state without circular import.
206
+ */
207
+ /**
208
+ * Enable or disable plain mode.
209
+ *
210
+ * When enabled:
211
+ * - isColorEnabled() returns false (color disabled)
212
+ * - Symbol tier is switched to "ascii"
213
+ * - toPlainBox() replaces Unicode box-drawing chars with ASCII
214
+ */
215
+ declare function setPlainMode(enabled: boolean): void;
216
+ /** Whether plain mode is currently active */
217
+ declare function isPlainMode(): boolean;
218
+ /**
219
+ * Replace Unicode box-drawing characters with ASCII equivalents.
220
+ *
221
+ * Is a no-op when plain mode is not active.
222
+ * Replacements:
223
+ * ─━═ → - │┃║ → | all corners/junctions (including rounded ╭╮╰╯) → +
224
+ */
225
+ declare function toPlainBox(str: string): string;
226
+
227
+ /**
228
+ * Three-tier glyph map for terminal status symbols.
229
+ *
230
+ * Tiers: nerd (Nerd Font PUA glyphs) → unicode (basic Unicode) → ascii (--plain)
231
+ * Default tier is "unicode". Tier is switched to "ascii" by setPlainMode(true).
232
+ *
233
+ * Circular dependency note: This module does NOT import from plain.ts.
234
+ * plain.ts calls setSymbolTier("ascii") directly. detectSymbolTier() accepts
235
+ * an options parameter to receive the plain mode state without importing it.
236
+ */
237
+ type SymbolRole = "success" | "fail" | "warning" | "info" | "pending" | "running";
238
+ type SymbolTier = "nerd" | "unicode" | "ascii";
239
+ /** Set the active symbol tier */
240
+ declare function setSymbolTier(tier: SymbolTier): void;
241
+ /** Get the symbol string for a given role using the current tier */
242
+ declare function sym(role: SymbolRole): string;
243
+ interface DetectSymbolTierOptions {
244
+ /** Override plain mode state (avoids circular dependency with plain.ts) */
245
+ plainMode?: boolean;
246
+ }
247
+ /**
248
+ * Detect the appropriate symbol tier based on environment.
249
+ *
250
+ * Priority:
251
+ * 1. plainMode option (or isPlainMode()) → "ascii"
252
+ * 2. VERTAA_ICONS env var (nerd|unicode|ascii) → explicit choice
253
+ * 3. Known Nerd Font terminals (TERM_PROGRAM) → "nerd"
254
+ * 4. supportsUnicode() → "unicode"
255
+ * 5. Fallback → "ascii"
256
+ */
257
+ declare function detectSymbolTier(options?: DetectSymbolTierOptions): SymbolTier;
258
+
259
+ /**
260
+ * Easing functions for animation clock.
261
+ *
262
+ * Pure math functions with no side effects or dependencies.
263
+ * Consumed by Phase 97+ for banner entrance animation and spinner timing.
264
+ */
265
+ /** Linear progression — t maps directly to output */
266
+ declare function linear(t: number): number;
267
+ /** Ease in — slow start, fast end (quadratic) */
268
+ declare function easeIn(t: number): number;
269
+ /** Ease out — fast start, slow end */
270
+ declare function easeOut(t: number): number;
271
+ /** Ease in-out — slow start and end, fast middle */
272
+ declare function easeInOut(t: number): number;
273
+ /**
274
+ * Interpolate between two values using an easing function.
275
+ *
276
+ * @param from - Start value
277
+ * @param to - End value
278
+ * @param t - Progress 0..1 (clamped automatically)
279
+ * @param ease - Easing function (default: linear)
280
+ */
281
+ declare function lerp(from: number, to: number, t: number, ease?: typeof linear): number;
282
+
185
283
  /**
186
284
  * Text styling primitives for terminal output.
187
285
  *
@@ -310,6 +408,13 @@ declare function renderTable(rows: Record<string, string>[], columns: Column[],
310
408
  * Renders an animated spinner with text to stderr.
311
409
  * Writes ONLY to stderr — never pollutes stdout.
312
410
  */
411
+ declare const BRAILLE_FRAMES: string[];
412
+ declare const FRAME_INTERVAL = 80;
413
+ /**
414
+ * Pure function: return the braille spinner character for the given frame index.
415
+ * Wraps around using modulo — frame index can be any non-negative integer.
416
+ */
417
+ declare function spinnerFrame(frameIndex: number): string;
313
418
  interface SpinnerInstance {
314
419
  /** Start the spinner animation */
315
420
  start(): void;
@@ -471,6 +576,117 @@ declare function renderDiff(lines: DiffLine[], opts?: DiffOptions): string;
471
576
  */
472
577
  declare function parseDiff(diffText: string): DiffLine[];
473
578
 
579
+ /**
580
+ * Branded error and warning box primitives.
581
+ *
582
+ * Renders error/warning messages in a rounded-border box with
583
+ * color hierarchy: bold red message, dim context, lime suggestion,
584
+ * dim exit code.
585
+ *
586
+ * Delegates to box() for border rendering.
587
+ * In plain mode, box() automatically converts to ASCII chars.
588
+ */
589
+ interface ErrorBoxOptions {
590
+ /** Primary error message (displayed bold) */
591
+ message: string;
592
+ /** Additional context about where/why the error occurred (displayed dim) */
593
+ context?: string;
594
+ /** Suggested resolution — displayed as "Try: suggestion" in lime */
595
+ suggestion?: string;
596
+ /** Exit code from underlying process */
597
+ exitCode?: number;
598
+ }
599
+ /**
600
+ * Render a branded error box.
601
+ *
602
+ * @param opts - Error box options
603
+ * @returns Rendered box string with rounded border, red border color
604
+ */
605
+ declare function renderError(opts: ErrorBoxOptions): string;
606
+ /**
607
+ * Render a branded warning box.
608
+ *
609
+ * @param opts - Warning box options (no exitCode)
610
+ * @returns Rendered box string with rounded border, amber border color
611
+ */
612
+ declare function renderWarning(opts: Omit<ErrorBoxOptions, "exitCode">): string;
613
+
614
+ /**
615
+ * Step-list rendering primitives for CLI step progress display.
616
+ *
617
+ * Provides types, pure rendering functions for multi-step progress UI.
618
+ * All rendering is stateless — pass StepState[] + frameIndex each render cycle.
619
+ */
620
+ type StepStatus = "pending" | "running" | "done" | "failed" | "skipped" | "warning";
621
+ /** Definition of a step (static configuration) */
622
+ interface StepDef {
623
+ id: string;
624
+ actionText: string;
625
+ summaryText: string;
626
+ run: () => Promise<void>;
627
+ subSteps?: StepDef[];
628
+ }
629
+ /** Mutable state of a step during execution */
630
+ interface StepState {
631
+ id: string;
632
+ actionText: string;
633
+ summaryText: string;
634
+ status: StepStatus;
635
+ startedAt: number | undefined;
636
+ finishedAt: number | undefined;
637
+ durationMs: number | undefined;
638
+ failReason: string | undefined;
639
+ subSteps: StepState[] | undefined;
640
+ }
641
+ /** Result of a completed step */
642
+ interface StepResult {
643
+ id: string;
644
+ status: StepStatus;
645
+ durationMs: number | undefined;
646
+ failReason: string | undefined;
647
+ }
648
+ /**
649
+ * Render a list of steps as a terminal string.
650
+ *
651
+ * @param steps - Array of step states to render
652
+ * @param frameIndex - Current animation frame index (for spinner)
653
+ * @param termWidth - Terminal width for right-alignment (default: 80)
654
+ * @returns Rendered string without trailing newline
655
+ */
656
+ declare function renderStepList(steps: StepState[], frameIndex: number, termWidth?: number): string;
657
+
658
+ /**
659
+ * runSteps — async step orchestrator.
660
+ *
661
+ * Executes a list of StepDef sequentially, managing state transitions
662
+ * and reporting via onStateChange callback.
663
+ *
664
+ * Fail modes:
665
+ * - failFast=true (CI/non-TTY default): mark current step "failed",
666
+ * mark remaining steps "skipped", return immediately.
667
+ * - failFast=false (interactive TTY default): mark current step "warning",
668
+ * continue to next step.
669
+ */
670
+
671
+ interface RunStepsOptions {
672
+ /** Whether to stop on first failure (default: isCI() || !isTTY()) */
673
+ failFast?: boolean;
674
+ /** Called after every state transition with the full states array */
675
+ onStateChange?: (states: StepState[]) => void;
676
+ }
677
+ interface RunStepsResult {
678
+ success: boolean;
679
+ states: StepState[];
680
+ }
681
+ /**
682
+ * Run a list of step definitions sequentially.
683
+ *
684
+ * @param defs - Step definitions to run
685
+ * @param opts - Options including failFast mode and onStateChange callback
686
+ * @returns Result with success flag and final states array
687
+ */
688
+ declare function runSteps(defs: StepDef[], opts?: RunStepsOptions): Promise<RunStepsResult>;
689
+
474
690
  /**
475
691
  * Renderer interface and factory for terminal output.
476
692
  *
@@ -478,6 +694,7 @@ declare function parseDiff(diffText: string): DiffLine[];
478
694
  * - AlternateScreenRenderer: Full terminal takeover (TTY)
479
695
  * - InlineRenderer: Timestamped log lines (CI/piped)
480
696
  */
697
+
481
698
  interface DashboardState {
482
699
  phase: string;
483
700
  phaseIndex: number;
@@ -490,6 +707,9 @@ interface DashboardState {
490
707
  scorePreview: number | null;
491
708
  verbose: boolean;
492
709
  elapsed: number;
710
+ /** Optional step states for step-list rendering. When present and non-empty,
711
+ * ComposedRenderer replaces the single-spinner line with a step list. */
712
+ stepStates?: StepState[];
493
713
  }
494
714
  interface SummaryResult {
495
715
  url: string;
@@ -507,12 +727,21 @@ interface Renderer {
507
727
  finish(result: SummaryResult): void;
508
728
  /** Clean up resources (keyboard, alternate screen, etc.) */
509
729
  dispose(): void;
730
+ /** Stop animation and show cursor before a prompt */
731
+ suspend(): void;
732
+ /** Restart animation after a prompt resolves */
733
+ resume(): void;
510
734
  }
511
- type RendererMode = "alternate" | "inline" | "auto";
735
+ type RendererMode = "alternate" | "inline" | "composed" | "auto";
736
+ /** Set a renderer override. Pass null to clear. */
737
+ declare function setRendererOverride(renderer: Renderer | null): void;
512
738
  /**
513
739
  * Create a renderer based on mode or auto-detection.
514
740
  *
515
- * auto: alternate in interactive TTY, inline in CI/piped
741
+ * If a renderer override is active (set by the interactive app),
742
+ * returns the override instead of creating a new one.
743
+ *
744
+ * auto: composed in interactive TTY, inline in CI/piped
516
745
  */
517
746
  declare function createRenderer(mode?: RendererMode, output?: NodeJS.WritableStream): Renderer;
518
747
 
@@ -531,9 +760,44 @@ declare class AlternateScreenRenderer implements Renderer {
531
760
  update(state: DashboardState): void;
532
761
  finish(result: SummaryResult): void;
533
762
  dispose(): void;
763
+ suspend(): void;
764
+ resume(): void;
534
765
  private renderSummary;
535
766
  }
536
767
 
768
+ /**
769
+ * ComposedRenderer — scroll-proof terminal rendering using alternate screen.
770
+ *
771
+ * Enters the alternate screen buffer on first update, renders the step-list
772
+ * with animated spinners, and exits on finish(). The alternate screen is
773
+ * scroll-proof — users cannot scroll past the rendered content.
774
+ *
775
+ * After finish(), output returns to the normal terminal where results
776
+ * (scores, issues, quality gate) are written to scrollback.
777
+ */
778
+
779
+ declare class ComposedRenderer implements Renderer {
780
+ private output;
781
+ private tickTimer;
782
+ private frameIndex;
783
+ private suspended;
784
+ private resizeTimer;
785
+ private lastState;
786
+ private entered;
787
+ constructor(output?: NodeJS.WritableStream);
788
+ update(state: DashboardState): void;
789
+ finish(result: SummaryResult): void;
790
+ dispose(): void;
791
+ suspend(): void;
792
+ resume(): void;
793
+ private startTick;
794
+ private stopTick;
795
+ private onResize;
796
+ private capContent;
797
+ private buildContent;
798
+ private buildFinishContent;
799
+ }
800
+
537
801
  /**
538
802
  * Inline renderer for CI/piped environments.
539
803
  *
@@ -549,6 +813,98 @@ declare class InlineRenderer implements Renderer {
549
813
  update(state: DashboardState): void;
550
814
  finish(result: SummaryResult): void;
551
815
  dispose(): void;
816
+ suspend(): void;
817
+ resume(): void;
818
+ }
819
+
820
+ /**
821
+ * Physical row calculation for terminal cursor math.
822
+ *
823
+ * Calculates how many terminal rows a string occupies at a given terminal
824
+ * width, accounting for line wrapping and ANSI escape sequences.
825
+ *
826
+ * Used by ComposedRenderer to determine how far to move the cursor up
827
+ * before redrawing — prevents cursor drift at 120+ column widths.
828
+ */
829
+ /**
830
+ * Calculate the number of physical terminal rows occupied by a string.
831
+ *
832
+ * Each logical line (split on "\n") occupies ceil(visibleLength / terminalWidth)
833
+ * rows, with a minimum of 1 row per line (empty lines still occupy a row).
834
+ *
835
+ * @param content - The string to measure (may contain ANSI escape codes and newlines)
836
+ * @param terminalWidth - The terminal column width
837
+ * @returns Number of physical rows, or 0 if terminalWidth <= 0
838
+ */
839
+ declare function physicalRows(content: string, terminalWidth: number): number;
840
+
841
+ /**
842
+ * ScrollingViewport — fixed-height arrow-key navigable list with expand/collapse.
843
+ *
844
+ * Renders a scrollable list of items within a bounded terminal region using
845
+ * cursor.up(N) + clearDown for in-place updates (no alternate screen).
846
+ *
847
+ * Features:
848
+ * - Up/Down arrows, j/k aliases, Page Up/Down navigation
849
+ * - Boundary stop (no wrap-around)
850
+ * - Top/bottom scroll indicators with item counts
851
+ * - Enter to toggle inline detail expansion; Esc to collapse
852
+ * - Ctrl+C exits cleanly and always restores terminal state
853
+ * - Terminal resize recalculates visibleRows and clamps scrollOffset
854
+ *
855
+ * All output goes to stderr (the `output` param). No alternate screen.
856
+ */
857
+ interface ViewportItem {
858
+ /** Unique identifier for this item */
859
+ id: string;
860
+ /** Severity level: critical, error, serious, warning, moderate, minor, info */
861
+ severity: string;
862
+ /** Display title */
863
+ title: string;
864
+ /** Effort estimate: trivial|small|medium|large */
865
+ effort: string;
866
+ /** Optional detail text shown when item is expanded */
867
+ detail?: string;
868
+ }
869
+ interface ViewportOptions {
870
+ items: ViewportItem[];
871
+ /** Maximum visible rows. Actual visibleRows = Math.min(maxRows, termHeight - 4). Default: 10 */
872
+ maxRows?: number;
873
+ /** Output stream. Default: process.stderr */
874
+ output?: NodeJS.WritableStream;
875
+ /** Input stream. Default: process.stdin */
876
+ stdin?: NodeJS.ReadStream;
877
+ }
878
+ declare class ScrollingViewport {
879
+ private readonly items;
880
+ private readonly maxRows;
881
+ private readonly output;
882
+ private readonly stdin;
883
+ /** Index of the currently highlighted item (0-indexed) */
884
+ cursorIdx: number;
885
+ /** Index of first visible item */
886
+ scrollOffset: number;
887
+ /** Index of expanded item (-1 = none) */
888
+ expandedIdx: number;
889
+ /** Calculated visible rows (updated on resize) */
890
+ visibleRows: number;
891
+ private lastRows;
892
+ private resizeTimer;
893
+ constructor(options: ViewportOptions);
894
+ /**
895
+ * Run the viewport interactively.
896
+ *
897
+ * Guard: if stdin is not a TTY or setRawMode is unavailable, returns
898
+ * immediately (non-interactive fallback).
899
+ *
900
+ * Resolves when the user presses Ctrl+C.
901
+ */
902
+ run(): Promise<void>;
903
+ private calcVisibleRows;
904
+ private clampScrollOffset;
905
+ private handleAction;
906
+ private buildFrame;
907
+ private redraw;
552
908
  }
553
909
 
554
910
  /**
@@ -590,6 +946,7 @@ declare function phaseTotal(): number;
590
946
  * Listens for keypresses in raw mode and emits semantic events.
591
947
  * Only works in TTY — gracefully no-ops in non-TTY environments.
592
948
  */
949
+ declare function setKeyboardOverrideActive(active: boolean): void;
593
950
  type KeyboardEvent = "quit" | "verbose";
594
951
  interface KeyboardHandler {
595
952
  /** Start listening for keypresses */
@@ -606,4 +963,4 @@ interface KeyboardHandler {
606
963
  */
607
964
  declare function createKeyboardHandler(stdin?: NodeJS.ReadStream): KeyboardHandler;
608
965
 
609
- export { AlternateScreenRenderer, AuditPhase, type AuditPhaseName, type BorderChars, type BorderStyle, type BoxOptions, type Column, type DashboardState, type DiffLine, type DiffMode, type DiffOptions, InlineRenderer, type KeyboardEvent, type KeyboardHandler, type ListOptions, type MultiProgress, PHASE_ORDER, type ProgressBar, type ProgressBarOptions, type Renderer, type RendererMode, type SeverityLevel, type SpinnerInstance, type SummaryResult, type TableOptions, type TreeNode, applyGradient, bold$1 as bold, boldColor, borders, box, brand, center, colorize, createKeyboardHandler, createMultiProgress, createProgressBar, createRenderer, createSpinner, cursor, dim$1 as dim, getTerminalHeight, getTerminalWidth, gradient, isCI, isColorEnabled, isStdinTTY, isStdoutTTY, isTTY, padEnd, padStart, parseDiff, phaseIndex, phaseTotal, renderDiff, renderFrame, renderGroupedList, renderList, renderTable, renderTree, scoreColor, screen, setColorEnabled, severity, severityLabels, severityOrder, shouldUseColor, stripAnsi, style, supportsUnicode, text, tokens, truncate, visibleLength };
966
+ export { AlternateScreenRenderer, AuditPhase, type AuditPhaseName, BRAILLE_FRAMES, type BorderChars, type BorderStyle, type BoxOptions, type Column, ComposedRenderer, type DashboardState, type DiffLine, type DiffMode, type DiffOptions, type ErrorBoxOptions, FRAME_INTERVAL, InlineRenderer, type KeyboardEvent, type KeyboardHandler, type ListOptions, type MultiProgress, PHASE_ORDER, type ProgressBar, type ProgressBarOptions, type Renderer, type RendererMode, type RunStepsOptions, ScrollingViewport, type SeverityLevel, type SpinnerInstance, type StepDef, type StepResult, type StepState, type StepStatus, type SummaryResult, type SymbolRole, type SymbolTier, type TableOptions, type TreeNode, type ViewportItem, type ViewportOptions, applyGradient, bgColor, bold$1 as bold, boldColor, borders, box, brand, center, colorize, createKeyboardHandler, createMultiProgress, createProgressBar, createRenderer, createSpinner, cursor, detectSymbolTier, dim$1 as dim, easeIn, easeInOut, easeOut, getTerminalHeight, getTerminalWidth, gradient, isCI, isColorEnabled, isPlainMode, isStdinTTY, isStdoutTTY, isTTY, lerp, linear, padEnd, padStart, parseDiff, phaseIndex, phaseTotal, physicalRows, renderDiff, renderError, renderFrame, renderGroupedList, renderList, renderStepList, renderTable, renderTree, renderWarning, runSteps, scoreColor, screen, setColorEnabled, setKeyboardOverrideActive, setPlainMode, setRendererOverride, setSymbolTier, severity, severityColor, severityLabels, severityOrder, shouldUseColor, spinnerFrame, stripAnsi, style, supportsUnicode, sym, text, toPlainBox, tokens, truncate, visibleLength };