Skip to main content

Render-in-the-loop cross-modal self-verification for coding agents

Project description

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

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:

# 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

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.
# 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.

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 for the full do-not-claim list and docs/RED-TEAM.md for why the design is shaped this way.

Documentation

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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

parallax_verify-0.1.0.tar.gz (118.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

parallax_verify-0.1.0-py3-none-any.whl (37.4 kB view details)

Uploaded Python 3

File details

Details for the file parallax_verify-0.1.0.tar.gz.

File metadata

  • Download URL: parallax_verify-0.1.0.tar.gz
  • Upload date:
  • Size: 118.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.14

File hashes

Hashes for parallax_verify-0.1.0.tar.gz
Algorithm Hash digest
SHA256 e9098dfec190c8c392f9465de88bf762d2575e949461875a0904b4eca19c9100
MD5 69db55965553c74847f0e70e7783e3b5
BLAKE2b-256 dd145fd1da51c0a0db37aa92e5f5d69ef590d093ab534835fc44819619c8b5aa

See more details on using hashes here.

File details

Details for the file parallax_verify-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for parallax_verify-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3fc96abced5f33d6027bad57a7ea4fb59363fc3a5226bf12c44e654687750141
MD5 6dfe22850142b3a1be035770aead15c5
BLAKE2b-256 c0bbf781736c6587cfd36a1a3df089a1e6c334532253c9ea7f7b62a4ec1e5923

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page