@fisaabil_/ai-verify 0.1.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 (68) hide show
  1. package/README.md +81 -0
  2. package/dist/analyzer/analyzer.d.ts +4 -0
  3. package/dist/analyzer/analyzer.js +2 -0
  4. package/dist/analyzer/analyzer.js.map +1 -0
  5. package/dist/analyzer/git-analyzer.d.ts +15 -0
  6. package/dist/analyzer/git-analyzer.js +208 -0
  7. package/dist/analyzer/git-analyzer.js.map +1 -0
  8. package/dist/analyzer/language.d.ts +1 -0
  9. package/dist/analyzer/language.js +23 -0
  10. package/dist/analyzer/language.js.map +1 -0
  11. package/dist/cli/index.d.ts +2 -0
  12. package/dist/cli/index.js +38 -0
  13. package/dist/cli/index.js.map +1 -0
  14. package/dist/cli/report.d.ts +6 -0
  15. package/dist/cli/report.js +65 -0
  16. package/dist/cli/report.js.map +1 -0
  17. package/dist/cli/version.d.ts +1 -0
  18. package/dist/cli/version.js +12 -0
  19. package/dist/cli/version.js.map +1 -0
  20. package/dist/core/orchestrator.d.ts +17 -0
  21. package/dist/core/orchestrator.js +21 -0
  22. package/dist/core/orchestrator.js.map +1 -0
  23. package/dist/core/types/analysis.d.ts +6 -0
  24. package/dist/core/types/analysis.js +2 -0
  25. package/dist/core/types/analysis.js.map +1 -0
  26. package/dist/core/types/change.d.ts +15 -0
  27. package/dist/core/types/change.js +2 -0
  28. package/dist/core/types/change.js.map +1 -0
  29. package/dist/core/types/finding.d.ts +15 -0
  30. package/dist/core/types/finding.js +2 -0
  31. package/dist/core/types/finding.js.map +1 -0
  32. package/dist/core/types/index.d.ts +5 -0
  33. package/dist/core/types/index.js +2 -0
  34. package/dist/core/types/index.js.map +1 -0
  35. package/dist/core/types/risk.d.ts +11 -0
  36. package/dist/core/types/risk.js +2 -0
  37. package/dist/core/types/risk.js.map +1 -0
  38. package/dist/core/types/verification.d.ts +17 -0
  39. package/dist/core/types/verification.js +2 -0
  40. package/dist/core/types/verification.js.map +1 -0
  41. package/dist/risk/index.d.ts +4 -0
  42. package/dist/risk/index.js +4 -0
  43. package/dist/risk/index.js.map +1 -0
  44. package/dist/risk/levels.d.ts +2 -0
  45. package/dist/risk/levels.js +16 -0
  46. package/dist/risk/levels.js.map +1 -0
  47. package/dist/risk/risk-engine.d.ts +7 -0
  48. package/dist/risk/risk-engine.js +15 -0
  49. package/dist/risk/risk-engine.js.map +1 -0
  50. package/dist/risk/rules.d.ts +2 -0
  51. package/dist/risk/rules.js +137 -0
  52. package/dist/risk/rules.js.map +1 -0
  53. package/dist/verifier/engine.d.ts +7 -0
  54. package/dist/verifier/engine.js +20 -0
  55. package/dist/verifier/engine.js.map +1 -0
  56. package/dist/verifier/index.d.ts +4 -0
  57. package/dist/verifier/index.js +4 -0
  58. package/dist/verifier/index.js.map +1 -0
  59. package/dist/verifier/select.d.ts +3 -0
  60. package/dist/verifier/select.js +10 -0
  61. package/dist/verifier/select.js.map +1 -0
  62. package/dist/verifier/typecheck.d.ts +8 -0
  63. package/dist/verifier/typecheck.js +114 -0
  64. package/dist/verifier/typecheck.js.map +1 -0
  65. package/dist/verifier/verifier.d.ts +10 -0
  66. package/dist/verifier/verifier.js +2 -0
  67. package/dist/verifier/verifier.js.map +1 -0
  68. package/package.json +43 -0
package/README.md ADDED
@@ -0,0 +1,81 @@
1
+ # AI Verify
2
+
3
+ > AI can generate code. AI Verify helps verify it.
4
+
5
+ Open-source, risk-adaptive verification infrastructure for AI-generated software.
6
+ It analyzes what changed, assesses how risky it is, and runs only the checks
7
+ that fit — then reports a clear `PASSED` / `FAILED` result.
8
+
9
+ ## Requirements
10
+
11
+ * Node.js `>= 18`
12
+ * Git
13
+
14
+ No config files. No extra services. Check tools (like `tsc`) are used from the
15
+ target repository itself when available — never downloaded automatically.
16
+
17
+ ## Install (no clone needed)
18
+
19
+ Once published, pick one — running stays in the terminal:
20
+
21
+ ```bash
22
+ npm install -g ai-verify
23
+ ai-verify /path/to/your/repo
24
+ ```
25
+
26
+ Try without installing:
27
+
28
+ ```bash
29
+ npx ai-verify@latest /path/to/your/repo
30
+ ```
31
+
32
+ Pin it for a team (inside your project):
33
+
34
+ ```bash
35
+ npm install -D ai-verify
36
+ npx ai-verify .
37
+ ```
38
+
39
+ No `sudo`, no config files, no extra services. The `ai-verify` command is
40
+ created automatically on install. If global install reports a permission
41
+ error, that comes from your npm prefix setup — prefer `npx` or point your
42
+ npm prefix at a directory you own.
43
+
44
+ ## Quickstart (from source)
45
+
46
+ Or during development:
47
+
48
+ ```bash
49
+ npm run dev -- /path/to/your/repo
50
+ ```
51
+
52
+ ## What the output means
53
+
54
+ ```text
55
+ Risk: HIGH (72) # NONE / LOW / MEDIUM / HIGH / CRITICAL + score 0-100
56
+ Factors: # why: auth change, no tests, large change, ...
57
+ +30 Authentication change — ...
58
+
59
+ Verification (812ms)
60
+ ✓ Type Check — passed # ✓ passed, ✗ failed, - skipped, ! error
61
+ - Type Check — skipped (TypeScript compiler (tsc) is not available ...)
62
+ Findings: 1
63
+ [HIGH] TS2322: ... (src/app.ts:12)
64
+ Result: PASSED # FAILED if any check failed or errored
65
+ ```
66
+
67
+ Honesty rules:
68
+
69
+ * A check that does not apply is `skipped` with a reason — never a failure.
70
+ * A missing tool is `skipped`, never downloaded or installed for you.
71
+ * A crashed tool is `error`, not silently treated as passed.
72
+
73
+ ## Quality checks
74
+
75
+ ```bash
76
+ npm run check # type check
77
+ npm run test # tests
78
+ npm run build # build
79
+ ```
80
+
81
+ See `docs/workflow.md` for the full vision, architecture, and roadmap.
@@ -0,0 +1,4 @@
1
+ import type { AnalysisRequest, ChangeSet } from "../core/types/index.js";
2
+ export interface Analyzer {
3
+ analyze(request: AnalysisRequest): Promise<ChangeSet>;
4
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../../src/analyzer/analyzer.ts"],"names":[],"mappings":""}
@@ -0,0 +1,15 @@
1
+ import type { AnalysisRequest, ChangeSet } from "../core/types/index.js";
2
+ import type { Analyzer } from "./analyzer.js";
3
+ export declare class GitAnalyzer implements Analyzer {
4
+ analyze(request: AnalysisRequest): Promise<ChangeSet>;
5
+ private assertGitRepository;
6
+ private getGitChanges;
7
+ private parseNameStatus;
8
+ private parseNameStatusLine;
9
+ private getUntrackedFiles;
10
+ private createFileChange;
11
+ private getFileStats;
12
+ private isTrackedFile;
13
+ private countUntrackedFileLines;
14
+ private parseStat;
15
+ }
@@ -0,0 +1,208 @@
1
+ import { execFile } from "node:child_process";
2
+ import path from "node:path";
3
+ import { promisify } from "node:util";
4
+ import { detectLanguage } from "./language.js";
5
+ const execFileAsync = promisify(execFile);
6
+ export class GitAnalyzer {
7
+ async analyze(request) {
8
+ const repositoryPath = path.resolve(request.repositoryPath);
9
+ await this.assertGitRepository(repositoryPath);
10
+ const changes = await this.getGitChanges(repositoryPath, request.includeUncommittedChanges);
11
+ const files = [];
12
+ for (const change of changes) {
13
+ const fileChange = await this.createFileChange(repositoryPath, change);
14
+ files.push(fileChange);
15
+ }
16
+ return {
17
+ files,
18
+ totalAdditions: files.reduce((total, file) => total + file.additions, 0),
19
+ totalDeletions: files.reduce((total, file) => total + file.deletions, 0),
20
+ };
21
+ }
22
+ async assertGitRepository(repositoryPath) {
23
+ try {
24
+ await execFileAsync("git", ["rev-parse", "--is-inside-work-tree"], {
25
+ cwd: repositoryPath,
26
+ });
27
+ }
28
+ catch {
29
+ throw new Error(`The target directory is not a Git repository: ${repositoryPath}`);
30
+ }
31
+ }
32
+ async getGitChanges(repositoryPath, includeUncommittedChanges) {
33
+ const args = includeUncommittedChanges
34
+ ? ["diff", "HEAD", "--name-status", "-M"]
35
+ : ["diff", "HEAD~1", "HEAD", "--name-status", "-M"];
36
+ const { stdout } = await execFileAsync("git", args, {
37
+ cwd: repositoryPath,
38
+ });
39
+ const changes = this.parseNameStatus(stdout);
40
+ if (!includeUncommittedChanges) {
41
+ return changes;
42
+ }
43
+ const untrackedFiles = await this.getUntrackedFiles(repositoryPath);
44
+ return [
45
+ ...changes,
46
+ ...untrackedFiles.map((filePath) => ({
47
+ path: filePath,
48
+ changeType: "added",
49
+ })),
50
+ ];
51
+ }
52
+ parseNameStatus(output) {
53
+ if (!output.trim()) {
54
+ return [];
55
+ }
56
+ return output
57
+ .split("\n")
58
+ .map((line) => line.trim())
59
+ .filter(Boolean)
60
+ .flatMap((line) => this.parseNameStatusLine(line));
61
+ }
62
+ parseNameStatusLine(line) {
63
+ const parts = line.split("\t");
64
+ if (parts.length < 2) {
65
+ return [];
66
+ }
67
+ const status = parts[0];
68
+ const firstPath = parts[1];
69
+ if (!status || !firstPath) {
70
+ return [];
71
+ }
72
+ const statusCode = status[0];
73
+ switch (statusCode) {
74
+ case "A":
75
+ return [
76
+ {
77
+ path: firstPath,
78
+ changeType: "added",
79
+ },
80
+ ];
81
+ case "M":
82
+ return [
83
+ {
84
+ path: firstPath,
85
+ changeType: "modified",
86
+ },
87
+ ];
88
+ case "D":
89
+ return [
90
+ {
91
+ path: firstPath,
92
+ changeType: "deleted",
93
+ },
94
+ ];
95
+ case "R": {
96
+ const newPath = parts[2];
97
+ if (!newPath) {
98
+ return [];
99
+ }
100
+ return [
101
+ {
102
+ path: newPath,
103
+ changeType: "renamed",
104
+ },
105
+ ];
106
+ }
107
+ default:
108
+ return [];
109
+ }
110
+ }
111
+ async getUntrackedFiles(repositoryPath) {
112
+ const { stdout } = await execFileAsync("git", ["ls-files", "--others", "--exclude-standard"], {
113
+ cwd: repositoryPath,
114
+ });
115
+ if (!stdout.trim()) {
116
+ return [];
117
+ }
118
+ return stdout
119
+ .split("\n")
120
+ .map((line) => line.trim())
121
+ .filter(Boolean);
122
+ }
123
+ async createFileChange(repositoryPath, change) {
124
+ const stats = await this.getFileStats(repositoryPath, change);
125
+ const language = detectLanguage(change.path);
126
+ const fileChange = {
127
+ path: change.path,
128
+ changeType: change.changeType,
129
+ additions: stats.additions,
130
+ deletions: stats.deletions,
131
+ source: "unknown",
132
+ };
133
+ if (language !== undefined) {
134
+ fileChange.language = language;
135
+ }
136
+ return fileChange;
137
+ }
138
+ async getFileStats(repositoryPath, change) {
139
+ if (change.changeType === "added") {
140
+ const isTracked = await this.isTrackedFile(repositoryPath, change.path);
141
+ if (!isTracked) {
142
+ return this.countUntrackedFileLines(repositoryPath, change.path);
143
+ }
144
+ }
145
+ try {
146
+ const { stdout } = await execFileAsync("git", ["diff", "HEAD", "--numstat", "-M", "--", change.path], {
147
+ cwd: repositoryPath,
148
+ });
149
+ const line = stdout
150
+ .split("\n")
151
+ .map((value) => value.trim())
152
+ .find(Boolean);
153
+ if (!line) {
154
+ return {
155
+ additions: 0,
156
+ deletions: 0,
157
+ };
158
+ }
159
+ const parts = line.split("\t");
160
+ return {
161
+ additions: this.parseStat(parts[0]),
162
+ deletions: this.parseStat(parts[1]),
163
+ };
164
+ }
165
+ catch {
166
+ return {
167
+ additions: 0,
168
+ deletions: 0,
169
+ };
170
+ }
171
+ }
172
+ async isTrackedFile(repositoryPath, filePath) {
173
+ try {
174
+ await execFileAsync("git", ["ls-files", "--error-unmatch", "--", filePath], {
175
+ cwd: repositoryPath,
176
+ });
177
+ return true;
178
+ }
179
+ catch {
180
+ return false;
181
+ }
182
+ }
183
+ async countUntrackedFileLines(repositoryPath, filePath) {
184
+ try {
185
+ const absolutePath = path.join(repositoryPath, filePath);
186
+ const { stdout } = await execFileAsync("wc", ["-l", absolutePath]);
187
+ const lineCount = Number.parseInt(stdout.trim().split(/\s+/)[0] ?? "0", 10);
188
+ return {
189
+ additions: Number.isNaN(lineCount) ? 0 : lineCount,
190
+ deletions: 0,
191
+ };
192
+ }
193
+ catch {
194
+ return {
195
+ additions: 0,
196
+ deletions: 0,
197
+ };
198
+ }
199
+ }
200
+ parseStat(value) {
201
+ if (!value || value === "-") {
202
+ return 0;
203
+ }
204
+ const parsed = Number.parseInt(value, 10);
205
+ return Number.isNaN(parsed) ? 0 : parsed;
206
+ }
207
+ }
208
+ //# sourceMappingURL=git-analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-analyzer.js","sourceRoot":"","sources":["../../src/analyzer/git-analyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function detectLanguage(filePath: string): string | undefined;
@@ -0,0 +1,23 @@
1
+ import path from "node:path";
2
+ const LANGUAGE_MAP = {
3
+ ".ts": "typescript",
4
+ ".tsx": "typescript",
5
+ ".js": "javascript",
6
+ ".jsx": "javascript",
7
+ ".py": "python",
8
+ ".go": "go",
9
+ ".rs": "rust",
10
+ ".java": "java",
11
+ ".php": "php",
12
+ ".rb": "ruby",
13
+ ".cs": "csharp",
14
+ ".cpp": "cpp",
15
+ ".c": "c",
16
+ ".swift": "swift",
17
+ ".kt": "kotlin",
18
+ };
19
+ export function detectLanguage(filePath) {
20
+ const extension = path.extname(filePath).toLowerCase();
21
+ return LANGUAGE_MAP[extension];
22
+ }
23
+ //# sourceMappingURL=language.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"language.js","sourceRoot":"","sources":["../../src/analyzer/language.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,YAAY,GAA2B;IAC3C,KAAK,EAAE,YAAY;IACnB,MAAM,EAAE,YAAY;IACpB,KAAK,EAAE,YAAY;IACnB,MAAM,EAAE,YAAY;IACpB,KAAK,EAAE,QAAQ;IACf,KAAK,EAAE,IAAI;IACX,KAAK,EAAE,MAAM;IACb,OAAO,EAAE,MAAM;IACf,MAAM,EAAE,KAAK;IACb,KAAK,EAAE,MAAM;IACb,KAAK,EAAE,QAAQ;IACf,MAAM,EAAE,KAAK;IACb,IAAI,EAAE,GAAG;IACT,QAAQ,EAAE,OAAO;IACjB,KAAK,EAAE,QAAQ;CAChB,CAAC;AAEF,MAAM,UAAU,cAAc,CAAC,QAAgB;IAC7C,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IACvD,OAAO,YAAY,CAAC,SAAS,CAAC,CAAC;AACjC,CAAC"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export declare function run(repositoryPath: string): Promise<number>;
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env node
2
+ import path from "node:path";
3
+ import { CoreOrchestrator } from "../core/orchestrator.js";
4
+ import { GitAnalyzer } from "../analyzer/git-analyzer.js";
5
+ import { RiskEngineV01 } from "../risk/risk-engine.js";
6
+ import { selectVerifiers } from "../verifier/index.js";
7
+ import { hasFailed, printBanner, printChangeReport, printRiskReport, printVerificationReport, } from "./report.js";
8
+ import { getVersion } from "./version.js";
9
+ export async function run(repositoryPath) {
10
+ const request = {
11
+ repositoryPath: path.resolve(repositoryPath),
12
+ includeUncommittedChanges: true,
13
+ };
14
+ const analyzer = new GitAnalyzer();
15
+ const riskEngine = new RiskEngineV01();
16
+ const core = new CoreOrchestrator(analyzer, riskEngine, selectVerifiers);
17
+ const { changeSet, risk, verification } = await core.run(request);
18
+ printBanner(getVersion());
19
+ printChangeReport(changeSet);
20
+ printRiskReport(risk);
21
+ printVerificationReport(verification);
22
+ return hasFailed(verification) ? 1 : 0;
23
+ }
24
+ async function main() {
25
+ const repositoryPath = process.argv[2] ?? ".";
26
+ process.exitCode = await run(repositoryPath);
27
+ }
28
+ main().catch((error) => {
29
+ console.error("AI Verify failed.");
30
+ if (error instanceof Error) {
31
+ console.error(error.message);
32
+ }
33
+ else {
34
+ console.error(error);
35
+ }
36
+ process.exitCode = 1;
37
+ });
38
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AAEA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EACL,SAAS,EACT,WAAW,EACX,iBAAiB,EACjB,eAAe,EACf,uBAAuB,GACxB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,CAAC,KAAK,UAAU,GAAG,CAAC,cAAsB;IAC9C,MAAM,OAAO,GAAG;QACd,cAAc,EAAE,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC;QAC5C,yBAAyB,EAAE,IAAI;KAChC,CAAC;IAEF,MAAM,QAAQ,GAAG,IAAI,WAAW,EAAE,CAAC;IACnC,MAAM,UAAU,GAAG,IAAI,aAAa,EAAE,CAAC;IACvC,MAAM,IAAI,GAAG,IAAI,gBAAgB,CAAC,QAAQ,EAAE,UAAU,EAAE,eAAe,CAAC,CAAC;IAEzE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAElE,WAAW,CAAC,UAAU,EAAE,CAAC,CAAC;IAC1B,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAC7B,eAAe,CAAC,IAAI,CAAC,CAAC;IACtB,uBAAuB,CAAC,YAAY,CAAC,CAAC;IAEtC,OAAO,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACzC,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;IAC9C,OAAO,CAAC,QAAQ,GAAG,MAAM,GAAG,CAAC,cAAc,CAAC,CAAC;AAC/C,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IAC9B,OAAO,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;IAEnC,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;IAED,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { ChangeSet, RiskAssessment, VerificationResult } from "../core/types/index.js";
2
+ export declare function printBanner(version: string): void;
3
+ export declare function hasFailed(result: VerificationResult): boolean;
4
+ export declare function printChangeReport(changeSet: ChangeSet): void;
5
+ export declare function printRiskReport(risk: RiskAssessment): void;
6
+ export declare function printVerificationReport(result: VerificationResult): void;
@@ -0,0 +1,65 @@
1
+ export function printBanner(version) {
2
+ console.log("");
3
+ console.log(`AI Verify v${version} — AI can generate code. AI Verify helps verify it.`);
4
+ console.log("------------------------------");
5
+ }
6
+ export function hasFailed(result) {
7
+ return result.checks.some((check) => check.status === "failed" || check.status === "error");
8
+ }
9
+ export function printChangeReport(changeSet) {
10
+ console.log(`Files changed : ${changeSet.files.length}`);
11
+ console.log(`Additions : +${changeSet.totalAdditions}`);
12
+ console.log(`Deletions : -${changeSet.totalDeletions}`);
13
+ console.log("");
14
+ if (changeSet.files.length === 0) {
15
+ console.log("No changes detected.");
16
+ return;
17
+ }
18
+ console.log("Changes:");
19
+ for (const file of changeSet.files) {
20
+ const language = file.language ?? "unknown";
21
+ console.log(` ${file.changeType.padEnd(8)} ${file.path} (${language}) +${file.additions}/-${file.deletions}`);
22
+ }
23
+ }
24
+ export function printRiskReport(risk) {
25
+ console.log("");
26
+ console.log(`Risk: ${risk.level.toUpperCase()} (${risk.score})`);
27
+ if (risk.factors.length === 0) {
28
+ console.log("No risk factors.");
29
+ return;
30
+ }
31
+ console.log("Factors:");
32
+ for (const factor of risk.factors) {
33
+ console.log(` +${factor.score} ${factor.name} — ${factor.reason}`);
34
+ }
35
+ }
36
+ const CHECK_ICONS = {
37
+ passed: "✓",
38
+ failed: "✗",
39
+ skipped: "-",
40
+ error: "!",
41
+ };
42
+ export function printVerificationReport(result) {
43
+ console.log("");
44
+ console.log(`Verification (${result.durationMs}ms)`);
45
+ if (result.checks.length === 0) {
46
+ console.log("No applicable verifiers for these changes.");
47
+ }
48
+ for (const check of result.checks) {
49
+ const icon = CHECK_ICONS[check.status] ?? "?";
50
+ const detail = check.findings.length > 0 ? `, ${check.findings.length} finding(s)` : "";
51
+ const reason = check.reason !== undefined && check.findings.length === 0
52
+ ? ` (${check.reason})`
53
+ : "";
54
+ console.log(` ${icon} ${check.name} — ${check.status}${detail}${reason}`);
55
+ }
56
+ console.log(`Findings: ${result.findings.length}`);
57
+ for (const finding of result.findings.slice(0, 20)) {
58
+ const location = finding.file !== undefined
59
+ ? ` (${finding.file}${finding.line !== undefined ? `:${finding.line}` : ""})`
60
+ : "";
61
+ console.log(` [${finding.severity.toUpperCase()}] ${finding.title}${location}`);
62
+ }
63
+ console.log(`Result: ${hasFailed(result) ? "FAILED" : "PASSED"}`);
64
+ }
65
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/cli/report.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function getVersion(): string;
@@ -0,0 +1,12 @@
1
+ import { createRequire } from "node:module";
2
+ export function getVersion() {
3
+ try {
4
+ const require = createRequire(import.meta.url);
5
+ const pkg = require("../../package.json");
6
+ return typeof pkg.version === "string" ? pkg.version : "unknown";
7
+ }
8
+ catch {
9
+ return "unknown";
10
+ }
11
+ }
12
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/cli/version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,UAAU,UAAU;IACxB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;QAC/C,MAAM,GAAG,GAAG,OAAO,CAAC,oBAAoB,CAA0B,CAAC;QAEnE,OAAO,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { AnalysisRequest, ChangeSet, RiskAssessment, VerificationResult } from "./types/index.js";
2
+ import type { Analyzer } from "../analyzer/analyzer.js";
3
+ import type { RiskEngine } from "../risk/risk-engine.js";
4
+ import type { Verifier } from "../verifier/verifier.js";
5
+ export interface AnalysisOutput {
6
+ changeSet: ChangeSet;
7
+ risk: RiskAssessment;
8
+ verification: VerificationResult;
9
+ }
10
+ export declare class CoreOrchestrator {
11
+ private readonly analyzer;
12
+ private readonly riskEngine;
13
+ private readonly selectVerifiers;
14
+ constructor(analyzer: Analyzer, riskEngine: RiskEngine, selectVerifiers: (changeSet: ChangeSet) => Verifier[]);
15
+ analyze(request: AnalysisRequest): Promise<ChangeSet>;
16
+ run(request: AnalysisRequest): Promise<AnalysisOutput>;
17
+ }
@@ -0,0 +1,21 @@
1
+ import { VerificationEngine } from "../verifier/engine.js";
2
+ export class CoreOrchestrator {
3
+ analyzer;
4
+ riskEngine;
5
+ selectVerifiers;
6
+ constructor(analyzer, riskEngine, selectVerifiers) {
7
+ this.analyzer = analyzer;
8
+ this.riskEngine = riskEngine;
9
+ this.selectVerifiers = selectVerifiers;
10
+ }
11
+ async analyze(request) {
12
+ return this.analyzer.analyze(request);
13
+ }
14
+ async run(request) {
15
+ const changeSet = await this.analyze(request);
16
+ const risk = this.riskEngine.assess(changeSet);
17
+ const verification = await new VerificationEngine(this.selectVerifiers(changeSet)).run({ repositoryPath: request.repositoryPath, changeSet }, risk);
18
+ return { changeSet, risk, verification };
19
+ }
20
+ }
21
+ //# sourceMappingURL=orchestrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../src/core/orchestrator.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAS3D,MAAM,OAAO,gBAAgB;IAER,QAAQ;IACR,UAAU;IACV,eAAe;IAHlC,YACmB,QAAkB,EAClB,UAAsB,EACtB,eAAqD;wBAFrD,QAAQ;0BACR,UAAU;+BACV,eAAe;IAC/B,CAAC;IAEJ,KAAK,CAAC,OAAO,CAAC,OAAwB;QACpC,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACxC,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,OAAwB;QAChC,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC/C,MAAM,YAAY,GAAG,MAAM,IAAI,kBAAkB,CAC/C,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,CAChC,CAAC,GAAG,CAAC,EAAE,cAAc,EAAE,OAAO,CAAC,cAAc,EAAE,SAAS,EAAE,EAAE,IAAI,CAAC,CAAC;QAEnE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;IAC3C,CAAC;CACF"}
@@ -0,0 +1,6 @@
1
+ import type { ChangeSet } from "./change.js";
2
+ export interface AnalysisRequest {
3
+ repositoryPath: string;
4
+ changeSet?: ChangeSet;
5
+ includeUncommittedChanges: boolean;
6
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=analysis.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analysis.js","sourceRoot":"","sources":["../../../src/core/types/analysis.ts"],"names":[],"mappings":""}
@@ -0,0 +1,15 @@
1
+ export type ChangeType = "added" | "modified" | "deleted" | "renamed";
2
+ export type ChangeSource = "human" | "ai" | "mixed" | "unknown";
3
+ export interface FileChange {
4
+ path: string;
5
+ changeType: ChangeType;
6
+ additions: number;
7
+ deletions: number;
8
+ source: ChangeSource;
9
+ language?: string;
10
+ }
11
+ export interface ChangeSet {
12
+ files: FileChange[];
13
+ totalAdditions: number;
14
+ totalDeletions: number;
15
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=change.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"change.js","sourceRoot":"","sources":["../../../src/core/types/change.ts"],"names":[],"mappings":""}
@@ -0,0 +1,15 @@
1
+ export type Severity = "info" | "low" | "medium" | "high" | "critical";
2
+ export type FindingCategory = "security" | "quality" | "reliability" | "dependency" | "configuration" | "test" | "unknown";
3
+ export type FindingSource = "typecheck" | "lint" | "test" | "sast" | "dependency" | "secret" | "llm" | "unknown";
4
+ export interface Finding {
5
+ id: string;
6
+ title: string;
7
+ description: string;
8
+ severity: Severity;
9
+ category: FindingCategory;
10
+ source: FindingSource;
11
+ file?: string;
12
+ line?: number;
13
+ ruleId?: string;
14
+ remediation?: string;
15
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=finding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding.js","sourceRoot":"","sources":["../../../src/core/types/finding.ts"],"names":[],"mappings":""}
@@ -0,0 +1,5 @@
1
+ export type { AnalysisRequest, } from "./analysis.js";
2
+ export type { ChangeType, ChangeSource, FileChange, ChangeSet, } from "./change.js";
3
+ export type { Severity, FindingCategory, FindingSource, Finding, } from "./finding.js";
4
+ export type { RiskLevel, RiskFactor, RiskAssessment, } from "./risk.js";
5
+ export type { VerificationStatus, VerificationCheck, VerificationResult, } from "./verification.js";
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/types/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,11 @@
1
+ export type RiskLevel = "none" | "low" | "medium" | "high" | "critical";
2
+ export interface RiskFactor {
3
+ name: string;
4
+ score: number;
5
+ reason: string;
6
+ }
7
+ export interface RiskAssessment {
8
+ score: number;
9
+ level: RiskLevel;
10
+ factors: RiskFactor[];
11
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=risk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"risk.js","sourceRoot":"","sources":["../../../src/core/types/risk.ts"],"names":[],"mappings":""}
@@ -0,0 +1,17 @@
1
+ import type { Finding } from "./finding.js";
2
+ import type { RiskAssessment } from "./risk.js";
3
+ export type VerificationStatus = "passed" | "failed" | "skipped" | "error";
4
+ export interface VerificationCheck {
5
+ id: string;
6
+ name: string;
7
+ status: VerificationStatus;
8
+ durationMs: number;
9
+ findings: Finding[];
10
+ reason?: string;
11
+ }
12
+ export interface VerificationResult {
13
+ checks: VerificationCheck[];
14
+ findings: Finding[];
15
+ risk: RiskAssessment;
16
+ durationMs: number;
17
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=verification.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verification.js","sourceRoot":"","sources":["../../../src/core/types/verification.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ export { RiskEngineV01 } from "./risk-engine.js";
2
+ export type { RiskEngine } from "./risk-engine.js";
3
+ export { scoreToLevel } from "./levels.js";
4
+ export { collectRiskFactors } from "./rules.js";
@@ -0,0 +1,4 @@
1
+ export { RiskEngineV01 } from "./risk-engine.js";
2
+ export { scoreToLevel } from "./levels.js";
3
+ export { collectRiskFactors } from "./rules.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/risk/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { RiskLevel } from "../core/types/index.js";
2
+ export declare function scoreToLevel(score: number): RiskLevel;
@@ -0,0 +1,16 @@
1
+ export function scoreToLevel(score) {
2
+ if (score <= 0) {
3
+ return "none";
4
+ }
5
+ if (score < 30) {
6
+ return "low";
7
+ }
8
+ if (score < 60) {
9
+ return "medium";
10
+ }
11
+ if (score < 90) {
12
+ return "high";
13
+ }
14
+ return "critical";
15
+ }
16
+ //# sourceMappingURL=levels.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"levels.js","sourceRoot":"","sources":["../../src/risk/levels.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QACf,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,IAAI,KAAK,GAAG,EAAE,EAAE,CAAC;QACf,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,KAAK,GAAG,EAAE,EAAE,CAAC;QACf,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,IAAI,KAAK,GAAG,EAAE,EAAE,CAAC;QACf,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { ChangeSet, RiskAssessment } from "../core/types/index.js";
2
+ export interface RiskEngine {
3
+ assess(changeSet: ChangeSet): RiskAssessment;
4
+ }
5
+ export declare class RiskEngineV01 implements RiskEngine {
6
+ assess(changeSet: ChangeSet): RiskAssessment;
7
+ }
@@ -0,0 +1,15 @@
1
+ import { scoreToLevel } from "./levels.js";
2
+ import { collectRiskFactors } from "./rules.js";
3
+ export class RiskEngineV01 {
4
+ assess(changeSet) {
5
+ const factors = collectRiskFactors(changeSet);
6
+ const raw = factors.reduce((total, factor) => total + factor.score, 0);
7
+ const score = Math.min(100, Math.max(0, raw));
8
+ return {
9
+ score,
10
+ level: scoreToLevel(score),
11
+ factors,
12
+ };
13
+ }
14
+ }
15
+ //# sourceMappingURL=risk-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"risk-engine.js","sourceRoot":"","sources":["../../src/risk/risk-engine.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAMhD,MAAM,OAAO,aAAa;IACxB,MAAM,CAAC,SAAoB;QACzB,MAAM,OAAO,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;QAE9C,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QACvE,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QAE9C,OAAO;YACL,KAAK;YACL,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC;YAC1B,OAAO;SACR,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,2 @@
1
+ import type { ChangeSet, RiskFactor } from "../core/types/index.js";
2
+ export declare function collectRiskFactors(changeSet: ChangeSet): RiskFactor[];
@@ -0,0 +1,137 @@
1
+ const PATH_RULES = [
2
+ {
3
+ name: "Authentication change",
4
+ score: 30,
5
+ reason: "Touches authentication or authorization logic",
6
+ patterns: [
7
+ /auth/i,
8
+ /login|logout/i,
9
+ /session/i,
10
+ /password/i,
11
+ /oauth/i,
12
+ /\bjwt\b/i,
13
+ /\btoken\b/i,
14
+ /\bmfa\b/i,
15
+ /permission|\brole\b|\bacl\b|identity/i,
16
+ ],
17
+ },
18
+ {
19
+ name: "Payment change",
20
+ score: 30,
21
+ reason: "Touches payment or billing logic",
22
+ patterns: [
23
+ /payment|billing|checkout|stripe|invoice|transaction|subscription|payout|refund/i,
24
+ ],
25
+ },
26
+ {
27
+ name: "Secrets touched",
28
+ score: 30,
29
+ reason: "Touches secrets or credentials",
30
+ patterns: [
31
+ /secret|credential/i,
32
+ /\.pem$|\.key$/i,
33
+ /private[_-]?key/i,
34
+ /vault/i,
35
+ /(^|\/)\.env(\.|$)/i,
36
+ ],
37
+ },
38
+ {
39
+ name: "Database change",
40
+ score: 25,
41
+ reason: "Touches database schema, migration, or query logic",
42
+ patterns: [
43
+ /migrat|prisma|\.sql$/i,
44
+ /database|\/db\/|^db\//i,
45
+ /repository|seed/i,
46
+ ],
47
+ },
48
+ {
49
+ name: "Security-sensitive file",
50
+ score: 20,
51
+ reason: "Touches security-sensitive code",
52
+ patterns: [/crypto|cipher|\bhash\b|cert|\btls\b|\bssl\b|security|sanitiz|xss|csrf|inject/i],
53
+ },
54
+ {
55
+ name: "Configuration / infra change",
56
+ score: 15,
57
+ reason: "Touches configuration or infrastructure",
58
+ patterns: [
59
+ /dockerfile|docker-compose/i,
60
+ /\.github\/workflows/i,
61
+ /terraform|\.tf$/i,
62
+ /k8s|kubernetes|nginx/i,
63
+ /^infra\/|^config\//i,
64
+ ],
65
+ },
66
+ ];
67
+ const TEST_PATH = /__tests__|[/]tests?[/]|\.test\.|\.spec\.|_test\.go$|test_.*\.py$/i;
68
+ function isTestFile(filePath) {
69
+ return TEST_PATH.test(filePath);
70
+ }
71
+ function isCodeFile(language) {
72
+ return language !== undefined;
73
+ }
74
+ function collectPathFactors(changeSet) {
75
+ const factors = [];
76
+ for (const rule of PATH_RULES) {
77
+ const matched = changeSet.files
78
+ .map((file) => file.path)
79
+ .filter((filePath) => rule.patterns.some((pattern) => pattern.test(filePath)));
80
+ if (matched.length === 0) {
81
+ continue;
82
+ }
83
+ factors.push({
84
+ name: rule.name,
85
+ score: rule.score,
86
+ reason: `${rule.reason}: ${matched.slice(0, 5).join(", ")}`,
87
+ });
88
+ }
89
+ return factors;
90
+ }
91
+ function collectTestFactor(changeSet) {
92
+ const codeChanged = changeSet.files.some((file) => isCodeFile(file.language));
93
+ if (!codeChanged) {
94
+ return [];
95
+ }
96
+ const testChanged = changeSet.files.some((file) => isTestFile(file.path));
97
+ if (testChanged) {
98
+ return [];
99
+ }
100
+ return [
101
+ {
102
+ name: "No related tests",
103
+ score: 12,
104
+ reason: "Code changed without accompanying test changes",
105
+ },
106
+ ];
107
+ }
108
+ function collectSizeFactor(changeSet) {
109
+ const total = changeSet.totalAdditions + changeSet.totalDeletions;
110
+ if (total > 500) {
111
+ return [
112
+ {
113
+ name: "Large change",
114
+ score: 10,
115
+ reason: `Change spans ${total} lines`,
116
+ },
117
+ ];
118
+ }
119
+ if (total > 200) {
120
+ return [
121
+ {
122
+ name: "Medium-large change",
123
+ score: 5,
124
+ reason: `Change spans ${total} lines`,
125
+ },
126
+ ];
127
+ }
128
+ return [];
129
+ }
130
+ export function collectRiskFactors(changeSet) {
131
+ return [
132
+ ...collectPathFactors(changeSet),
133
+ ...collectTestFactor(changeSet),
134
+ ...collectSizeFactor(changeSet),
135
+ ];
136
+ }
137
+ //# sourceMappingURL=rules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules.js","sourceRoot":"","sources":["../../src/risk/rules.ts"],"names":[],"mappings":"AASA,MAAM,UAAU,GAAe;IAC7B;QACE,IAAI,EAAE,uBAAuB;QAC7B,KAAK,EAAE,EAAE;QACT,MAAM,EAAE,+CAA+C;QACvD,QAAQ,EAAE;YACR,OAAO;YACP,eAAe;YACf,UAAU;YACV,WAAW;YACX,QAAQ;YACR,UAAU;YACV,YAAY;YACZ,UAAU;YACV,uCAAuC;SACxC;KACF;IACD;QACE,IAAI,EAAE,gBAAgB;QACtB,KAAK,EAAE,EAAE;QACT,MAAM,EAAE,kCAAkC;QAC1C,QAAQ,EAAE;YACR,iFAAiF;SAClF;KACF;IACD;QACE,IAAI,EAAE,iBAAiB;QACvB,KAAK,EAAE,EAAE;QACT,MAAM,EAAE,gCAAgC;QACxC,QAAQ,EAAE;YACR,oBAAoB;YACpB,gBAAgB;YAChB,kBAAkB;YAClB,QAAQ;YACR,oBAAoB;SACrB;KACF;IACD;QACE,IAAI,EAAE,iBAAiB;QACvB,KAAK,EAAE,EAAE;QACT,MAAM,EAAE,oDAAoD;QAC5D,QAAQ,EAAE;YACR,uBAAuB;YACvB,wBAAwB;YACxB,kBAAkB;SACnB;KACF;IACD;QACE,IAAI,EAAE,yBAAyB;QAC/B,KAAK,EAAE,EAAE;QACT,MAAM,EAAE,iCAAiC;QACzC,QAAQ,EAAE,CAAC,+EAA+E,CAAC;KAC5F;IACD;QACE,IAAI,EAAE,8BAA8B;QACpC,KAAK,EAAE,EAAE;QACT,MAAM,EAAE,yCAAyC;QACjD,QAAQ,EAAE;YACR,4BAA4B;YAC5B,sBAAsB;YACtB,kBAAkB;YAClB,uBAAuB;YACvB,qBAAqB;SACtB;KACF;CACF,CAAC;AAEF,MAAM,SAAS,GAAG,mEAAmE,CAAC;AAEtF,SAAS,UAAU,CAAC,QAAgB;IAClC,OAAO,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AAClC,CAAC;AAED,SAAS,UAAU,CAAC,QAA4B;IAC9C,OAAO,QAAQ,KAAK,SAAS,CAAC;AAChC,CAAC;AAED,SAAS,kBAAkB,CAAC,SAAoB;IAC9C,MAAM,OAAO,GAAiB,EAAE,CAAC;IAEjC,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK;aAC5B,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;aACxB,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CACnB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CACxD,CAAC;QAEJ,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,SAAS;QACX,CAAC;QAED,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,KAAK,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;SAC5D,CAAC,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,iBAAiB,CAAC,SAAoB;IAC7C,MAAM,WAAW,GAAG,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAChD,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAC1B,CAAC;IAEF,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,WAAW,GAAG,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAChD,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CACtB,CAAC;IAEF,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO;QACL;YACE,IAAI,EAAE,kBAAkB;YACxB,KAAK,EAAE,EAAE;YACT,MAAM,EAAE,gDAAgD;SACzD;KACF,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CAAC,SAAoB;IAC7C,MAAM,KAAK,GAAG,SAAS,CAAC,cAAc,GAAG,SAAS,CAAC,cAAc,CAAC;IAElE,IAAI,KAAK,GAAG,GAAG,EAAE,CAAC;QAChB,OAAO;YACL;gBACE,IAAI,EAAE,cAAc;gBACpB,KAAK,EAAE,EAAE;gBACT,MAAM,EAAE,gBAAgB,KAAK,QAAQ;aACtC;SACF,CAAC;IACJ,CAAC;IAED,IAAI,KAAK,GAAG,GAAG,EAAE,CAAC;QAChB,OAAO;YACL;gBACE,IAAI,EAAE,qBAAqB;gBAC3B,KAAK,EAAE,CAAC;gBACR,MAAM,EAAE,gBAAgB,KAAK,QAAQ;aACtC;SACF,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,SAAoB;IACrD,OAAO;QACL,GAAG,kBAAkB,CAAC,SAAS,CAAC;QAChC,GAAG,iBAAiB,CAAC,SAAS,CAAC;QAC/B,GAAG,iBAAiB,CAAC,SAAS,CAAC;KAChC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { RiskAssessment, VerificationResult } from "../core/types/index.js";
2
+ import type { Verifier, VerifierContext } from "./verifier.js";
3
+ export declare class VerificationEngine {
4
+ private readonly verifiers;
5
+ constructor(verifiers: Verifier[]);
6
+ run(context: VerifierContext, risk: RiskAssessment): Promise<VerificationResult>;
7
+ }
@@ -0,0 +1,20 @@
1
+ export class VerificationEngine {
2
+ verifiers;
3
+ constructor(verifiers) {
4
+ this.verifiers = verifiers;
5
+ }
6
+ async run(context, risk) {
7
+ const start = Date.now();
8
+ const checks = [];
9
+ for (const verifier of this.verifiers) {
10
+ checks.push(await verifier.run(context));
11
+ }
12
+ return {
13
+ checks,
14
+ findings: checks.flatMap((check) => check.findings),
15
+ risk,
16
+ durationMs: Date.now() - start,
17
+ };
18
+ }
19
+ }
20
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/verifier/engine.ts"],"names":[],"mappings":"AAIA,MAAM,OAAO,kBAAkB;IACA,SAAS;IAAtC,YAA6B,SAAqB;yBAArB,SAAS;IAAe,CAAC;IAEtD,KAAK,CAAC,GAAG,CACP,OAAwB,EACxB,IAAoB;QAEpB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEzB,MAAM,MAAM,GAAG,EAAE,CAAC;QAClB,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACtC,MAAM,CAAC,IAAI,CAAC,MAAM,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;QAC3C,CAAC;QAED,OAAO;YACL,MAAM;YACN,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC;YACnD,IAAI;YACJ,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;SAC/B,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,4 @@
1
+ export { VerificationEngine } from "./engine.js";
2
+ export { TypeCheckVerifier } from "./typecheck.js";
3
+ export { selectVerifiers } from "./select.js";
4
+ export type { Verifier, VerifierContext } from "./verifier.js";
@@ -0,0 +1,4 @@
1
+ export { VerificationEngine } from "./engine.js";
2
+ export { TypeCheckVerifier } from "./typecheck.js";
3
+ export { selectVerifiers } from "./select.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/verifier/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ChangeSet } from "../core/types/index.js";
2
+ import type { Verifier } from "./verifier.js";
3
+ export declare function selectVerifiers(changeSet: ChangeSet): Verifier[];
@@ -0,0 +1,10 @@
1
+ import { TypeCheckVerifier, isTypeScriptFile } from "./typecheck.js";
2
+ export function selectVerifiers(changeSet) {
3
+ const verifiers = [];
4
+ const touchesTypeScript = changeSet.files.some((file) => isTypeScriptFile(file.path, file.language));
5
+ if (touchesTypeScript) {
6
+ verifiers.push(new TypeCheckVerifier());
7
+ }
8
+ return verifiers;
9
+ }
10
+ //# sourceMappingURL=select.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select.js","sourceRoot":"","sources":["../../src/verifier/select.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGrE,MAAM,UAAU,eAAe,CAAC,SAAoB;IAClD,MAAM,SAAS,GAAe,EAAE,CAAC;IAEjC,MAAM,iBAAiB,GAAG,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CACtD,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAC3C,CAAC;IAEF,IAAI,iBAAiB,EAAE,CAAC;QACtB,SAAS,CAAC,IAAI,CAAC,IAAI,iBAAiB,EAAE,CAAC,CAAC;IAC1C,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { VerificationCheck } from "../core/types/index.js";
2
+ import type { Verifier, VerifierContext } from "./verifier.js";
3
+ export declare function isTypeScriptFile(filePath: string, language: string | undefined): boolean;
4
+ export declare class TypeCheckVerifier implements Verifier {
5
+ readonly id = "typecheck";
6
+ readonly name = "Type Check";
7
+ run(context: VerifierContext): Promise<VerificationCheck>;
8
+ }
@@ -0,0 +1,114 @@
1
+ import { execFile } from "node:child_process";
2
+ import { stat } from "node:fs/promises";
3
+ import { promisify } from "node:util";
4
+ const execFileAsync = promisify(execFile);
5
+ const TSC_ERROR_LINE = /^(.+?)\((\d+),(\d+)\):\s+error\s+(TS\d+):\s+(.*)$/;
6
+ export function isTypeScriptFile(filePath, language) {
7
+ if (language === "typescript") {
8
+ return true;
9
+ }
10
+ return /\.(ts|tsx|mts|cts)$/i.test(filePath);
11
+ }
12
+ function parseFinding(line, index) {
13
+ const match = TSC_ERROR_LINE.exec(line.trim());
14
+ if (!match) {
15
+ return undefined;
16
+ }
17
+ const [, filePath, lineStr, , code, message] = match;
18
+ if (!filePath || !lineStr || !code || !message) {
19
+ return undefined;
20
+ }
21
+ const parsedLine = Number.parseInt(lineStr, 10);
22
+ const finding = {
23
+ id: `typecheck-${index + 1}`,
24
+ title: `${code}: ${message}`,
25
+ description: `TypeScript error ${code} in ${filePath}`,
26
+ severity: "high",
27
+ category: "reliability",
28
+ source: "typecheck",
29
+ file: filePath,
30
+ ruleId: code,
31
+ };
32
+ if (!Number.isNaN(parsedLine)) {
33
+ finding.line = parsedLine;
34
+ }
35
+ return finding;
36
+ }
37
+ async function isAccessibleDirectory(path) {
38
+ try {
39
+ return (await stat(path)).isDirectory();
40
+ }
41
+ catch {
42
+ return false;
43
+ }
44
+ }
45
+ async function isTscAvailable(repositoryPath) {
46
+ try {
47
+ await execFileAsync("npx", ["--no-install", "tsc", "--version"], {
48
+ cwd: repositoryPath,
49
+ timeout: 60_000,
50
+ });
51
+ return true;
52
+ }
53
+ catch {
54
+ return false;
55
+ }
56
+ }
57
+ export class TypeCheckVerifier {
58
+ id = "typecheck";
59
+ name = "Type Check";
60
+ async run(context) {
61
+ const start = Date.now();
62
+ const finish = (status, findings = [], reason) => {
63
+ if (reason === undefined) {
64
+ return {
65
+ id: this.id,
66
+ name: this.name,
67
+ status,
68
+ durationMs: Date.now() - start,
69
+ findings,
70
+ };
71
+ }
72
+ return {
73
+ id: this.id,
74
+ name: this.name,
75
+ status,
76
+ durationMs: Date.now() - start,
77
+ findings,
78
+ reason,
79
+ };
80
+ };
81
+ const touchesTypeScript = context.changeSet.files.some((file) => isTypeScriptFile(file.path, file.language));
82
+ if (!touchesTypeScript) {
83
+ return finish("skipped", [], "No TypeScript files changed.");
84
+ }
85
+ if (!(await isAccessibleDirectory(context.repositoryPath))) {
86
+ return finish("error", [], `Cannot access repository path: ${context.repositoryPath}`);
87
+ }
88
+ if (!(await isTscAvailable(context.repositoryPath))) {
89
+ return finish("skipped", [], "TypeScript compiler (tsc) is not available in this repository.");
90
+ }
91
+ try {
92
+ await execFileAsync("npx", ["--no-install", "tsc", "--noEmit"], {
93
+ cwd: context.repositoryPath,
94
+ timeout: 120_000,
95
+ });
96
+ return finish("passed");
97
+ }
98
+ catch (error) {
99
+ if (error !== null &&
100
+ typeof error === "object" &&
101
+ "stdout" in error &&
102
+ typeof error.stdout === "string" &&
103
+ error.stdout.trim() !== "") {
104
+ const findings = error.stdout
105
+ .split("\n")
106
+ .map((line, index) => parseFinding(line, index))
107
+ .filter((finding) => finding !== undefined);
108
+ return finish("failed", findings);
109
+ }
110
+ return finish("error", [], "Type check execution failed before producing output.");
111
+ }
112
+ }
113
+ }
114
+ //# sourceMappingURL=typecheck.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typecheck.js","sourceRoot":"","sources":["../../src/verifier/typecheck.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { ChangeSet, VerificationCheck } from "../core/types/index.js";
2
+ export interface VerifierContext {
3
+ repositoryPath: string;
4
+ changeSet: ChangeSet;
5
+ }
6
+ export interface Verifier {
7
+ readonly id: string;
8
+ readonly name: string;
9
+ run(context: VerifierContext): Promise<VerificationCheck>;
10
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=verifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifier.js","sourceRoot":"","sources":["../../src/verifier/verifier.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@fisaabil_/ai-verify",
3
+ "version": "0.1.0",
4
+ "description": "Open-source, risk-adaptive verification infrastructure for AI-generated software",
5
+ "main": "./dist/cli/index.js",
6
+ "files": [
7
+ "dist/",
8
+ "README.md"
9
+ ],
10
+ "scripts": {
11
+ "test": "vitest run",
12
+ "check": "tsc --noEmit",
13
+ "build": "tsc",
14
+ "dev": "tsx src/cli/index.ts",
15
+ "start": "node dist/cli/index.js",
16
+ "prepublishOnly": "npm run check && npm run test && npm run build"
17
+ },
18
+ "keywords": [
19
+ "ai",
20
+ "verification",
21
+ "code-review",
22
+ "static-analysis",
23
+ "devtools",
24
+ "cli"
25
+ ],
26
+ "author": "Muhammad Fisabilillah",
27
+ "license": "ISC",
28
+ "type": "module",
29
+ "engines": {
30
+ "node": ">=18"
31
+ },
32
+ "bin": {
33
+ "ai-verify": "dist/cli/index.js"
34
+ },
35
+ "devDependencies": {
36
+ "@types/node": "^26.4.1",
37
+ "eslint": "^10.10.0",
38
+ "prettier": "^3.9.6",
39
+ "tsx": "^4.23.13",
40
+ "typescript": "^7.0.2",
41
+ "vitest": "^5.0.0"
42
+ }
43
+ }