Metadata-Version: 2.4
Name: parallax-verify
Version: 0.1.0
Summary: Render-in-the-loop cross-modal self-verification for coding agents
Project-URL: Homepage, https://github.com/sani-savaliya/parallax
Project-URL: Repository, https://github.com/sani-savaliya/parallax
Project-URL: Issues, https://github.com/sani-savaliya/parallax/issues
Author: Sani Savaliya
License-Expression: MIT
License-File: LICENSE
Keywords: agents,anthropic,llm,mcp,regex,sql,verification,vision
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Quality Assurance
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: duckdb>=1.0
Requires-Dist: pillow>=10
Provides-Extra: anthropic
Requires-Dist: anthropic>=0.40; extra == 'anthropic'
Provides-Extra: dev
Requires-Dist: mypy; extra == 'dev'
Requires-Dist: pytest; extra == 'dev'
Requires-Dist: pytest-cov; extra == 'dev'
Requires-Dist: ruff; extra == 'dev'
Provides-Extra: mcp
Requires-Dist: mcp>=1.2; extra == 'mcp'
Provides-Extra: openai
Requires-Dist: openai>=1.0; extra == 'openai'
Description-Content-Type: text/markdown

# Parallax

**Render-in-the-loop self-verification for coding agents — and the study of why it works.**

> A second viewpoint reveals structure invisible from the first. Parallax flips a generated text artifact (SQL, a regex, plotting code) into a *rendered representation*, has a critic inspect the render, and reports (or corrects) silent, "looks-right-but-wrong" bugs a quick glance misses.

- **Package (PyPI):** `parallax-verify` · **import:** `parallax` · **API:** `crosscheck(artifact, render_fn)`
- **Status:** 🟢 **M1 usable.** The `crosscheck` primitive works end-to-end with two adapters (SQL-result-shape, regex-highlight), a CLI, and an MCP server. Offline by default (no API key); upgrades to a multimodal vision critic when one is configured. The *why-it-works* study (M2) is separate and ongoing.

---

## What it catches

Code that LLMs (and people) generate can fail **silently** — it runs, returns a plausible answer, and is wrong. Nothing throws.

- **SQL:** a dropped/loose `JOIN` predicate inflates row counts (fan-out); a `LEFT`/`INNER` swap silently drops rows.
- **Regex:** a greedy quantifier over-matches into a region it shouldn't; a pattern quietly misses spans it should catch.

Parallax extracts a small set of neutral shape facts (row-count ratio, null fractions, how many matches land in a forbidden region, …), renders them, and has a critic flag anything that looks off. It knows only what you tell it — there is no hidden oracle.

## Install

```bash
pip install parallax-verify               # core: SQL + regex + CLI, offline heuristic critic
pip install "parallax-verify[anthropic]"  # + Anthropic vision critic
pip install "parallax-verify[openai]"     # + any OpenAI-compatible vision endpoint
pip install "parallax-verify[mcp]"        # + the MCP server
```

## Quickstart (CLI)

Offline by default — no API key required:

```bash
# SQL: does this query's result shape look like a silent failure?
parallax sql "SELECT o.id, c.region FROM orders o JOIN cust c ON o.cust = c.id" \
  --setup "CREATE TABLE orders(id INT, cust INT); INSERT INTO orders VALUES (1,10),(2,10),(3,10);
           CREATE TABLE cust(id INT, region VARCHAR); INSERT INTO cust VALUES (10,'A'),(10,'B'),(10,'C'),(10,'D');" \
  --expected-rows 3
# -> [!] SUSPICIOUS  flagged: rowcount_ratio_to_expected   (12 rows where 3 were expected)

# Regex: does the pattern match where it shouldn't?
parallax regex "<.*>" --target "<a>SECRET<b>" --forbidden-spans 3:9
# -> [!] SUSPICIOUS  flagged: matches_in_forbidden_region
```

Exit code is `0` when it looks fine, `1` when flagged, `2` on error — so it drops into CI. Add `--json` for machine-readable output, and `--critic anthropic` (with `ANTHROPIC_API_KEY` set) to use the vision critic.

## Use from Python

```python
from parallax import Artifact, crosscheck, render_regex
from parallax.clients.heuristic_critic import HeuristicCritic

art = Artifact(kind="regex_highlight", text="<.*>",
               context={"target": "<a>SECRET<b>", "forbidden_spans": "3:9"})
result = crosscheck(art, render_regex, HeuristicCritic(), mode="expected")
print(result.critique.caught, result.critique.flagged)  # True ('matches_in_forbidden_region',)
```

Run the full demo (SQL + regex, offline): `python examples/demo.py`.

## Use as an MCP tool (for Claude / agents)

`parallax-mcp` starts a server exposing one `crosscheck` tool (`kind` = `sql` | `regex`, `text`, `context`, optional `mode`/`critic`). Point your MCP client at it and an agent can render-verify its own generated SQL/regex before trusting the result.

## The two honest modes

Parallax has no magic oracle. It works from what you give it:

1. **Supplied expectations** — you provide the expected row count, the spans you meant to match, or the regions that must not match.
2. **Relative anomaly** — compare against a previous / reference run.

## Critics

Bring your own key — `local` needs none, and the vision critics accept a key from an env var or the `--api-key` flag:

- **`local`** (default) — a fast, offline, rule-based sanity check over the same verdict-free features. No API key.
- **`anthropic`** — an Anthropic multimodal model looks at the rendered image. `PARALLAX_CRITIC=anthropic` + `ANTHROPIC_API_KEY` (default model `claude-opus-4-8`).
- **`openai`** — any OpenAI-compatible vision endpoint. `PARALLAX_CRITIC=openai` + `OPENAI_API_KEY` (default model `gpt-4o-mini`). Point `--base-url` (or `PARALLAX_BASE_URL`) at OpenAI, Google Gemini's OpenAI-compatible endpoint, OpenRouter, or a local server, and pick the model with `--model`.

```bash
# use your own OpenAI key
parallax sql "..." --setup "..." --expected-rows 3 --critic openai --api-key "$OPENAI_API_KEY"
# or a different provider via its OpenAI-compatible endpoint
parallax regex "<.*>" --target "<a>x<b>" --forbidden-spans 3:4 \
  --critic openai --base-url https://openrouter.ai/api/v1 --model "google/gemini-2.5-flash"
```

All settings also read from the environment (`PARALLAX_CRITIC` / `PARALLAX_MODEL` / `PARALLAX_API_KEY` / `PARALLAX_BASE_URL`) — see [.env.example](https://github.com/sani-savaliya/parallax/blob/main/.env.example).

## What this is (and is not)

The render-and-critique *loop* is not new — it exists in several verticals (maps, motion trajectories, plotting, GUI agents). **Parallax's contribution is different:** a general, artifact-agnostic primitive with SQL-result-shape and regex-highlight adapters, plus a controlled study the field skips.

We do **not** claim "rendering beats text," that images universally help, or that the idea is ours. The honest claim is a **model-conditional representation effect**, scoped to the cells we actually run, with nulls reported. The factorial decomposition that would justify any *why-it-works* statement is a separate, ongoing research program (M2) — see [docs/NOVELTY.md](https://github.com/sani-savaliya/parallax/blob/main/docs/NOVELTY.md) for the full do-not-claim list and [docs/RED-TEAM.md](https://github.com/sani-savaliya/parallax/blob/main/docs/RED-TEAM.md) for why the design is shaped this way.

## Documentation

| Doc | What |
|---|---|
| [docs/PRD.md](https://github.com/sani-savaliya/parallax/blob/main/docs/PRD.md) | Product requirements, users, scope/non-goals |
| [docs/INTERFACE.md](https://github.com/sani-savaliya/parallax/blob/main/docs/INTERFACE.md) | `crosscheck()` + the adapter contract + worked adapter specs |
| [docs/ARCHITECTURE.md](https://github.com/sani-savaliya/parallax/blob/main/docs/ARCHITECTURE.md) | Stack, package layout, sandboxing, model routing |
| [docs/TASKS.md](https://github.com/sani-savaliya/parallax/blob/main/docs/TASKS.md) | TDD-first task list (M1 library MVP + M2 study), risk register |
| [docs/EVAL.md](https://github.com/sani-savaliya/parallax/blob/main/docs/EVAL.md) | **The M2 crux** — pre-registration-grade factorial decomposition design |
| [docs/NOVELTY.md](https://github.com/sani-savaliya/parallax/blob/main/docs/NOVELTY.md) | Prior-art verdict, defensible claim, do-not-claim list |
| [docs/RED-TEAM.md](https://github.com/sani-savaliya/parallax/blob/main/docs/RED-TEAM.md) | The adversarial findings that reshaped the contribution |
| [docs/CITATIONS.md](https://github.com/sani-savaliya/parallax/blob/main/docs/CITATIONS.md) | Citation-integrity pass — 6 fixes needed before publish |
