@vibecodeqa/cli 0.37.2 → 0.37.4

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/monitor.js +24 -18
  2. package/package.json +1 -1
package/dist/monitor.js CHANGED
@@ -164,7 +164,7 @@ function ActivityPanel({ log, height }) {
164
164
  improve: "green", regress: "red", error: "red", alert: "magenta",
165
165
  };
166
166
  const visibleLines = Math.max(1, height - 3);
167
- return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 1, height: height, overflowY: "hidden", children: [_jsx(Text, { bold: true, color: "magenta", children: " \u25C8 Activity" }), log.slice(-visibleLines).map((entry, i) => (_jsxs(Text, { wrap: "truncate", children: [_jsxs(Text, { dimColor: true, children: [entry.time, " "] }), _jsx(Text, { color: colors[entry.type], children: entry.text })] }, i)))] }));
167
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 1, height: height, overflowY: "hidden", children: [_jsx(Text, { bold: true, color: "magenta", children: " \u25C8 Activity" }), log.slice(-visibleLines).map((entry, i) => (_jsxs(Text, { wrap: "truncate", children: [_jsxs(Text, { dimColor: true, children: [entry.time, " "] }), _jsx(Text, { color: colors[entry.type], children: entry.text })] }, `${entry.time}-${i}`)))] }));
168
168
  }
169
169
  function ConfigScreen({ cursor, options }) {
170
170
  return (_jsxs(Box, { flexDirection: "column", borderStyle: "double", borderColor: "magenta", paddingX: 2, paddingY: 1, children: [_jsx(Text, { bold: true, color: "magenta", children: " \u2699 Settings" }), _jsx(Text, { dimColor: true, children: " " }), options.map((opt, i) => {
@@ -346,11 +346,10 @@ function IssueDetail({ issue, checkName, cwd, height, copied }) {
346
346
  const srcHeight = ctx ? Math.min(ctx.lines.length + 2, Math.floor((height - 8) * 0.6)) : 0;
347
347
  const promptHeight = height - 8 - srcHeight;
348
348
  const promptLines = prompt.split("\n");
349
- return (_jsxs(Box, { flexDirection: "column", height: height, paddingX: 1, overflowY: "hidden", children: [_jsx(Text, { bold: true, color: "magenta", children: " \u25C8 Issue Detail" }), _jsxs(Text, { children: [_jsxs(Text, { color: sc(issue.severity), bold: true, children: [" ", issue.severity.toUpperCase(), " "] }), _jsx(Text, { dimColor: true, children: checkName }), issue.rule && _jsxs(Text, { dimColor: true, children: [" \u00B7 ", issue.rule] }), copied && _jsx(Text, { color: "green", bold: true, children: " \u2713 Copied!" })] }), _jsxs(Text, { wrap: "wrap", children: [" ", issue.message] }), issue.file && (_jsxs(Text, { color: "cyan", children: [" ", issue.file, issue.line ? `:${issue.line}` : ""] })), ctx && (_jsxs(Box, { flexDirection: "column", height: srcHeight, overflowY: "hidden", children: [_jsxs(Text, { dimColor: true, children: [" \u2500\u2500\u2500 ", ctx.filePath, " \u2500\u2500\u2500"] }), ctx.lines.slice(0, srcHeight - 2).map((l) => (_jsxs(Text, { wrap: "truncate", children: [_jsx(Text, { color: l.highlight ? "yellow" : "gray", children: l.highlight ? "▸" : " " }), _jsxs(Text, { dimColor: true, children: [String(l.num).padStart(4), "\u2502"] }), _jsx(Text, { color: l.highlight ? "white" : undefined, children: l.text })] }, l.num))), _jsx(Text, { dimColor: true, children: " \u2500\u2500\u2500" })] })), _jsxs(Box, { flexDirection: "column", height: Math.max(3, promptHeight), overflowY: "hidden", marginTop: ctx ? 0 : 1, children: [_jsxs(Text, { bold: true, color: "green", children: [" Fix prompt ", _jsx(Text, { dimColor: true, children: "(y to copy)" })] }), promptLines.slice(0, Math.max(1, promptHeight - 1)).map((line, i) => (_jsxs(Text, { dimColor: true, wrap: "truncate", children: [" ", line] }, i)))] })] }));
349
+ return (_jsxs(Box, { flexDirection: "column", height: height, paddingX: 1, overflowY: "hidden", children: [_jsx(Text, { bold: true, color: "magenta", children: " \u25C8 Issue Detail" }), _jsxs(Text, { children: [_jsxs(Text, { color: sc(issue.severity), bold: true, children: [" ", issue.severity.toUpperCase(), " "] }), _jsx(Text, { dimColor: true, children: checkName }), issue.rule && _jsxs(Text, { dimColor: true, children: [" \u00B7 ", issue.rule] }), copied && _jsx(Text, { color: "green", bold: true, children: " \u2713 Copied!" })] }), _jsxs(Text, { wrap: "wrap", children: [" ", issue.message] }), issue.file && (_jsxs(Text, { color: "cyan", children: [" ", issue.file, issue.line ? `:${issue.line}` : ""] })), ctx && (_jsxs(Box, { flexDirection: "column", height: srcHeight, overflowY: "hidden", children: [_jsxs(Text, { dimColor: true, children: [" \u2500\u2500\u2500 ", ctx.filePath, " \u2500\u2500\u2500"] }), ctx.lines.slice(0, srcHeight - 2).map((l) => (_jsxs(Text, { wrap: "truncate", children: [_jsx(Text, { color: l.highlight ? "yellow" : "gray", children: l.highlight ? "▸" : " " }), _jsxs(Text, { dimColor: true, children: [String(l.num).padStart(4), "\u2502"] }), _jsx(Text, { color: l.highlight ? "white" : undefined, children: l.text })] }, l.num))), _jsx(Text, { dimColor: true, children: " \u2500\u2500\u2500" })] })), _jsxs(Box, { flexDirection: "column", height: Math.max(3, promptHeight), overflowY: "hidden", marginTop: ctx ? 0 : 1, children: [_jsxs(Text, { bold: true, color: "green", children: [" Fix prompt ", _jsx(Text, { dimColor: true, children: "(y to copy)" })] }), promptLines.slice(0, Math.max(1, promptHeight - 1)).map((line, i) => (_jsxs(Text, { dimColor: true, wrap: "truncate", children: [" ", line] }, `p-${i}`)))] })] }));
350
350
  }
351
351
  // ── Git Changes View ──
352
- function GitChangesView({ cwd, checks, height, cursor }) {
353
- const changes = useMemo(() => getGitChanges(cwd), [cwd]);
352
+ function GitChangesView({ changes, checks, height, cursor }) {
354
353
  // Cross-reference with issues
355
354
  const issuesByFile = useMemo(() => {
356
355
  const map = new Map();
@@ -440,6 +439,18 @@ function MonitorApp({ cwd }) {
440
439
  return (o[a.severity] ?? 2) - (o[b.severity] ?? 2);
441
440
  }), [state.checks]);
442
441
  const currentList = panel === "checks" ? activeChecks : allIssues;
442
+ // Derived data for file views (memoized, used by both render + keyboard)
443
+ const filesWithIssues = useMemo(() => {
444
+ const map = new Map();
445
+ for (const c of state.checks) {
446
+ for (const iss of c.issues) {
447
+ if (iss.file && typeof iss.file === "string")
448
+ map.set(iss.file, (map.get(iss.file) || 0) + 1);
449
+ }
450
+ }
451
+ return [...map.keys()].sort((a, b) => (map.get(b) || 0) - (map.get(a) || 0));
452
+ }, [state.checks]);
453
+ const gitChanges = useMemo(() => getGitChanges(cwd), [cwd, state.scanCount]);
443
454
  // Clamp cursor when data changes
444
455
  useEffect(() => {
445
456
  setCursor((c) => Math.min(c, Math.max(0, currentList.length - 1)));
@@ -679,28 +690,23 @@ function MonitorApp({ cwd }) {
679
690
  }
680
691
  // ── All files: ↑↓ navigate, Enter drill into file issues ──
681
692
  if (mode.view === "all-files") {
682
- const fileMap = state.checks
683
- .flatMap((c) => c.issues.filter((i) => i.file && typeof i.file === "string").map((i) => i.file))
684
- .reduce((map, f) => { map.set(f, (map.get(f) || 0) + 1); return map; }, new Map());
685
- const files = [...fileMap.keys()].sort((a, b) => (fileMap.get(b) || 0) - (fileMap.get(a) || 0));
686
693
  if (key.upArrow)
687
694
  setCursor((c) => Math.max(0, c - 1));
688
695
  if (key.downArrow)
689
- setCursor((c) => Math.min(files.length - 1, c + 1));
690
- if (key.return && files[cursor]) {
691
- setMode({ view: "file-issues", file: files[cursor] });
696
+ setCursor((c) => Math.min(filesWithIssues.length - 1, c + 1));
697
+ if (key.return && filesWithIssues[cursor]) {
698
+ setMode({ view: "file-issues", file: filesWithIssues[cursor] });
692
699
  setCursor(0);
693
700
  }
694
701
  }
695
702
  // ── Git changes: ↑↓ navigate, Enter drill into file issues ──
696
703
  if (mode.view === "git-changes") {
697
- const changes = getGitChanges(cwd);
698
704
  if (key.upArrow)
699
705
  setCursor((c) => Math.max(0, c - 1));
700
706
  if (key.downArrow)
701
- setCursor((c) => Math.min(changes.length - 1, c + 1));
702
- if (key.return && changes[cursor]) {
703
- setMode({ view: "file-issues", file: changes[cursor].file });
707
+ setCursor((c) => Math.min(gitChanges.length - 1, c + 1));
708
+ if (key.return && gitChanges[cursor]) {
709
+ setMode({ view: "file-issues", file: gitChanges[cursor].file });
704
710
  setCursor(0);
705
711
  }
706
712
  }
@@ -738,13 +744,13 @@ function MonitorApp({ cwd }) {
738
744
  return (_jsxs(Box, { flexDirection: "column", height: rows, children: [_jsx(Header, { proj: proj, stack: stack, workspace: workspace, state: state }), _jsx(AllFilesView, { checks: state.checks, height: rows - 3, cursor: cursor }), _jsx(Box, { paddingX: 1, children: _jsx(Text, { dimColor: true, children: "Esc back \u00B7 \u2191\u2193 select \u00B7 Enter view file issues \u00B7 q quit" }) })] }));
739
745
  }
740
746
  if (mode.view === "git-changes") {
741
- return (_jsxs(Box, { flexDirection: "column", height: rows, children: [_jsx(Header, { proj: proj, stack: stack, workspace: workspace, state: state }), _jsx(GitChangesView, { cwd: cwd, checks: state.checks, height: rows - 3, cursor: cursor }), _jsx(Box, { paddingX: 1, children: _jsx(Text, { dimColor: true, children: "Esc back \u00B7 \u2191\u2193 select \u00B7 Enter view file issues \u00B7 q quit" }) })] }));
747
+ return (_jsxs(Box, { flexDirection: "column", height: rows, children: [_jsx(Header, { proj: proj, stack: stack, workspace: workspace, state: state }), _jsx(GitChangesView, { changes: gitChanges, checks: state.checks, height: rows - 3, cursor: cursor }), _jsx(Box, { paddingX: 1, children: _jsx(Text, { dimColor: true, children: "Esc back \u00B7 \u2191\u2193 select \u00B7 Enter view file issues \u00B7 q quit" }) })] }));
742
748
  }
743
749
  if (mode.view === "file-issues") {
744
750
  const fileIssues = state.checks.flatMap((c) => c.issues.filter((i) => i.file === mode.file).map((i) => ({ check: c.name, ...i })));
745
751
  return (_jsxs(Box, { flexDirection: "column", height: rows, children: [_jsx(Header, { proj: proj, stack: stack, workspace: workspace, state: state }), _jsxs(Box, { flexDirection: "column", height: rows - 3, paddingX: 1, overflowY: "hidden", children: [_jsxs(Text, { bold: true, color: "magenta", children: [" \u25C8 ", mode.file] }), _jsxs(Text, { dimColor: true, children: [" ", fileIssues.length, " issue", fileIssues.length !== 1 ? "s" : "", copied && _jsx(Text, { color: "green", bold: true, children: " \u2713 Copied!" })] }), _jsx(Text, { children: " " }), fileIssues.length === 0 ? (_jsx(Text, { color: "green", children: " No issues in this file." })) : (fileIssues.slice(0, rows - 8).map((iss, i) => {
746
752
  const sel = i === cursor;
747
- return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { children: [_jsx(Text, { color: sel ? "white" : "gray", children: sel ? "▸" : " " }), _jsxs(Text, { color: sc(iss.severity), bold: true, children: [iss.severity[0].toUpperCase(), " "] }), iss.line && _jsx(Text, { color: "cyan", children: String(iss.line).padEnd(5) }), _jsx(Text, { dimColor: true, children: iss.check.padEnd(14) }), iss.rule && _jsxs(Text, { dimColor: true, children: ["(", iss.rule, ") "] })] }), _jsxs(Text, { wrap: "wrap", children: [_jsx(Text, { color: sel ? "white" : "gray", children: " " }), _jsx(Text, { color: sel ? "white" : undefined, children: iss.message })] })] }, i));
753
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { children: [_jsx(Text, { color: sel ? "white" : "gray", children: sel ? "▸" : " " }), _jsxs(Text, { color: sc(iss.severity), bold: true, children: [iss.severity[0].toUpperCase(), " "] }), iss.line && _jsx(Text, { color: "cyan", children: String(iss.line).padEnd(5) }), _jsx(Text, { dimColor: true, children: iss.check.padEnd(14) }), iss.rule && _jsxs(Text, { dimColor: true, children: ["(", iss.rule, ") "] })] }), _jsxs(Text, { wrap: "wrap", children: [_jsx(Text, { color: sel ? "white" : "gray", children: " " }), _jsx(Text, { color: sel ? "white" : undefined, children: iss.message })] })] }, `${iss.check}-${iss.line || i}`));
748
754
  }))] }), _jsx(Box, { paddingX: 1, children: _jsx(Text, { dimColor: true, children: "Esc back \u00B7 \u2191\u2193 select \u00B7 Enter source \u00B7 y copy prompt \u00B7 q quit" }) })] }));
749
755
  }
750
756
  if (mode.view === "issue-detail") {
@@ -777,7 +783,7 @@ function MonitorApp({ cwd }) {
777
783
  return (_jsxs(Text, { children: [_jsxs(Text, { color: sel ? "white" : gc(c.grade), children: [sel ? "▸" : " ", c.grade === "A" ? "●" : c.grade === "B" ? "◐" : "○", " "] }), _jsx(Text, { bold: sel, children: c.name.slice(0, 13).padEnd(13) }), _jsx(Text, { color: gc(c.grade), children: String(c.score).padStart(3) })] }, c.name));
778
784
  })] }))] })), mainVisible && (_jsxs(Box, { flexDirection: "column", flexGrow: 1, children: [p.activity && _jsx(ActivityPanel, { log: log, height: activityH }), p.issues && (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: panel === "issues" ? "magenta" : "gray", paddingX: 1, height: issuesH, overflowY: "hidden", children: [_jsxs(Text, { bold: true, color: "magenta", children: [" ", "\u25C8 Issues (", allIssues.length, ") ", panel === "issues" && _jsx(Text, { dimColor: true, children: "\u25C4" })] }), allIssues.slice(0, issuesH - 3).map((iss, i) => {
779
785
  const sel = panel === "issues" && i === cursor;
780
- return (_jsxs(Text, { wrap: "truncate", children: [_jsx(Text, { color: sel ? "white" : "gray", children: sel ? "▸" : " " }), _jsxs(Text, { color: sc(iss.severity), bold: true, children: [iss.severity[0].toUpperCase(), " "] }), _jsxs(Text, { dimColor: true, children: [(iss.check || "").slice(0, 11).padEnd(11), " "] }), iss.file && _jsxs(Text, { color: "cyan", children: [basename(String(iss.file)).slice(0, 18).padEnd(18), " "] }), _jsx(Text, { children: iss.message.slice(0, 40) })] }, i));
786
+ return (_jsxs(Text, { wrap: "truncate", children: [_jsx(Text, { color: sel ? "white" : "gray", children: sel ? "▸" : " " }), _jsxs(Text, { color: sc(iss.severity), bold: true, children: [iss.severity[0].toUpperCase(), " "] }), _jsxs(Text, { dimColor: true, children: [(iss.check || "").slice(0, 11).padEnd(11), " "] }), iss.file && _jsxs(Text, { color: "cyan", children: [basename(String(iss.file)).slice(0, 18).padEnd(18), " "] }), _jsx(Text, { children: iss.message.slice(0, 40) })] }, `${iss.check}-${iss.file || ""}-${iss.line || i}`));
781
787
  }), allIssues.length > issuesH - 3 && _jsxs(Text, { dimColor: true, children: [" +", allIssues.length - (issuesH - 3), " more"] })] }))] })), !sidebarVisible && !mainVisible && (_jsx(Box, { height: bodyRows, justifyContent: "center", alignItems: "center", children: _jsx(Text, { dimColor: true, children: "All panels hidden. Press c to configure." }) }))] }), _jsx(Box, { paddingX: 1, justifyContent: "space-between", children: _jsx(Text, { dimColor: true, children: "Tab panel \u00B7 \u2191\u2193 Enter Esc \u00B7 r scan \u00B7 f files \u00B7 g git \u00B7 t trends \u00B7 c config \u00B7 q" }) })] }));
782
788
  }
783
789
  function Header({ proj, stack, workspace, state }) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibecodeqa/cli",
3
- "version": "0.37.2",
3
+ "version": "0.37.4",
4
4
  "description": "Code health scanner for the AI coding era. 25 checks, zero config, full report.",
5
5
  "type": "module",
6
6
  "bin": {