
Vizzini packs your diff into token-sized chunks, asks any model behind a LiteLLM proxy for findings, and checks every answer against a CUE schema before it reaches you. If an answer fails, the error goes back to the model to fix. Written in pure Go as a static binary, ready to embed in mrman or run offline in a microVM.
git clone https://github.com/infrashift/vizzini-pr-reviewer && cd vizzini-pr-reviewer && make buildNeeds Go 1.25+. Not released yet: the pr-review CLI and pkg/reviewer API work today, and a first tag is coming soon. Try it from source.### internal/store/users.go (modified) @@ -41,6 +41,7 @@ func (s *Store) FindUser(ctx context.Context, name string) (*User, error) { 41 41 if name == "" { 42 42 return nil, ErrEmptyName 43 43 } 44 - row := s.db.QueryRowContext(ctx, "SELECT id, name FROM users WHERE name = $1", name) 44 + q := "SELECT id, name FROM users WHERE name = '" + name + "'" 45 + row := s.db.QueryRowContext(ctx, q) 45 46 var u User 46 47 return &u, row.Scan(&u.ID, &u.Name)
{
"summary": "FindUser now builds its SQL by string concatenation instead of a bound parameter.",
"risk_score": 92,
"findings": [
{
"file": "internal/store/users.go",
"start_line": 44,
"end_line": 45,
"severity": "Critical",
"category": "Security",
"title": "SQL injection via string-built query",
"body": "name is concatenated into the query, so a name like ' OR '1'='1 returns arbitrary rows. The previous version bound it as $1.",
"suggestion": "row := s.db.QueryRowContext(ctx, \"SELECT id, name FROM users WHERE name = $1\", name)"
}
]
}Left: the diff exactly as Vizzini renders it for the prompt, with old and new line numbers so findings point at real lines. Right: a review that passes schema/review.cue. Both are generated by Vizzini's own code.
Responses are unified with closed CUE definitions. A "High" where the schema says "Major", an end_line before its start_line, or an invented field is rejected, and the error goes back to the model to fix.
Diffs are packed into chunks within a tiktoken budget. Large files split only between hunks, never in the middle of one, and the token counts are exact, not estimated.
Every line in a hunk is labeled with its old and new line number, so the model points at lines that exist instead of guessing at offsets.
Speaks the OpenAI chat API to your internal LiteLLM proxy in JSON mode. Retries transient failures with backoff, and never retries a client error.
CGO_ENABLED=0 everywhere. Drop it into a minimal UBI9 image or a QEMU microVM with no libc dependency.
Tokenizer encodings are pinned by checksum and pre-seeded, so token counting never needs the network. The test suite blocks network access to prove it.
Each milestone is tracked as an issue and lands as its own tested commit.
The model can be as clever as it likes. Vizzini only accepts answers that unify with the schema, and anything else goes back to the model to fix before you ever see it.
Review SchemaHow It Works