@vibecodeqa/cli 0.40.0 → 0.41.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.
package/dist/core.d.ts ADDED
@@ -0,0 +1,28 @@
1
+ /** @vibecodeqa/cli/core — Programmatic scan API.
2
+ *
3
+ * Usage:
4
+ * import { scan } from "@vibecodeqa/cli/core";
5
+ * const report = await scan("./src");
6
+ * console.log(report.score, report.grade);
7
+ */
8
+ import { CHECK_META, getCheckMeta, type CheckMeta } from "./check-meta.js";
9
+ import { type VcqaConfig } from "./config.js";
10
+ import type { CheckResult, Issue, StackInfo, VibeReport, WorkspaceInfo, WorkspacePackage } from "./types.js";
11
+ export interface ScanOptions {
12
+ /** Skip test execution (faster scan). Default: false */
13
+ skipTests?: boolean;
14
+ /** Only run these checks (by name). Default: all checks */
15
+ checks?: string[];
16
+ /** Override config (instead of loading from .vcqa.json). */
17
+ config?: VcqaConfig;
18
+ /** Progress callback — called for each completed check. */
19
+ onProgress?: (check: string, result: CheckResult, index: number, total: number) => void;
20
+ }
21
+ /** Run a full code health scan. Returns a VibeReport with score, grade, and all check results. */
22
+ export declare function scan(cwd: string, options?: ScanOptions): Promise<VibeReport>;
23
+ export { CHECK_META, getCheckMeta, type CheckMeta };
24
+ export { computeScore } from "./score.js";
25
+ export { loadConfig, type VcqaConfig } from "./config.js";
26
+ export { detectStack, detectWorkspace } from "./detect.js";
27
+ export { gradeFromScore } from "./types.js";
28
+ export type { CheckResult, Issue, StackInfo, VibeReport, WorkspaceInfo, WorkspacePackage };
package/dist/core.js ADDED
@@ -0,0 +1,163 @@
1
+ /** @vibecodeqa/cli/core — Programmatic scan API.
2
+ *
3
+ * Usage:
4
+ * import { scan } from "@vibecodeqa/cli/core";
5
+ * const report = await scan("./src");
6
+ * console.log(report.score, report.grade);
7
+ */
8
+ import { resolve } from "node:path";
9
+ import { readFileSync } from "node:fs";
10
+ import { CHECK_META, getCheckMeta } from "./check-meta.js";
11
+ import { getCheckIgnore, isCheckEnabled, loadConfig } from "./config.js";
12
+ import { detectRepoUrl, detectStack, detectWorkspace } from "./detect.js";
13
+ import { setGlobalIgnore, setGlobalSrcRoots } from "./fs-utils.js";
14
+ import { runAccessibility } from "./runners/accessibility.js";
15
+ import { runArchitecture } from "./runners/architecture.js";
16
+ import { runBestPractices } from "./runners/best-practices.js";
17
+ import { runCodeCoherence } from "./runners/code-coherence.js";
18
+ import { runCommentStaleness } from "./runners/comment-staleness.js";
19
+ import { runComplexity } from "./runners/complexity.js";
20
+ import { runDeadPatterns } from "./runners/dead-patterns.js";
21
+ import { runTestAudit } from "./runners/test-audit.js";
22
+ import { runConfusion } from "./runners/confusion.js";
23
+ import { runContext } from "./runners/context.js";
24
+ import { runDependencies } from "./runners/dependencies.js";
25
+ import { runDocCoherence } from "./runners/doc-coherence.js";
26
+ import { runDocs } from "./runners/docs.js";
27
+ import { runDuplication } from "./runners/duplication.js";
28
+ import { runErrorHandling } from "./runners/error-handling.js";
29
+ import { runLint } from "./runners/lint.js";
30
+ import { runPerformance } from "./runners/performance.js";
31
+ import { runReact } from "./runners/react.js";
32
+ import { runSecrets } from "./runners/secrets.js";
33
+ import { runSecurity } from "./runners/security.js";
34
+ import { runStandards } from "./runners/standards.js";
35
+ import { runStructure } from "./runners/structure.js";
36
+ import { runTesting } from "./runners/testing.js";
37
+ import { runTypeSafety } from "./runners/type-safety.js";
38
+ import { runTypeCheck } from "./runners/types-check.js";
39
+ import { computeScore } from "./score.js";
40
+ import { gradeFromScore } from "./types.js";
41
+ const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf-8"));
42
+ const VERSION = pkg.version;
43
+ /** Run a full code health scan. Returns a VibeReport with score, grade, and all check results. */
44
+ export async function scan(cwd, options = {}) {
45
+ const start = Date.now();
46
+ const resolvedCwd = resolve(cwd);
47
+ const config = options.config ?? loadConfig(resolvedCwd);
48
+ const workspace = detectWorkspace(resolvedCwd);
49
+ const stack = detectStack(resolvedCwd, workspace);
50
+ const isDart = stack.language === "dart";
51
+ setGlobalSrcRoots(workspace.isMonorepo ? workspace.srcRoots : undefined);
52
+ setGlobalIgnore(config.ignore);
53
+ const srcRoots = workspace.isMonorepo ? workspace.srcRoots : undefined;
54
+ const skipTests = options.skipTests ?? false;
55
+ const allRunners = [
56
+ { name: "structure", fn: () => runStructure(resolvedCwd, stack, workspace) },
57
+ { name: "lint", fn: () => runLint(resolvedCwd, stack, workspace) },
58
+ { name: "types", fn: () => runTypeCheck(resolvedCwd, isDart, workspace) },
59
+ { name: "type-safety", fn: () => runTypeSafety(resolvedCwd, isDart) },
60
+ { name: "standards", fn: () => runStandards(resolvedCwd, stack) },
61
+ { name: "complexity", fn: () => runComplexity(resolvedCwd) },
62
+ { name: "duplication", fn: () => runDuplication(resolvedCwd) },
63
+ { name: "error-handling", fn: () => runErrorHandling(resolvedCwd, stack) },
64
+ { name: "react", fn: () => runReact(resolvedCwd, stack) },
65
+ { name: "accessibility", fn: () => runAccessibility(resolvedCwd) },
66
+ { name: "docs", fn: () => runDocs(resolvedCwd) },
67
+ { name: "best-practices", fn: () => runBestPractices(resolvedCwd, workspace) },
68
+ { name: "testing", fn: () => runTesting(resolvedCwd, stack, skipTests, srcRoots) },
69
+ { name: "secrets", fn: () => runSecrets(resolvedCwd) },
70
+ { name: "security", fn: () => runSecurity(resolvedCwd) },
71
+ { name: "dependencies", fn: () => runDependencies(resolvedCwd, stack) },
72
+ { name: "architecture", fn: () => runArchitecture(resolvedCwd, workspace) },
73
+ { name: "performance", fn: () => runPerformance(resolvedCwd) },
74
+ { name: "confusion", fn: () => runConfusion(resolvedCwd) },
75
+ { name: "context", fn: () => runContext(resolvedCwd) },
76
+ { name: "doc-coherence", fn: () => runDocCoherence(resolvedCwd) },
77
+ { name: "code-coherence", fn: () => runCodeCoherence(resolvedCwd) },
78
+ { name: "comment-staleness", fn: () => runCommentStaleness(resolvedCwd) },
79
+ { name: "dead-patterns", fn: () => runDeadPatterns(resolvedCwd) },
80
+ { name: "test-audit", fn: () => runTestAudit(resolvedCwd) },
81
+ ];
82
+ // Filter checks if specified
83
+ const checkFilter = options.checks ? new Set(options.checks) : null;
84
+ const runners = checkFilter
85
+ ? allRunners.filter((r) => checkFilter.has(r.name))
86
+ : allRunners;
87
+ const checks = [];
88
+ const total = runners.length;
89
+ for (let i = 0; i < total; i++) {
90
+ const runner = runners[i];
91
+ if (!isCheckEnabled(config, runner.name)) {
92
+ const skipped = {
93
+ name: runner.name,
94
+ score: 0,
95
+ grade: "F",
96
+ details: { skipped: true, reason: "disabled in config" },
97
+ issues: [],
98
+ duration: 0,
99
+ };
100
+ checks.push(skipped);
101
+ options.onProgress?.(runner.name, skipped, i, total);
102
+ continue;
103
+ }
104
+ let result;
105
+ try {
106
+ const maybeResult = runner.fn();
107
+ result = maybeResult instanceof Promise ? await maybeResult : maybeResult;
108
+ }
109
+ catch (err) {
110
+ result = {
111
+ name: runner.name,
112
+ score: 0,
113
+ grade: "F",
114
+ details: { skipped: true, reason: `runner error: ${err instanceof Error ? err.message : "unknown"}` },
115
+ issues: [],
116
+ duration: 0,
117
+ };
118
+ }
119
+ // Apply per-check ignore patterns
120
+ const patterns = getCheckIgnore(config, result.name);
121
+ if (patterns?.length) {
122
+ result.issues = result.issues.filter((issue) => {
123
+ if (!issue.file || typeof issue.file !== "string")
124
+ return true;
125
+ const f = issue.file;
126
+ return !patterns.some((p) => {
127
+ if (p.endsWith("/**"))
128
+ return f.startsWith(p.slice(0, -3) + "/");
129
+ if (p.startsWith("*"))
130
+ return f.endsWith(p.slice(1));
131
+ return f.startsWith(p);
132
+ });
133
+ });
134
+ }
135
+ checks.push(result);
136
+ options.onProgress?.(runner.name, result, i, total);
137
+ }
138
+ const score = computeScore(checks);
139
+ const grade = gradeFromScore(score);
140
+ const { repoUrl, branch } = detectRepoUrl(resolvedCwd);
141
+ return {
142
+ version: VERSION,
143
+ timestamp: new Date().toISOString(),
144
+ score,
145
+ grade,
146
+ checks,
147
+ meta: {
148
+ cwd: resolvedCwd,
149
+ node: process.version,
150
+ duration: Date.now() - start,
151
+ stack,
152
+ workspace,
153
+ repoUrl,
154
+ branch,
155
+ },
156
+ };
157
+ }
158
+ // ── Re-exports ──
159
+ export { CHECK_META, getCheckMeta };
160
+ export { computeScore } from "./score.js";
161
+ export { loadConfig } from "./config.js";
162
+ export { detectStack, detectWorkspace } from "./detect.js";
163
+ export { gradeFromScore } from "./types.js";
package/package.json CHANGED
@@ -1,12 +1,16 @@
1
1
  {
2
2
  "name": "@vibecodeqa/cli",
3
- "version": "0.40.0",
3
+ "version": "0.41.0",
4
4
  "description": "Code health scanner for the AI coding era. 25 checks, zero config, full report.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "vcqa": "./dist/cli.js",
8
8
  "vibe-check": "./dist/cli.js"
9
9
  },
10
+ "exports": {
11
+ ".": "./dist/cli.js",
12
+ "./core": "./dist/core.js"
13
+ },
10
14
  "files": [
11
15
  "dist",
12
16
  "LICENSE",