# VibeGate

[![PyPI version](https://badge.fury.io/py/vibegate.svg)](https://badge.fury.io/py/vibegate)
[![CI](https://github.com/maxadamsky/VibeGate/actions/workflows/ci.yml/badge.svg)](https://github.com/maxadamsky/VibeGate/actions/workflows/ci.yml)
[![semantic-release](https://img.shields.io/badge/semantic--release-automated-e10079?logo=semantic-release)](https://github.com/semantic-release/semantic-release)
[![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg)](https://conventionalcommits.org)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)

VibeGate runs deterministic readiness checks for vibe-coded FastAPI repos and produces an evidence ledger plus a deterministic Fix Pack of remediation patches.

**Status:** Alpha - Automated releases via semantic-release

## Quickstart

Install and run VibeGate in the way that matches your workflow.

### A) Install VibeGate as a tool to run on other repos (pipx recommended)

This keeps the CLI isolated and available on your PATH.

```bash
pipx install "vibegate[tools]"
```

### B) Install VibeGate in a project venv

Use this when VibeGate should live alongside your project dependencies.

```bash
python -m pip install "vibegate[tools]"
```

If you want the minimal package without tooling, install without extras.

```bash
python -m pip install "vibegate"
```

### C) Contributor dev install

Use this when working on VibeGate itself.

```bash
python -m pip install -e ".[dev]"
```

## Release workflow

Releases are **fully automated** using [semantic-release](https://python-semantic-release.readthedocs.io/) based on [Conventional Commits](https://www.conventionalcommits.org/).

**How it works:**

1. Merge PRs with conventional commit messages to `main` (`feat:`, `fix:`, `perf:`, etc.)
2. The `semantic-release` workflow automatically runs on every push to `main`
3. If releasable commits exist, semantic-release will:
   - Determine the next version based on commit types
   - Update `CHANGELOG.md` automatically
   - Create and push a git tag
   - Build and publish to PyPI via Trusted Publishing
   - Create a GitHub Release with changelog notes

**No manual version bumping required!**

**Commit types and version bumps:**
- `feat:` → minor version bump (0.1.0 → 0.2.0)
- `fix:`, `perf:`, `refactor:` → patch version bump (0.1.0 → 0.1.1)
- `feat!:` or `BREAKING CHANGE:` → major version bump (0.1.0 → 1.0.0)
- `docs:`, `chore:`, `ci:`, `test:` → no release

**For contributors:**
- Use conventional commits (enforced by pre-commit hooks)
- See [CONTRIBUTING.md](CONTRIBUTING.md) for commit message format
- See [docs/RELEASING.md](docs/RELEASING.md) for detailed release documentation

**Manual releases** (backup method):
- For emergency releases, use the `hotfix` workflow
- For manual control, use the deprecated `prepare_release` workflow
- See [docs/RELEASING.md](docs/RELEASING.md) for details

### Run VibeGate

Installed tool path (console script available on PATH):

```bash
vibegate init .
vibegate doctor .
vibegate check .
```

From source path (works without installing the console script):

```bash
python -m vibegate init .
python -m vibegate doctor .
python -m vibegate check .
```

Review artifacts:

VibeGate writes `vibegate.yaml`, `.vibegate/suppressions.yaml`, and generates `artifacts/`
plus `evidence/`. The report, fix pack, and JSONL evidence ledger are the audit trail for
what ran and why it failed. `artifacts/` and `evidence/` are generated outputs and typically
should not be committed.

List fix pack tasks without `jq`:

```bash
vibegate fixpack-list --path artifacts/fixpack.json
```

## Developer install

```bash
python -m pip install -e ".[dev]"
```

## Contributor quickstart

```bash
make install
make test
make gate
make sync-schemas
```

Smoke CI repro (build wheel, install, run checks):

```bash
./scripts/ci_smoke.sh
```

Release smoke (clean build, install newest wheel, run CLI checks):

```bash
./scripts/build_and_smoke.sh
```

On Windows:

```powershell
./scripts/ci_smoke.ps1
```

## Demo

Try the demos:

- `examples/fastapi-demo/` (fails: a test expectation mismatch)
- `examples/fastapi-demo-fixed/` (passes)

Each demo includes a `run_vibegate.sh` script that runs `python -m vibegate check .`
and prints where artifacts and evidence land.

## CI example (GitHub Actions)

```yaml
- name: Install VibeGate
  run: pipx install "vibegate[tools]"
- name: Run VibeGate
  run: |
    vibegate doctor .
    vibegate check .
```

## Why the helper scripts exist (zsh-safe)

Shells like zsh can error on unmatched globs (for example, `dist/*.whl`). The
helper scripts in `scripts/` avoid that footgun by using `find` and explicit
selection of the newest wheel.

## Hello Plugin walkthrough

VibeGate supports external check plugins via Python entry points. A minimal example
plugin lives at `examples/hello-plugin/`.

1) Install the example plugin in editable mode:

```bash
python -m pip install -e examples/hello-plugin
```

2) Enable the plugin in `vibegate.yaml`:

```yaml
plugins:
  checks:
    enabled:
      - hello
```

3) (Optional) Customize the message from the plugin:

```yaml
plugins:
  checks:
    config:
      hello:
        message: "Hello from my repo!"
```

4) Run VibeGate as usual:

```bash
vibegate check .
```

You should see a new finding with `check_id` set to `plugin.hello` in the report.

## Local dev

```bash
python -m pip install -e ".[dev]"
pytest
```

## Continuous Integration

CI runs a fast Ubuntu job on every pull request targeting `main`, and runs a broader
OS matrix on pushes to `main` (plus manual workflow dispatches). Each job installs dev
dependencies, runs the test/check steps, and always uploads debugging artifacts from
`artifacts/` and `evidence/` to the workflow run's "Artifacts" section in GitHub Actions.

### Expected output files

Defaults (can be overridden by `vibegate.yaml`):

- `artifacts/vibegate_report.md`
- `artifacts/fixpack.json`
- `artifacts/fixpack.md`
- `evidence/vibegate.jsonl`

Configuration contract:

- `vibegate.yaml` (validated against `schema/vibegate.schema.json`)

### Profiles

Profiles let you define named override bundles (for enabling/disabling checks, severity overrides,
or tool-specific configuration tweaks) and select one with `profile`. The base config is loaded
first, then the selected profile overrides are applied on top.

Example:

```yaml
profile: "strict"
profiles:
  fast:
    checks:
      tests:
        enabled: false
      dependency_hygiene:
        enabled: false
  strict:
    checks:
      sast:
        enabled: true
        severity_threshold: high
    severity_overrides:
      "sast.bandit": high
  ci:
    checks:
      runtime_smoke:
        enabled: true
    tool_overrides:
      pytest:
        args: ["-q", "--maxfail=1"]
```

## Troubleshooting

If `vibegate.yaml` fails schema validation, regenerate it or fix the required fields:

```bash
vibegate init . --force
```

This overwrites the existing `vibegate.yaml`. Or fix the required fields listed in the schema errors.

## What runs

Baseline checks:

- Formatting: `ruff format --check`
- Lint: `ruff check --output-format json`
- Typecheck: `pyright --outputjson`
- Tests: `pytest -q`
- Dependency hygiene: lockfile required + `uv lock --check` when UV is detected
- Config sanity: deterministic scanning for debug/uvicorn reload/cors/secret/placeholder patterns
- Error handling: AST-based detection of bare except, empty except blocks, generic exceptions, and missing logging
- Defensive programming: AST-based detection of missing None checks, bounds validation, and zero divisor checks
- Code complexity: Function length, nesting depth, and cyclomatic complexity analysis
- Dead code: Detection of unreachable code and commented-out code blocks (optional vulture tool integration)

Optional when the tool is on `PATH`:

- `bandit` (JSON output)
- `gitleaks` (JSON output)
- `osv-scanner` offline only when a local DB snapshot is configured
- `vulture` (dead code detection)

## Workspace scope

VibeGate only scans files in the workspace set:

- In a Git repo, the workspace is `git ls-files` (tracked files).
- Outside Git, VibeGate walks the repo and applies default excludes.

Default excludes: `.venv/`, `venv/`, `env/`, `.git/`, `__pycache__/`,
`.pytest_cache/`, `.mypy_cache/`, `.ruff_cache/`, `node_modules/`, `dist/`,
`build/`, `.tox/`, `.eggs/`, `site-packages/`, `*.egg-info/`.

Virtualenv site-packages are excluded by default, including `.venv/site-packages`
and `venv/site-packages`.

## Evidence & Fix Pack

Evidence is written as JSONL with `run_start`, `tool_exec`, `finding`, `suppression_applied`, and `run_summary` events. Each tool execution records argv, cwd, duration, exit code, and artifact hashes.

Fix Pack output (`fixpack.json` + `fixpack.md`) is deterministic and ordered by category: dependency hygiene → vulnerability → secrets → security → typecheck → lint → formatting → tests → config → runtime.

## CLI

- `vibegate check [REPO_ROOT]` (defaults to `.`; exit 0 on PASS, 1 on FAIL, 2 on config error)
- `vibegate init [REPO_ROOT]` (scaffold `vibegate.yaml`, `artifacts/`, `evidence/`, `.vibegate/`)
- `vibegate doctor [REPO_ROOT]` (report missing tools + version drift)
- `vibegate fixpack` (runs checks, emits fix pack only, still writes evidence)
- `vibegate fixpack-list [--path artifacts/fixpack.json]` (TSV summary of fixpack tasks)
- `vibegate verify` (alias of `check`)
- `vibegate prompt` (stub)

## How to add VibeGate to an existing FastAPI repo

1. Add `vibegate.yaml` at the repo root using the contract schema in `schema/vibegate.schema.json`.
2. Set `project.app_module` to your ASGI entrypoint (e.g. `app.main:app`).
3. Commit a lockfile (`uv.lock`, `poetry.lock`, or `pdm.lock`) and ensure it stays fresh.
4. Add `.vibegate/suppressions.yaml` if you need to suppress known findings with justification and expiry.
5. Run `vibegate check` locally and in CI, and review `artifacts/fixpack.md` for remediation steps.
