Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ dist
grammars/
# Generated graph artifacts from fixture/dev runs
test/**/.vibgrate/
# Vitest 5 report/cache directory (blob, attachments, html reporter)
.vitest/
4 changes: 2 additions & 2 deletions DOCS.md
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,7 @@ Use this to treat SBOMs as operational intelligence instead of static compliance
The primary command. Scans your project for upgrade drift.

```bash
vg scan [path] [--vulns] [--full] [--format text|json|sarif|md] [--out <file>] [--fail-on warn|error] [--offline] [--package-manifest <file>] [--no-local-artifacts] [--max-privacy] [--baseline <file>] [--drift-budget <score>] [--drift-worsening <percent>] [--changed-only] [--concurrency <n>]
vg scan [path] [--vulns] [--full] [--format text|json|sarif|md] [--out <file>] [--fail-on warn|error|architecture-finding|architecture-warning] [--offline] [--package-manifest <file>] [--no-local-artifacts] [--max-privacy] [--baseline <file>] [--drift-budget <score>] [--drift-worsening <percent>] [--changed-only] [--concurrency <n>]
```

| Flag | Default | Description |
Expand All @@ -631,7 +631,7 @@ vg scan [path] [--vulns] [--full] [--format text|json|sarif|md] [--out <file>] [
| `--full` | — | Comprehensive scan: enables `--vulns` and reports banned dependencies when a standards policy exists |
| `--format` | `text` | Output format: `text`, `json`, `sarif`, or `md` |
| `--out <file>` | — | Write output to a file |
| `--fail-on <level>` | — | Exit with code 2 if findings at this level exist |
| `--fail-on <level>` | — | Exit with code 2 if findings at this level exist. `warn` / `error` gate on drift findings. `architecture-finding` (hard boundary violations) and `architecture-warning` (violations and warnings) gate on the architecture module's boundary findings, judged under the policy pack in force — `hexagonal-v1` unless `.vibgrate/architecture.toml`, `VIBGRATE_ARCHITECTURE_POLICY` or `vg build --policy` says `layered-v1`. The output names the pack whether the gate passes or fails; each failing row is `file:line symbol violation: … (rule)`. Pick the pack before turning this on: see [Architecture policy packs](./docs/architecture-policies.md) |
| `--baseline <file>` | — | Compare against a previous baseline |
| `--changed-only` | — | Only scan changed files |
| `--concurrency <n>` | `8` | Max concurrent npm registry calls |
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -524,7 +524,7 @@ Under each set, commands are listed A–Z. A short **typical path** (usual order
| Command | Description |
| --- | --- |
| `vg ask "<question>"` | Query the map in natural language |
| `vg build [path]` | Build / update the code map (incremental, deterministic) |
| `vg build [path]` | Build / update the code map (incremental, deterministic); `--policy hexagonal-v1\|layered-v1` picks the boundary rules the architecture module evaluates (default from `.vibgrate/architecture.toml`; the two packs are compared in [docs/architecture-policies.md](./docs/architecture-policies.md)) |
| `vg bundle` | Build an air-gapped bundle (grammars + graph + library catalog) |
| `vg code ["<instruction>"]` | Graph-grounded coding agent — local or hosted model, every edit and command approved (`--auto` for CI, `--single` for a one-shot diff) |
| `vg embed` | Precompute the semantic index for instant `vg ask` |
Expand Down Expand Up @@ -612,7 +612,7 @@ Local scoring does not require this — nothing leaves your machine until you pu
| `vg push` | Upload scan results to Vibgrate Cloud |

```bash
vg scan [path] [--vulns] [--full] [--format text|json|sarif|md] [--out <file>] [--fail-on warn|error] \
vg scan [path] [--vulns] [--full] [--format text|json|sarif|md] [--out <file>] [--fail-on warn|error|architecture-finding|architecture-warning] \
[--offline] [--package-manifest <file>] [--no-local-artifacts] [--max-privacy] \
[--drift-budget <score>] [--drift-worsening <percent>] [--baseline <file>]
```
Expand Down
2 changes: 1 addition & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ inputs:
image-tag:
description: 'Scanner image tag to run (defaults to a pinned, tested release).'
required: false
default: '2026.903.2' # vibgrate:cli-version — stamped by scripts/stamp-release-pins.mjs
default: '2026.903.3' # vibgrate:cli-version — stamped by scripts/stamp-release-pins.mjs
verify:
description: 'Verify the image cosign signature + provenance before running (requires cosign on the runner).'
required: false
Expand Down
2 changes: 1 addition & 1 deletion charts/vibgrate/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ type: application
# stamped to the released @vibgrate/cli calendar version by
# scripts/stamp-release-pins.mjs (via the marker on the appVersion line below).
version: 0.1.1
appVersion: "2026.903.2" # vibgrate:cli-version — stamped by scripts/stamp-release-pins.mjs
appVersion: "2026.903.3" # vibgrate:cli-version — stamped by scripts/stamp-release-pins.mjs
home: https://vibgrate.com
icon: https://vibgrate.com/web-app-manifest-512x512.png
sources:
Expand Down
87 changes: 87 additions & 0 deletions docs/architecture-policies.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Architecture policy packs: `hexagonal-v1` and `layered-v1`

The architecture module (`vg module install haile`) reads what each function or
method does from its own source text — the store it writes, the query it runs,
the HTTP call it makes, the response it returns — and then judges those duties
against one **policy pack**: a small set of boundary rules for the style of
architecture your repository says it follows. A finding is a crossing of one
of those rules, anchored on the line of the offending call.

Two packs ship. They disagree on purpose, so pick the one that describes your
code **before** you turn on `vg scan --fail-on architecture-finding`. A layered
application judged as a hexagon fails on its services; a hexagonal one judged
as layered fails on its adapters. Nothing here is compiled, interpreted or run.

## Choosing the pack

The pack is chosen once per repository and stamped on the classify file, so
every reader (`vg show`, the VS Code Architecture view, `vg scan`) knows which
rules produced a finding. Precedence, highest first:

| Where | How |
|---|---|
| `vg build --policy layered-v1` | For one build |
| `VIBGRATE_ARCHITECTURE_POLICY=layered-v1` | For one shell or CI job |
| `.vibgrate/architecture.toml` | Committed default for the repository |
| Nothing set | `hexagonal-v1` |

```toml
# .vibgrate/architecture.toml
policy = "layered-v1"
```

An unknown value falls back to `hexagonal-v1` without failing the build. The
pack in force is printed by `vg scan --fail-on architecture-finding` whether
the gate passes or fails, and every rule id carries it as a prefix
(`layered-v1/controller-reads`).

## What each pack expects

| | `hexagonal-v1` (ports and adapters) | `layered-v1` (controller → service → repository) |
|---|---|---|
| Fits | Clean / onion architecture: handlers delegate to an application layer, the domain is pure, persistence sits behind a port interface | Classic MVC and service-layer apps: Spring Boot, ASP.NET MVC, Rails, Django, Express + service classes |
| HTTP handler writes the store itself | **violation** `controller-persists` | **violation** `controller-persists` |
| HTTP handler reads the store itself | allowed | warning `controller-reads` — reads go through the service layer too |
| HTTP handler calls out over HTTP itself | warning `controller-calls-out` (skips the application layer) | warning `controller-calls-out` (skips the service layer) |
| Domain model / domain service writes a store, calls out, or touches the file system | **violation** `domain-does-io` | **violation** `domain-does-io` (the model layer must stay pure) |
| Application service / use case writes the ORM directly (a concrete `DbContext`, `PrismaClient`, session) | warning `service-writes-orm` — go through a port or repository | allowed — the service layer owns the ORM |
| Repository / persistence adapter talks to the network | warning `repository-calls-out` | warning `repository-calls-out` |
| View / UI code writes the store | **violation** `view-persists` | **violation** `view-persists` |

"Writes the store itself" means the handler's own body calls a repository, a
DbContext or session, an ORM model, or a SQL write — or calls into a class
whose name says it is the store layer. Delegating to an application service,
a command handler or a MediatR-style `Send` is the intended path and is never
a crossing, even when that callee persists. Writing through an interface such
as `IApplicationDbContext` from an application service is a port, not a
violation, under either pack.

## Gating CI

```bash
# hard violations only (recommended first step)
vg scan --fail-on architecture-finding

# violations and warnings — the dry run for a stricter gate
vg scan --fail-on architecture-warning
```

The gate is off by default. It needs the code map the scan builds (not
compatible with `--no-graph`, `--max-privacy` or `--no-local-artifacts`) and
the architecture module; when the module has not classified the map the scan
exits 2 with a message saying so rather than passing silently. Each failing
row is printed as `file:line symbol violation: message (rule)`; the summary
line names the pack. Start with `architecture-warning` in a non-blocking job to
see what the pack would flag, fix or accept those, then promote to
`architecture-finding` as the blocking gate.

## What the packs do not do

- They do not infer which pack you meant. A repository with no configuration
is judged as a hexagon.
- One pack applies to the whole repository. A per-path profile map and a
vertical-slice pack are not shipped.
- They judge duties reconstructed from source text and the code map. An
untyped call the map could not resolve is not evidence, so a store call on a
receiver nothing declares does not produce a finding; it also does not
suppress one that a typed call in the same body produces.
1 change: 1 addition & 0 deletions docs/ci/github-actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ vibgrate-vulns.sarif --fail-on error`, then upload the file yourself.
The CI template uses existing scan-time gates:

- `--fail-on error` to fail on error-level findings
- `--fail-on architecture-finding` to fail on a hard boundary finding from the architecture module (an HTTP handler that writes the store, domain code that does I/O); `architecture-warning` also fails on warnings. Needs the code map the scan builds and the module (`vg module install haile`); the rules come from `.vibgrate/architecture.toml` (`policy = "hexagonal-v1"` or `"layered-v1"`). Each failing line is `file:line symbol violation: … (rule)`
- `--drift-budget <score>` to fail when drift score exceeds your budget

Example gate command:
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@vibgrate/cli",
"version": "2026.903.2",
"version": "2026.903.3",
"description": "vg — local codebase intelligence CLI + MCP server for AI coding agents: deterministic code graph, drift reporting, and version-correct library docs (Apache-2.0)",
"//mcpName": "Official MCP registry ownership proof: the registry fetches the published npm package and requires this field to match the com.vibgrate/ai-context server entry (see docs/marketing/mcp-registry/README.md). Must ship in the published @vibgrate/cli package.json.",
"mcpName": "com.vibgrate/ai-context",
Expand Down Expand Up @@ -108,7 +108,7 @@
"graphology-types": "^0.24.8",
"tsup": "^8.0.0",
"tsx": "^4.23.12",
"vitest": "^4.1.10"
"vitest": "^5.0.0"
},
"engines": {
"node": ">=22.0.0"
Expand Down
Loading
Loading