jstar-reviewer 2.4.3 → 3.0.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/README.md CHANGED
@@ -1,150 +1,49 @@
1
- # J-Star Code Reviewer
2
-
3
- **Local-first, context-aware AI code reviewer** powered by LlamaIndex + Groq.
4
-
5
- Works with **any language** — TypeScript, Python, Rust, Go, you name it.
6
-
7
- ## Features
8
-
9
- - **Local Vector Index** Embeddings stored locally, no external DB
10
- - **Gemini Embeddings** Free tier friendly, no OpenAI key needed
11
- - **Chunked Reviews** — Handles large diffs without rate limits
12
- - **Detective Engine** — Deterministic checks for common issues
13
- - **Dashboard Output** — Professional review reports with fix prompts
14
- - **Global CLI** — Install once, use in any project
15
-
16
- ---
17
-
18
- ## 🚀 Quick Install
19
-
20
- ### Option 1: Global CLI (Recommended)
21
-
22
- ```bash
23
- # Install globally
24
- npm install -g jstar-reviewer
25
-
26
- # In any project directory:
27
- jstar setup # Create config files
28
- jstar init # Index the codebase
29
- jstar review # Review staged changes
30
- ```
31
-
32
- ### Option 2: One-Curl (Adds to current project)
33
-
34
- ```bash
35
- curl -fsSL https://raw.githubusercontent.com/JStaRFilms/jstar-code-review/v2.0.0/setup.js | node
36
- ```
37
-
38
- ### After Install:
39
-
40
- 1. **Check Config**: The tool now **auto-creates** `.env.example` and `.jstar/` when you run it.
41
- 2. **Add Keys**: Copy `.env.example` → `.env.local` and add your `GEMINI_API_KEY` and `GROQ_API_KEY`.
42
- 3. **Index**: Run `jstar init` (or `pnpm run index:init`) to build the brain.
43
- 4. **Review**: Stage changes (`git add`) and run `jstar review` (or `pnpm run review`).
44
-
45
- For a detailed walkthrough, see **[ONBOARDING.md](./ONBOARDING.md)**.
46
-
47
-
48
- ---
49
-
50
- ```
51
- git diff --staged
52
-
53
-
54
- ┌──────────────────┐
55
- │ Detective │ ← Static analysis (secrets, console.log, "use client")
56
- │ Engine │
57
- └────────┬─────────┘
58
-
59
-
60
- ┌──────────────────┐
61
- │ Local Brain │ ← Gemini embeddings via LlamaIndex
62
- │ (Retrieval) │
63
- └────────┬─────────┘
64
-
65
-
66
- ┌──────────────────┐
67
- │ Chunked Review │ ← Splits diff by file, delays between calls
68
- │ Queue │
69
- └────────┬─────────┘
70
-
71
-
72
- ┌──────────────────┐
73
- │ Groq LLM │ ← moonshotai/kimi-k2-instruct-0905
74
- │ (The Judge) │
75
- └────────┬─────────┘
76
-
77
-
78
- 📝 Review Report
79
- ```
80
-
81
- ## 🚀 Quick Start
82
-
83
- ### 1. Install Dependencies
84
-
85
- ```bash
86
- pnpm install
87
- ```
88
-
89
- ### 2. Set Environment Variables
90
-
91
- Create `.env.local`:
92
-
93
- ```env
94
- GEMINI_API_KEY=your_gemini_key
95
- GROQ_API_KEY=your_groq_key
96
- ```
97
-
98
- ### 3. Index Your Codebase
99
-
100
- ```bash
101
- pnpm run index:init
102
- ```
103
-
104
- ### 4. Review Staged Changes
105
-
106
- ```bash
107
- git add <files>
108
- pnpm run review
109
- ```
110
-
111
- ## 📁 Project Structure
112
-
113
- ```
114
- scripts/
115
- ├── indexer.ts # Scans codebase, builds vector index
116
- ├── reviewer.ts # Orchestrates review pipeline
117
- ├── detective.ts # Static analysis engine
118
- ├── gemini-embedding.ts # Google Gemini adapter
119
- └── mock-llm.ts # LlamaIndex compatibility stub
120
-
121
- .jstar/
122
- └── storage/ # Persisted embeddings (gitignored)
123
-
124
- docs/features/
125
- ├── architecture-v2.md # Full architecture docs
126
- ├── detective.md # Static analysis rules
127
- ├── analyst.md # LLM reviewer (The Judge)
128
- └── ...
129
- ```
130
-
131
- ## ⚙️ Configuration
132
-
133
- Edit `scripts/reviewer.ts`:
134
-
135
- ```typescript
136
- const MODEL_NAME = "moonshotai/kimi-k2-instruct-0905";
137
- const MAX_TOKENS_PER_REQUEST = 8000;
138
- const DELAY_BETWEEN_CHUNKS_MS = 2000;
139
- ```
140
-
141
- ## 📚 Documentation
142
-
143
- - [Architecture v2](docs/features/architecture-v2.md)
144
- - [Detective Engine](docs/features/detective.md)
145
- - [Token Budget](docs/features/token-budget.md)
146
- - [Chunked Reviews](docs/features/map-reduce.md)
147
-
148
- ---
149
-
150
- Built with ⚡ by J Star Studios
1
+ # J-Star Code Reviewer
2
+
3
+ Local-first, context-aware code review with a deterministic security audit layer.
4
+
5
+ ## What it does
6
+
7
+ - Builds a local vector index for repo-aware reviews
8
+ - Runs hybrid reviews with deterministic checks plus LLM analysis
9
+ - Produces machine-readable review output for automation
10
+ - Runs a standalone deterministic security audit with markdown and JSON reports
11
+
12
+ ## Quick start
13
+
14
+ ```bash
15
+ pnpm install
16
+ pnpm run index:init
17
+ git add .
18
+ pnpm run review
19
+ pnpm run audit
20
+ ```
21
+
22
+ Review output:
23
+ - `.jstar/last-review.md`
24
+ - `.jstar/session.json`
25
+
26
+ Audit output:
27
+ - `.jstar/audit_report.md`
28
+ - `.jstar/audit_report.json`
29
+
30
+ ## CLI
31
+
32
+ ```bash
33
+ jstar setup
34
+ jstar init
35
+ jstar review
36
+ jstar review --pr
37
+ jstar audit
38
+ jstar audit --path src
39
+ jstar audit --json
40
+ jstar chat --headless
41
+ ```
42
+
43
+ ## Notes
44
+
45
+ - `review` requires `GEMINI_API_KEY` and `GROQ_API_KEY`
46
+ - `audit` and `detect` do not require model keys
47
+ - deterministic audit ignores live in `.jstar/audit-ignore.json`
48
+
49
+ See [ONBOARDING.md](./ONBOARDING.md) and [docs/features/cli-commands.md](./docs/features/cli-commands.md) for details.
package/bin/jstar.js CHANGED
@@ -29,7 +29,7 @@ function log(msg) {
29
29
 
30
30
  function printHelp() {
31
31
  log(`
32
- ${COLORS.bold}🌟 J-Star Reviewer v2.4.3${COLORS.reset}
32
+ ${COLORS.bold}🌟 J-Star Reviewer v3.0.0${COLORS.reset}
33
33
 
34
34
  ${COLORS.dim}AI-powered code review with local embeddings${COLORS.reset}
35
35
 
@@ -39,6 +39,7 @@ ${COLORS.bold}USAGE:${COLORS.reset}
39
39
  ${COLORS.bold}COMMANDS:${COLORS.reset}
40
40
  ${COLORS.green}init${COLORS.reset} Index the current codebase (build the brain)
41
41
  ${COLORS.green}review${COLORS.reset} Review staged git changes
42
+ ${COLORS.green}audit${COLORS.reset} Run deterministic security audit checks
42
43
  ${COLORS.green}chat${COLORS.reset} Resume an interactive session from the last review
43
44
  ${COLORS.green}detect${COLORS.reset} Run static analysis (Detective Engine)
44
45
  ${COLORS.green}setup${COLORS.reset} Create .env.example and .jstar/ in current directory
@@ -47,6 +48,7 @@ ${COLORS.bold}OPTIONS:${COLORS.reset}
47
48
  ${COLORS.yellow}--json${COLORS.reset} Output machine-readable JSON (for CI/CD)
48
49
  ${COLORS.yellow}--headless${COLORS.reset} Enable stdin/stdout protocol (for AI agents)
49
50
  ${COLORS.yellow}--all${COLORS.reset} Scan all files (including build artifacts like .next) in 'detect' mode
51
+ ${COLORS.yellow}--full${COLORS.reset} For 'audit', scan the full workspace (default)
50
52
 
51
53
  ${COLORS.bold}REVIEW OPTIONS:${COLORS.reset}
52
54
  ${COLORS.yellow}--pr${COLORS.reset} Review a Pull Request (compare against main/base)
@@ -62,6 +64,9 @@ ${COLORS.bold}EXAMPLES:${COLORS.reset}
62
64
  ${COLORS.dim}# Review staged changes (default)${COLORS.reset}
63
65
  jstar review
64
66
 
67
+ ${COLORS.dim}# Run a full deterministic security audit${COLORS.reset}
68
+ jstar audit
69
+
65
70
  ${COLORS.dim}# Review a Pull Request${COLORS.reset}
66
71
  jstar review --pr
67
72
  jstar review --pr --base develop
@@ -157,11 +162,12 @@ function runScript(scriptName) {
157
162
  });
158
163
  }
159
164
 
160
- const REQUIRED_ENV_VARS = {
161
- 'GEMINI_API_KEY': '# Required: Gemini API key (or GOOGLE_API_KEY)\nGEMINI_API_KEY=your_gemini_api_key_here',
162
- 'GROQ_API_KEY': '# Required: Groq API key for LLM reviews\nGROQ_API_KEY=your_groq_api_key_here',
163
- 'REVIEW_MODEL_NAME': '# Optional: Override the default model\n# REVIEW_MODEL_NAME=moonshotai/kimi-k2-instruct-0905'
164
- };
165
+ const REQUIRED_ENV_VARS = {
166
+ 'GEMINI_API_KEY': '# Required: Gemini API key (or GOOGLE_API_KEY)\nGEMINI_API_KEY=your_gemini_api_key_here',
167
+ 'GROQ_API_KEY': '# Required: Groq API key for LLM reviews\nGROQ_API_KEY=your_groq_api_key_here',
168
+ 'GEMINI_EMBEDDING_MODEL': '# Optional: Override the embedding model\n# GEMINI_EMBEDDING_MODEL=gemini-embedding-001',
169
+ 'REVIEW_MODEL_NAME': '# Optional: Override the default model\n# REVIEW_MODEL_NAME=moonshotai/kimi-k2-instruct-0905'
170
+ };
165
171
 
166
172
  function createSetupFiles() {
167
173
  const cwd = process.cwd();
@@ -237,6 +243,9 @@ switch (command) {
237
243
  case 'review':
238
244
  runScript('reviewer.ts');
239
245
  break;
246
+ case 'audit':
247
+ runScript('audit.ts');
248
+ break;
240
249
  case 'chat':
241
250
  runScript('chat.ts');
242
251
  break;
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderAuditReport = renderAuditReport;
4
+ const SEVERITY_EMOJI = {
5
+ CRITICAL: "🛑",
6
+ HIGH: "⚠️",
7
+ WARNING: "📝",
8
+ INFO: "ℹ️",
9
+ };
10
+ function renderFindingRow(finding) {
11
+ const location = finding.line ? `${finding.file}:${finding.line}` : finding.file;
12
+ return `| ${SEVERITY_EMOJI[finding.severity]} ${finding.severity} | ${finding.category} | \`${location}\` | **${finding.ruleId}** ${finding.title}<br>${finding.message} | ${finding.recommendation} |`;
13
+ }
14
+ function renderAuditReport(report) {
15
+ let markdown = `# J-Star Security Audit Report
16
+
17
+ **Date:** \`${report.date}\`
18
+ **Scope:** \`${report.mode}\`
19
+ **Target:** \`${report.target}\`
20
+ **Ruleset:** \`${report.rulesVersion}\`
21
+
22
+ ---
23
+
24
+ ## Summary
25
+
26
+ | Metric | Value |
27
+ | --- | --- |
28
+ | Files scanned | ${report.summary.filesScanned} |
29
+ | Active findings | ${report.summary.findings} |
30
+ | Critical | ${report.summary.critical} |
31
+ | High | ${report.summary.high} |
32
+ | Warning | ${report.summary.warning} |
33
+ | Info | ${report.summary.info} |
34
+ | Ignored | ${report.summary.ignored} |
35
+
36
+ > ${report.recommendedAction}
37
+
38
+ ---
39
+
40
+ ## Findings
41
+
42
+ `;
43
+ if (report.findings.length === 0) {
44
+ markdown += "No deterministic security findings detected.\n";
45
+ }
46
+ else {
47
+ markdown += `| Severity | Category | Location | Issue | Recommendation |
48
+ | --- | --- | --- | --- | --- |
49
+ `;
50
+ report.findings.forEach((finding) => {
51
+ markdown += renderFindingRow(finding) + "\n";
52
+ });
53
+ }
54
+ if (report.ignoredFindings.length > 0) {
55
+ markdown += `
56
+
57
+ ---
58
+
59
+ ## Ignored Findings
60
+
61
+ | Severity | Category | Location | Issue | Ignore Reason |
62
+ | --- | --- | --- | --- | --- |
63
+ `;
64
+ report.ignoredFindings.forEach((finding) => {
65
+ const location = finding.line ? `${finding.file}:${finding.line}` : finding.file;
66
+ markdown += `| ${SEVERITY_EMOJI[finding.severity]} ${finding.severity} | ${finding.category} | \`${location}\` | **${finding.ruleId}** ${finding.title} | ${finding.ignoreReason ?? "Ignored"} |\n`;
67
+ });
68
+ }
69
+ return markdown + "\n";
70
+ }
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ const fs = __importStar(require("fs"));
40
+ const path = __importStar(require("path"));
41
+ const chalk_1 = __importDefault(require("chalk"));
42
+ const simple_git_1 = __importDefault(require("simple-git"));
43
+ require("./config");
44
+ const audit_report_1 = require("./audit-report");
45
+ const deterministic_audit_1 = require("./core/deterministic-audit");
46
+ const review_target_1 = require("./core/review-target");
47
+ const logger_1 = require("./utils/logger");
48
+ const MARKDOWN_OUTPUT = path.join(process.cwd(), ".jstar", "audit_report.md");
49
+ const JSON_OUTPUT = path.join(process.cwd(), ".jstar", "audit_report.json");
50
+ function hasDiffFlags(args) {
51
+ return ["--staged", "--last", "--commit", "--range", "--pr"].some((flag) => args.includes(flag));
52
+ }
53
+ function resolveCustomPath(args) {
54
+ const pathArgIndex = args.indexOf("--path");
55
+ if (pathArgIndex === -1 || !args[pathArgIndex + 1]) {
56
+ return null;
57
+ }
58
+ const resolved = path.resolve(process.cwd(), args[pathArgIndex + 1]);
59
+ if (!fs.existsSync(resolved)) {
60
+ throw new Error(`Path not found: ${resolved}`);
61
+ }
62
+ const stat = fs.statSync(resolved);
63
+ if (stat.isDirectory()) {
64
+ return {
65
+ target: path.relative(process.cwd(), resolved).replace(/\\/g, "/") || ".",
66
+ rootDir: resolved,
67
+ };
68
+ }
69
+ return {
70
+ target: path.relative(process.cwd(), resolved).replace(/\\/g, "/"),
71
+ filePaths: [resolved],
72
+ };
73
+ }
74
+ async function main() {
75
+ logger_1.Logger.init();
76
+ const args = process.argv.slice(2);
77
+ const git = (0, simple_git_1.default)();
78
+ const diffMode = hasDiffFlags(args) || args.includes("--staged");
79
+ const customPath = resolveCustomPath(args);
80
+ logger_1.Logger.info(chalk_1.default.blue("🔐 J-Star Security Audit: Running deterministic checks...\n"));
81
+ const report = diffMode
82
+ ? await runDiffAudit(git, args)
83
+ : await runFullAudit(customPath);
84
+ fs.mkdirSync(path.dirname(MARKDOWN_OUTPUT), { recursive: true });
85
+ fs.writeFileSync(MARKDOWN_OUTPUT, (0, audit_report_1.renderAuditReport)(report));
86
+ fs.writeFileSync(JSON_OUTPUT, JSON.stringify(report, null, 2));
87
+ if (logger_1.Logger.isHeadless()) {
88
+ logger_1.Logger.json(report);
89
+ return;
90
+ }
91
+ logger_1.Logger.info(chalk_1.default.bold.green("🔐 SECURITY AUDIT COMPLETE"));
92
+ logger_1.Logger.info(` Scope: ${report.mode}`);
93
+ logger_1.Logger.info(` Target: ${report.target}`);
94
+ logger_1.Logger.info(` Files scanned: ${report.summary.filesScanned}`);
95
+ logger_1.Logger.info(` Critical: ${report.summary.critical}`);
96
+ logger_1.Logger.info(` High: ${report.summary.high}`);
97
+ logger_1.Logger.info(` Warning: ${report.summary.warning}`);
98
+ logger_1.Logger.info(` Info: ${report.summary.info}`);
99
+ logger_1.Logger.info(chalk_1.default.dim(` Markdown: ${MARKDOWN_OUTPUT}`));
100
+ logger_1.Logger.info(chalk_1.default.dim(` JSON: ${JSON_OUTPUT}`));
101
+ logger_1.Logger.info(`\n💡 ${report.recommendedAction}`);
102
+ }
103
+ async function runDiffAudit(git, args) {
104
+ const reviewTarget = await (0, review_target_1.resolveReviewTarget)(git, args);
105
+ if (!reviewTarget.diff) {
106
+ return (0, deterministic_audit_1.runDeterministicAudit)({
107
+ mode: "DIFF_SCAN",
108
+ target: reviewTarget.label,
109
+ filePaths: [],
110
+ includeRepositoryChecks: false,
111
+ });
112
+ }
113
+ const filePaths = (0, review_target_1.extractDiffFileNames)(reviewTarget.diff)
114
+ .map((filePath) => path.resolve(process.cwd(), filePath))
115
+ .filter((filePath) => fs.existsSync(filePath));
116
+ return (0, deterministic_audit_1.runDeterministicAudit)({
117
+ mode: "DIFF_SCAN",
118
+ target: reviewTarget.label,
119
+ filePaths,
120
+ includeRepositoryChecks: false,
121
+ });
122
+ }
123
+ async function runFullAudit(customPath) {
124
+ return (0, deterministic_audit_1.runDeterministicAudit)({
125
+ mode: "FULL_SCAN",
126
+ target: customPath?.target ?? ".",
127
+ rootDir: customPath?.rootDir ?? process.cwd(),
128
+ filePaths: customPath?.filePaths,
129
+ includeRepositoryChecks: true,
130
+ });
131
+ }
132
+ main().catch((error) => {
133
+ logger_1.Logger.error(`❌ Security audit failed: ${error.message}`);
134
+ process.exit(1);
135
+ });
@@ -44,6 +44,7 @@ const path = __importStar(require("path"));
44
44
  const REQUIRED_ENV_VARS = {
45
45
  'GEMINI_API_KEY': '# Required: Gemini API key (or GOOGLE_API_KEY)\nGEMINI_API_KEY=your_gemini_api_key_here',
46
46
  'GROQ_API_KEY': '# Required: Groq API key for LLM reviews\nGROQ_API_KEY=your_groq_api_key_here',
47
+ 'GEMINI_EMBEDDING_MODEL': '# Optional: Override the embedding model\n# GEMINI_EMBEDDING_MODEL=gemini-embedding-001',
47
48
  'REVIEW_MODEL_NAME': '# Optional: Override the default model\n# REVIEW_MODEL_NAME=moonshotai/kimi-k2-instruct-0905'
48
49
  };
49
50
  function ensureSetup() {