repopilot 0.7.0 → 0.9.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
@@ -2,33 +2,40 @@
2
2
 
3
3
  [![Crates.io](https://img.shields.io/crates/v/repopilot.svg)](https://crates.io/crates/repopilot)
4
4
  [![npm](https://img.shields.io/npm/v/repopilot.svg)](https://www.npmjs.com/package/repopilot)
5
- [![Docs.rs](https://docs.rs/repopilot/badge.svg)](https://docs.rs/repopilot)
6
5
  [![CI](https://github.com/MykytaStel/repopilot/actions/workflows/ci.yaml/badge.svg)](https://github.com/MykytaStel/repopilot/actions)
7
6
  [![GitHub Release](https://img.shields.io/github/v/release/MykytaStel/repopilot)](https://github.com/MykytaStel/repopilot/releases)
8
7
  [![License](https://img.shields.io/crates/l/repopilot.svg)](LICENSE)
8
+ [![GitHub Stars](https://img.shields.io/github/stars/MykytaStel/repopilot?style=social)](https://github.com/MykytaStel/repopilot)
9
9
 
10
- Local-first CLI for repository audit, architecture risk detection, baseline tracking, and CI-friendly code review.
10
+ Audit your repository locally, turn the results into AI-ready remediation context,
11
+ and ship safer changes without sending source code to a hosted scanner.
11
12
 
12
- RepoPilot runs on your machine and does not upload your repository. It helps developers understand what changed, what became riskier, and where to review first.
13
+ RepoPilot is a local-first CLI for architecture, security, code quality, testing,
14
+ and framework health checks. It gives developers useful terminal reports, CI gates,
15
+ SARIF for GitHub Code Scanning, and Markdown briefs that can be pasted into Claude
16
+ Code, ChatGPT, Cursor, or another coding assistant.
13
17
 
14
18
  ## Why RepoPilot?
15
19
 
16
- Modern developers ship more code than they can carefully review, especially with AI-assisted workflows.
20
+ Most linters and audit tools stop at the terminal. RepoPilot bridges the gap to your AI assistant:
17
21
 
18
- RepoPilot helps you understand:
22
+ | | SonarQube / CodeClimate | ESLint / language linters | **RepoPilot** |
23
+ |---|---|---|---|
24
+ | Runs offline | ❌ | ✅ | ✅ |
25
+ | No code upload | ❌ | ✅ | ✅ |
26
+ | Cross-language architecture analysis | ✅ | ❌ | ✅ |
27
+ | LLM-ready output | ❌ | ❌ | ✅ |
28
+ | Fits in a model context window | ❌ | ❌ | ✅ |
29
+ | CI gate on new findings only | ✅ | partial | ✅ |
19
30
 
20
- - what changed;
21
- - what became riskier;
22
- - which findings are new;
23
- - which findings already existed;
24
- - where to review first.
25
-
26
- RepoPilot runs locally and does not upload your repository.
31
+ ```bash
32
+ repopilot ai context . | pbcopy # macOS: paste into your coding assistant
33
+ ```
27
34
 
28
35
  ## Features
29
36
 
30
37
  - Repository scanning for projects, folders, and individual files
31
- - Gitignore-aware walking with built-in ignores for common build and service directories
38
+ - Gitignore-aware walking with built-in ignores for common build, cache, vendor, and native platform directories
32
39
  - Architecture findings: oversized files, deep nesting, too many modules per directory
33
40
  - Coupling analysis: excessive fan-out, high-instability hubs, circular dependencies
34
41
  - Code quality findings: cyclomatic complexity density, long functions, TODO/FIXME/HACK markers
@@ -36,20 +43,24 @@ RepoPilot runs locally and does not upload your repository.
36
43
  - Testing findings: missing test folder, source files without test counterparts
37
44
  - Framework findings for JavaScript, React, React Native, and Expo projects
38
45
  - React Native architecture profile: project kind, New Architecture, Hermes, Codegen, platform mismatch, and package manager signals
39
- - Workspace scanning (`--workspace`) for npm, yarn, pnpm, and Cargo workspaces with per-package risk summary
46
+ - Workspace scanning (`--workspace`) for npm, yarn, pnpm, and Cargo workspaces with per-package risk summary — parallel per-package scans
40
47
  - Evidence-backed findings with stable rule IDs, severity, file paths, line numbers, and snippets
41
48
  - 36 built-in rules with titles, descriptions, recommendations, and docs links
42
49
  - `repopilot.toml` configuration generated by `repopilot init`
50
+ - Configuration presets (`--preset strict|balanced|lenient`) for quick threshold tuning
43
51
  - Baseline workflow for accepting existing findings in legacy repositories
44
52
  - CI-friendly failure thresholds with `--fail-on`
45
53
  - Git diff-aware review mode for prioritizing findings introduced by changed lines
46
54
  - Console, JSON, Markdown, HTML, and SARIF (2.1.0) scan output — SARIF includes per-result category and workspace package properties
47
- - First-party GitHub Action wrapper with optional SARIF upload
55
+ - First-party GitHub Action wrapper for `scan`, `review`, `compare`, and `ai` workflows, with optional SARIF upload for scans
48
56
  - Compare mode for diffing two JSON scan reports
57
+ - **`repopilot ai context`** — formats scan output as LLM-ready markdown, paste into Claude Code or ChatGPT to start remediating
58
+ - **`repopilot ai plan`** — turns findings into a prioritized remediation plan
59
+ - **`repopilot ai prompt`** — exports an AI-ready remediation prompt with RepoPilot context
49
60
 
50
61
  See [docs/rulesets.md](docs/rulesets.md) for the full list of rules and severity levels.
51
62
 
52
- ## Installation
63
+ ## Install
53
64
 
54
65
  ```bash
55
66
  cargo install repopilot
@@ -61,11 +72,27 @@ Install with npm:
61
72
  npm install -g repopilot
62
73
  ```
63
74
 
75
+ Install with Homebrew:
76
+
77
+ ```bash
78
+ brew tap mykytastel/repopilot
79
+ brew install repopilot
80
+ ```
81
+
82
+ Install with curl (Linux/macOS):
83
+
84
+ ```bash
85
+ curl -fsSL https://raw.githubusercontent.com/MykytaStel/repopilot/main/install.sh | bash
86
+ ```
87
+
88
+ The curl installer verifies the GitHub Release SHA256 checksum and aborts if the checksum cannot be downloaded or verified.
89
+
64
90
  Upgrade:
65
91
 
66
92
  ```bash
67
93
  cargo install repopilot --force
68
94
  npm update -g repopilot
95
+ brew update && brew upgrade repopilot
69
96
  ```
70
97
 
71
98
  Build from source:
@@ -81,13 +108,14 @@ cargo build --release
81
108
  ```bash
82
109
  repopilot init
83
110
  repopilot scan .
111
+ repopilot ai context .
112
+ repopilot review . --base origin/main --fail-on new-high
84
113
  ```
85
114
 
86
- React Native quick scan:
115
+ Save a shareable report:
87
116
 
88
117
  ```bash
89
118
  repopilot scan . --format markdown --output repopilot-report.md
90
- repopilot review . --base origin/main --baseline .repopilot/baseline.json --fail-on new-high
91
119
  ```
92
120
 
93
121
  Reduce scan noise while iterating:
@@ -95,27 +123,91 @@ Reduce scan noise while iterating:
95
123
  ```bash
96
124
  repopilot scan . --min-severity high
97
125
  repopilot scan . --workspace --min-severity medium
126
+ repopilot scan . --exclude fixtures --max-file-size 1mb --max-files 500
127
+ ```
128
+
129
+ By default, RepoPilot skips low-signal audit paths such as tests, fixtures, examples, generated files, and benchmarks. Use `--include-low-signal` when you want those paths analyzed too.
130
+
131
+ ## Local-First AI Workflow
132
+
133
+ RepoPilot does not call LLM APIs. AI commands scan local files and produce Markdown
134
+ that you decide where to paste.
135
+
136
+ `repopilot ai context` scans a project and formats all findings as structured markdown ready to paste into Claude Code, Cursor, ChatGPT, or any LLM assistant. It includes a risk level, tech stack summary, findings grouped by category with evidence snippets and fix recommendations, and a token-count estimate.
137
+
138
+ ```bash
139
+ # Paste into Claude Code or ChatGPT
140
+ repopilot ai context .
141
+
142
+ # Focus on security only, keep it short
143
+ repopilot ai context . --focus security --budget 2k
144
+
145
+ # Save to file
146
+ repopilot ai context . --output repopilot-context.md
147
+
148
+ # Pipe directly into clipboard (macOS)
149
+ repopilot ai context . --no-header | pbcopy
150
+ ```
151
+
152
+ ## Example Output
153
+
98
154
  ```
155
+ $ repopilot ai context .
156
+
157
+ # RepoPilot Vibe Check — my-app
158
+
159
+ **Risk Level:** 🟠 ELEVATED
160
+ **Tech Stack:** React Native (New Arch), Expo, TypeScript
161
+ **Size:** 94 files · 8,340 LOC · ~42k tokens
162
+ **Health:** 18 findings · 2.2/kloc — 4 high, 9 medium
163
+
164
+ ## Security (2 high)
165
+ 1. [HIGH] Possible secret detected — `src/config/api.ts:12`
166
+ ```
167
+ const API_KEY = "sk_live_…"
168
+ ```
169
+ > **Fix:** Move to environment variables or a secrets manager.
99
170
 
100
- ## AI-Assisted Workflow
171
+ ## Architecture (2 high)
172
+ 1. [HIGH] Circular dependency detected — `src/store/index.ts`
173
+ > **Fix:** Extract shared types to a separate module to break the cycle.
174
+
175
+ ## Top Recommendations
176
+ 1. **Move hardcoded API key** (src/config/api.ts:12) — use process.env or a vault
177
+ 2. **Break circular dependency** (src/store/index.ts) — extract shared types
178
+
179
+ ---
180
+ *~3.8k tokens (budget: 4k) · scanned in 312ms — paste into Claude Code, Cursor, or ChatGPT*
181
+ ```
182
+
183
+ Paste this into a coding assistant and ask for a focused patch. For larger
184
+ repositories, start with one focus area instead of asking for every finding at
185
+ once.
186
+
187
+ ## Recommended Remediation Loop
101
188
 
102
189
  RepoPilot is a local-first safety layer for AI-assisted and vibe-coded changes. Run it after generating or refactoring code to catch newly introduced high-risk findings, workspace hotspots, missing tests, and architecture drift without uploading source code to an external service.
103
190
 
104
191
  ```bash
192
+ repopilot ai context . --focus security # get an LLM brief for Claude Code
193
+ repopilot ai plan . --focus security # get a prioritized hardening plan
194
+ repopilot ai prompt . --budget 8k # generate a paste-ready remediation prompt
105
195
  repopilot review . --base origin/main --baseline .repopilot/baseline.json --fail-on new-high
106
196
  repopilot scan . --workspace --min-severity medium --format markdown --output repopilot-report.md
107
197
  ```
108
198
 
109
- The v0.7.0 release does not add new `vibe`, `harden`, or AI prompt commands. Those are planned as deterministic post-0.7 workflows built on the existing scan and review data.
110
-
111
199
  ## Commands
112
200
 
113
201
  | Command | Alias | Description |
114
202
  |---------|-------|-------------|
115
203
  | `repopilot scan <path>` | `s` | Scan a project, folder, or file for findings |
116
204
  | `repopilot review [path]` | `r` | Review findings that touch changed Git diff lines |
205
+ | `repopilot ai context <path>` | — | LLM-ready context from a scan |
206
+ | `repopilot ai plan <path>` | — | Prioritized remediation plan |
207
+ | `repopilot ai prompt <path>` | — | AI-ready remediation prompt |
117
208
  | `repopilot compare <before> <after>` | `cmp` | Compare two JSON scan reports and show what changed |
118
209
  | `repopilot baseline create <path>` | `bl` | Scan a path and store current findings as accepted debt |
210
+ | `repopilot doctor [path]` | `d` | Diagnose audit readiness |
119
211
  | `repopilot init` | — | Generate a default `repopilot.toml` configuration file |
120
212
 
121
213
  Use `--help` on any command for the full description and examples:
@@ -164,7 +256,12 @@ ignore = [
164
256
  "dist",
165
257
  "build",
166
258
  ".next",
167
- "coverage"
259
+ ".nuxt",
260
+ ".cache",
261
+ "coverage",
262
+ "vendor",
263
+ "Pods",
264
+ "DerivedData"
168
265
  ]
169
266
  max_file_bytes = 2097152
170
267
 
@@ -194,8 +291,16 @@ CLI threshold overrides:
194
291
  repopilot scan . --max-file-loc 500
195
292
  repopilot scan . --max-directory-modules 25
196
293
  repopilot scan . --max-directory-depth 6
294
+ repopilot scan . --max-file-size 1mb
295
+ repopilot scan . --max-files 1000
296
+ repopilot scan . --exclude generated
297
+ repopilot scan . --include-low-signal
197
298
  ```
198
299
 
300
+ `--max-file-size` accepts raw bytes or `kb`, `mb`, and `gb` suffixes. `--exclude` matches an exact path relative to the scan root or a file/directory name; repeat it for multiple paths.
301
+
302
+ JSON output includes scan input accounting fields: `files_discovered` for files found after ignore/exclude filters, `files_count` for analyzed text files, `files_skipped_low_signal` for default low-signal skips, and `binary_files_skipped` for unreadable/binary files.
303
+
199
304
  ## Baseline Workflow
200
305
 
201
306
  Existing repositories often have findings that cannot all be fixed before adopting a new audit tool. A baseline stores accepted existing findings so future scans can distinguish new findings from existing ones.
@@ -251,7 +356,7 @@ If your installed RepoPilot version does not support `--output`, redirect stdout
251
356
  repopilot scan . --format sarif > repopilot.sarif
252
357
  ```
253
358
 
254
- Use JSON when custom scripts need to parse RepoPilot results. Use Markdown for human-readable reports. Use SARIF for CI and code scanning integrations, including GitHub Code Scanning.
359
+ Use JSON when custom scripts need to parse RepoPilot results. Console, Markdown, and HTML reports include the RepoPilot version, risk summary, top rules, and grouped findings for human review. Use SARIF for CI and code scanning integrations, including GitHub Code Scanning.
255
360
 
256
361
  See [docs/integrations/github-code-scanning.md](docs/integrations/github-code-scanning.md) for a copy-paste GitHub Actions workflow, required permissions, and local validation commands.
257
362
 
@@ -272,6 +377,7 @@ Use `--fail-on new-high` to fail CI only when new high or critical findings are
272
377
  When `--fail-on new-*` is used without `--baseline`, RepoPilot treats all current findings as new. For baseline-based adoption, commit an accepted baseline and scan against it in CI.
273
378
 
274
379
  To upload RepoPilot findings to GitHub Code Scanning, generate SARIF and use `github/codeql-action/upload-sarif`. The workflow must include `security-events: write`.
380
+ The first-party action can also run `command: ai-context`, `command: ai-plan`, or `command: ai-prompt`; those commands emit Markdown and do not produce SARIF. Prefer typed action inputs such as `path`, `config`, `baseline`, `fail-on`, `focus`, `budget`, and `output`; `args` remains available for advanced flags.
275
381
 
276
382
  ```yaml
277
383
  name: RepoPilot
@@ -279,12 +385,16 @@ name: RepoPilot
279
385
  on:
280
386
  pull_request:
281
387
 
388
+ permissions:
389
+ contents: read
390
+ security-events: write
391
+
282
392
  jobs:
283
393
  repopilot:
284
394
  runs-on: ubuntu-latest
285
395
 
286
396
  steps:
287
- - uses: actions/checkout@v4
397
+ - uses: actions/checkout@v5
288
398
 
289
399
  - name: Install Rust
290
400
  uses: dtolnay/rust-toolchain@stable
@@ -299,7 +409,7 @@ jobs:
299
409
  run: repopilot scan . --format sarif --output repopilot.sarif
300
410
 
301
411
  - name: Upload to GitHub Code Scanning
302
- uses: github/codeql-action/upload-sarif@v3
412
+ uses: github/codeql-action/upload-sarif@v4
303
413
  if: always()
304
414
  with:
305
415
  sarif_file: repopilot.sarif
@@ -309,9 +419,6 @@ jobs:
309
419
 
310
420
  These are planned ideas, not current features:
311
421
 
312
- - Vibe Check command for AI-assisted codebase readiness
313
- - Hardening Plan output based on existing findings
314
- - AI-agent prompt/context export
315
422
  - Change Risk Map
316
423
  - Better architecture drift detection
317
424
  - Optional per-platform npm binary packages for faster installs
@@ -320,12 +427,18 @@ These are planned ideas, not current features:
320
427
 
321
428
  | Document | Description |
322
429
  |---|---|
430
+ | [docs/install.md](docs/install.md) | Installation options for Cargo, npm, Homebrew, curl, and source builds |
431
+ | [docs/ai-workflows.md](docs/ai-workflows.md) | Claude Code, ChatGPT, Cursor, and AI remediation workflows |
432
+ | [docs/security.md](docs/security.md) | Local-first trust model, installer security, and vulnerability reporting |
433
+ | [docs/configuration.md](docs/configuration.md) | `repopilot.toml`, presets, ignore files, and baseline adoption |
434
+ | [docs/language-support.md](docs/language-support.md) | Supported language/framework tiers, rule families, and limitations |
323
435
  | [docs/cli.md](docs/cli.md) | Complete CLI reference — all commands, flags, and exit codes |
324
436
  | [docs/commands.md](docs/commands.md) | Task-oriented command guide and common patterns |
325
437
  | [docs/rulesets.md](docs/rulesets.md) | Implemented audit rules, categories, and severity levels |
326
438
  | [docs/react-native.md](docs/react-native.md) | React Native and Expo detection, findings, and limitations |
327
439
  | [docs/integrations/github-code-scanning.md](docs/integrations/github-code-scanning.md) | GitHub Code Scanning SARIF workflow |
328
440
  | [docs/release.md](docs/release.md) | Manual release process |
441
+ | [docs/release-checklist-0.9.md](docs/release-checklist-0.9.md) | 0.9.0 release readiness checklist |
329
442
  | [docs/distribution.md](docs/distribution.md) | Distribution channels |
330
443
  | [docs/github-ruleset.md](docs/github-ruleset.md) | GitHub branch ruleset configuration |
331
444
  | [CHANGELOG.md](CHANGELOG.md) | Version history |
package/package.json CHANGED
@@ -1,38 +1,41 @@
1
1
  {
2
- "name": "repopilot",
3
- "version": "0.7.0",
4
- "description": "Local-first CLI for repository audit, architecture risk detection, baseline tracking, and CI-friendly code review.",
5
- "license": "MIT OR Apache-2.0",
6
- "repository": {
7
- "type": "git",
8
- "url": "git+https://github.com/MykytaStel/repopilot.git"
9
- },
10
- "homepage": "https://github.com/MykytaStel/repopilot#readme",
11
- "bugs": {
12
- "url": "https://github.com/MykytaStel/repopilot/issues"
13
- },
14
- "bin": {
15
- "repopilot": "bin/repopilot.js"
16
- },
17
- "scripts": {
18
- "postinstall": "node scripts/install.js",
19
- "test:npm": "node --test tests/npm_wrapper.test.js"
20
- },
21
- "files": [
22
- "bin",
23
- "scripts",
24
- "README.md",
25
- "LICENSE"
26
- ],
27
- "keywords": [
28
- "cli",
29
- "audit",
30
- "code-review",
31
- "static-analysis",
32
- "architecture",
33
- "react-native"
34
- ],
35
- "engines": {
36
- "node": ">=18"
37
- }
2
+ "name": "repopilot",
3
+ "version": "0.9.0",
4
+ "description": "Local-first CLI for repository audit, architecture risk detection, baseline tracking, and CI-friendly code review.",
5
+ "license": "MIT OR Apache-2.0",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/MykytaStel/repopilot.git"
9
+ },
10
+ "homepage": "https://github.com/MykytaStel/repopilot#readme",
11
+ "bugs": {
12
+ "url": "https://github.com/MykytaStel/repopilot/issues"
13
+ },
14
+ "bin": {
15
+ "repopilot": "bin/repopilot.js"
16
+ },
17
+ "scripts": {
18
+ "postinstall": "node scripts/install.js",
19
+ "test": "npm run test:npm",
20
+ "test:npm": "node --test tests/npm_wrapper.test.js",
21
+ "release:check": "bash scripts/verify-release.sh",
22
+ "product:smoke": "bash scripts/smoke-product.sh"
23
+ },
24
+ "files": [
25
+ "bin",
26
+ "scripts",
27
+ "README.md",
28
+ "LICENSE"
29
+ ],
30
+ "keywords": [
31
+ "cli",
32
+ "audit",
33
+ "code-review",
34
+ "static-analysis",
35
+ "architecture",
36
+ "react-native"
37
+ ],
38
+ "engines": {
39
+ "node": ">=18"
40
+ }
38
41
  }
@@ -0,0 +1,264 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
5
+
6
+ BINARY=""
7
+ REPO_PATH="$ROOT_DIR"
8
+ TMP_DIR=""
9
+ TMP_CREATED=0
10
+ KEEP_TMP=0
11
+ RUN_LEGACY=1
12
+
13
+ usage() {
14
+ cat <<'EOF'
15
+ Usage: scripts/smoke-product.sh [OPTIONS]
16
+
17
+ Run product-readiness smoke checks against RepoPilot.
18
+
19
+ Options:
20
+ --binary PATH Use an already built repopilot binary.
21
+ --repo PATH Repository or project path to smoke test. Defaults to this repo.
22
+ --tmp-dir PATH Directory for generated smoke artifacts. Defaults to mktemp.
23
+ --keep-tmp Keep generated smoke artifacts when using a temporary directory.
24
+ --skip-legacy Skip hidden 0.x compatibility command checks.
25
+ -h, --help Show this help message.
26
+
27
+ Examples:
28
+ scripts/smoke-product.sh
29
+ scripts/smoke-product.sh --binary ./target/release/repopilot
30
+ scripts/smoke-product.sh --repo /path/to/project --keep-tmp
31
+ EOF
32
+ }
33
+
34
+ while [[ $# -gt 0 ]]; do
35
+ case "$1" in
36
+ --binary)
37
+ BINARY="${2:-}"
38
+ shift 2
39
+ ;;
40
+ --repo)
41
+ REPO_PATH="${2:-}"
42
+ shift 2
43
+ ;;
44
+ --tmp-dir)
45
+ TMP_DIR="${2:-}"
46
+ shift 2
47
+ ;;
48
+ --keep-tmp)
49
+ KEEP_TMP=1
50
+ shift
51
+ ;;
52
+ --skip-legacy)
53
+ RUN_LEGACY=0
54
+ shift
55
+ ;;
56
+ -h|--help)
57
+ usage
58
+ exit 0
59
+ ;;
60
+ *)
61
+ echo "Unknown argument: $1" >&2
62
+ usage >&2
63
+ exit 2
64
+ ;;
65
+ esac
66
+ done
67
+
68
+ if [[ -z "$REPO_PATH" ]]; then
69
+ echo "--repo cannot be empty" >&2
70
+ exit 2
71
+ fi
72
+
73
+ REPO_PATH="$(cd "$REPO_PATH" && pwd)"
74
+
75
+ if [[ -z "$BINARY" ]]; then
76
+ if [[ ! -x "$ROOT_DIR/target/debug/repopilot" ]]; then
77
+ echo "==> Building debug binary for product smoke checks" >&2
78
+ cargo build --manifest-path "$ROOT_DIR/Cargo.toml"
79
+ fi
80
+ BINARY="$ROOT_DIR/target/debug/repopilot"
81
+ else
82
+ case "$BINARY" in
83
+ /*) ;;
84
+ *)
85
+ BINARY="$(cd "$(dirname "$BINARY")" && pwd)/$(basename "$BINARY")"
86
+ ;;
87
+ esac
88
+ fi
89
+
90
+ if [[ ! -x "$BINARY" ]]; then
91
+ echo "RepoPilot binary is not executable: $BINARY" >&2
92
+ exit 3
93
+ fi
94
+
95
+ if [[ -z "$TMP_DIR" ]]; then
96
+ TMP_DIR="$(mktemp -d)"
97
+ TMP_CREATED=1
98
+ else
99
+ rm -rf "$TMP_DIR"
100
+ mkdir -p "$TMP_DIR"
101
+ TMP_DIR="$(cd "$TMP_DIR" && pwd)"
102
+ fi
103
+
104
+ cleanup() {
105
+ if [[ "$TMP_CREATED" -eq 1 && "$KEEP_TMP" -eq 0 ]]; then
106
+ rm -rf "$TMP_DIR"
107
+ fi
108
+ }
109
+ trap cleanup EXIT
110
+
111
+ run_repopilot() {
112
+ echo "==> repopilot $*" >&2
113
+ (
114
+ cd "$REPO_PATH"
115
+ "$BINARY" "$@"
116
+ )
117
+ }
118
+
119
+ assert_non_empty() {
120
+ local file="$1"
121
+ if [[ ! -s "$file" ]]; then
122
+ echo "Expected non-empty file: $file" >&2
123
+ exit 3
124
+ fi
125
+ }
126
+
127
+ assert_contains() {
128
+ local file="$1"
129
+ local expected="$2"
130
+
131
+ if ! grep -Fq "$expected" "$file"; then
132
+ echo "Expected '$file' to contain: $expected" >&2
133
+ echo "---- file content ----" >&2
134
+ cat "$file" >&2 || true
135
+ echo "----------------------" >&2
136
+ exit 3
137
+ fi
138
+ }
139
+
140
+ validate_json_if_possible() {
141
+ local file="$1"
142
+
143
+ if command -v python3 >/dev/null 2>&1; then
144
+ python3 -m json.tool "$file" >/dev/null
145
+ fi
146
+ }
147
+
148
+ find_explain_file() {
149
+ local preferred="$REPO_PATH/src/main.rs"
150
+
151
+ if [[ -f "$preferred" ]]; then
152
+ printf '%s\n' "$preferred"
153
+ return 0
154
+ fi
155
+
156
+ local discovered=""
157
+ while IFS= read -r candidate; do
158
+ discovered="$candidate"
159
+ break
160
+ done < <(
161
+ find "$REPO_PATH" \
162
+ -path "$REPO_PATH/.git" -prune -o \
163
+ -path "$REPO_PATH/target" -prune -o \
164
+ -path "$REPO_PATH/node_modules" -prune -o \
165
+ -type f \( \
166
+ -name '*.rs' -o \
167
+ -name '*.ts' -o \
168
+ -name '*.tsx' -o \
169
+ -name '*.js' -o \
170
+ -name '*.jsx' -o \
171
+ -name '*.py' -o \
172
+ -name '*.go' \
173
+ \) \
174
+ -print
175
+ )
176
+
177
+ if [[ -n "$discovered" && -f "$discovered" ]]; then
178
+ printf '%s\n' "$discovered"
179
+ return 0
180
+ fi
181
+
182
+ printf '%s\n' "$REPO_PATH/Cargo.toml"
183
+ }
184
+
185
+ EXPLAIN_FILE="$(find_explain_file)"
186
+
187
+ echo "==> RepoPilot product smoke suite"
188
+ echo "Binary: $BINARY"
189
+ echo "Repo: $REPO_PATH"
190
+ echo "Tmp: $TMP_DIR"
191
+ echo
192
+
193
+ run_repopilot --version > "$TMP_DIR/version.txt"
194
+ assert_non_empty "$TMP_DIR/version.txt"
195
+
196
+ run_repopilot --help > "$TMP_DIR/help.txt"
197
+ assert_non_empty "$TMP_DIR/help.txt"
198
+ assert_contains "$TMP_DIR/help.txt" "scan"
199
+ assert_contains "$TMP_DIR/help.txt" "review"
200
+ assert_contains "$TMP_DIR/help.txt" "ai"
201
+ assert_contains "$TMP_DIR/help.txt" "inspect"
202
+
203
+ run_repopilot init --force --path "$TMP_DIR/repopilot.toml"
204
+ assert_non_empty "$TMP_DIR/repopilot.toml"
205
+
206
+ run_repopilot doctor . --format markdown --output "$TMP_DIR/doctor.md"
207
+ assert_non_empty "$TMP_DIR/doctor.md"
208
+
209
+ run_repopilot scan . --format json --output "$TMP_DIR/scan.json"
210
+ assert_non_empty "$TMP_DIR/scan.json"
211
+ validate_json_if_possible "$TMP_DIR/scan.json"
212
+
213
+ run_repopilot scan . --format markdown --output "$TMP_DIR/scan.md"
214
+ assert_non_empty "$TMP_DIR/scan.md"
215
+
216
+ if git -C "$REPO_PATH" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
217
+ run_repopilot review . --format markdown --output "$TMP_DIR/review.md"
218
+ assert_non_empty "$TMP_DIR/review.md"
219
+ else
220
+ echo "==> Skipping review smoke check because repo path is not inside a Git worktree" >&2
221
+ fi
222
+
223
+ run_repopilot ai context . --focus security --budget 2k --output "$TMP_DIR/ai-context.md"
224
+ assert_non_empty "$TMP_DIR/ai-context.md"
225
+
226
+ run_repopilot ai plan . --focus all --budget 2k --output "$TMP_DIR/ai-plan.md"
227
+ assert_non_empty "$TMP_DIR/ai-plan.md"
228
+
229
+ run_repopilot ai prompt . --focus quality --budget 2k --output "$TMP_DIR/ai-prompt.md"
230
+ assert_non_empty "$TMP_DIR/ai-prompt.md"
231
+
232
+ run_repopilot inspect knowledge --format json --output "$TMP_DIR/inspect-knowledge.json"
233
+ assert_non_empty "$TMP_DIR/inspect-knowledge.json"
234
+ validate_json_if_possible "$TMP_DIR/inspect-knowledge.json"
235
+
236
+ run_repopilot inspect knowledge --section rules --format markdown --output "$TMP_DIR/inspect-knowledge-rules.md"
237
+ assert_non_empty "$TMP_DIR/inspect-knowledge-rules.md"
238
+
239
+ run_repopilot inspect explain "$EXPLAIN_FILE" --format json --output "$TMP_DIR/inspect-explain.json"
240
+ assert_non_empty "$TMP_DIR/inspect-explain.json"
241
+ validate_json_if_possible "$TMP_DIR/inspect-explain.json"
242
+
243
+ if [[ "$RUN_LEGACY" -eq 1 ]]; then
244
+ run_repopilot vibe . --focus security --budget 2k --output "$TMP_DIR/legacy-vibe.md"
245
+ assert_non_empty "$TMP_DIR/legacy-vibe.md"
246
+
247
+ run_repopilot harden . --focus all --budget 2k --output "$TMP_DIR/legacy-harden.md"
248
+ assert_non_empty "$TMP_DIR/legacy-harden.md"
249
+
250
+ run_repopilot prompt . --focus quality --budget 2k --output "$TMP_DIR/legacy-prompt.md"
251
+ assert_non_empty "$TMP_DIR/legacy-prompt.md"
252
+
253
+ run_repopilot knowledge --format json --output "$TMP_DIR/legacy-knowledge.json"
254
+ assert_non_empty "$TMP_DIR/legacy-knowledge.json"
255
+ validate_json_if_possible "$TMP_DIR/legacy-knowledge.json"
256
+
257
+ run_repopilot explain "$EXPLAIN_FILE" --format json --output "$TMP_DIR/legacy-explain.json"
258
+ assert_non_empty "$TMP_DIR/legacy-explain.json"
259
+ validate_json_if_possible "$TMP_DIR/legacy-explain.json"
260
+ fi
261
+
262
+ echo
263
+ echo "==> Product smoke suite passed"
264
+ echo "Artifacts: $TMP_DIR"
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
5
+ cd "$ROOT_DIR"
6
+
7
+ echo "==> RepoPilot release verification"
8
+
9
+ echo "==> Rust formatting"
10
+ cargo fmt --all -- --check
11
+
12
+ echo "==> Rust clippy"
13
+ cargo clippy --all-targets --all-features -- -D warnings
14
+
15
+ echo "==> Rust tests"
16
+ cargo test --all
17
+
18
+ echo "==> Rust dependency security audit"
19
+ cargo audit
20
+
21
+ echo "==> Cargo dependency policy"
22
+ cargo deny check advisories licenses
23
+
24
+ echo "==> Shell script syntax"
25
+ scripts=()
26
+ if [[ -f install.sh ]]; then
27
+ scripts+=(install.sh)
28
+ fi
29
+ if [[ -d scripts ]]; then
30
+ while IFS= read -r -d '' script; do
31
+ scripts+=("$script")
32
+ done < <(find scripts -maxdepth 1 -type f -name '*.sh' -print0)
33
+ fi
34
+
35
+ if ((${#scripts[@]} > 0)); then
36
+ for script in "${scripts[@]}"; do
37
+ bash -n "$script"
38
+ done
39
+
40
+ echo "==> ShellCheck"
41
+ shellcheck "${scripts[@]}"
42
+ else
43
+ echo "==> No shell scripts found"
44
+ fi
45
+
46
+ echo "==> GitHub Actions validation"
47
+ workflows=()
48
+ if [[ -d .github/workflows ]]; then
49
+ while IFS= read -r -d '' workflow; do
50
+ workflows+=("$workflow")
51
+ done < <(find .github/workflows -maxdepth 1 -type f \( -name '*.yml' -o -name '*.yaml' \) -print0)
52
+ fi
53
+
54
+ if ((${#workflows[@]} > 0)); then
55
+ actionlint "${workflows[@]}"
56
+ else
57
+ echo "==> No GitHub Actions workflows found"
58
+ fi
59
+
60
+ echo "==> CLI release smoke tests"
61
+ cargo test --test cli_release_smoke
62
+
63
+ echo "==> Cargo package contents"
64
+ cargo package --list
65
+
66
+ echo "==> Cargo publish dry-run"
67
+ cargo publish --dry-run
68
+
69
+ echo "==> npm wrapper tests"
70
+ npm run test:npm
71
+
72
+ echo "==> npm package dry-run"
73
+ npm pack --dry-run
74
+
75
+ echo "==> Build release binary"
76
+ cargo build --release
77
+
78
+ echo "==> Product readiness smoke suite"
79
+ ./scripts/smoke-product.sh \
80
+ --binary ./target/release/repopilot \
81
+ --repo . \
82
+ --tmp-dir /tmp/repopilot-release-smoke
83
+
84
+ echo "==> Release verification passed"