parallax
Fans N independent readers over a request and surfaces only the divergences as questions humans must answer.
parallax
ADLC phase: P1 Interrogate · Gate: the measured ambiguity score is at or below threshold (spec/edge), or the routed answers agree (route).
What it defends against
A single model reading an ambiguous request commits to one interpretation and states it with total confidence. The ambiguity never surfaces; it just silently becomes a decision. parallax replaces that introspection with measurement: it fans N independent cheap-tier readings, diffs them, and reports only where they disagree. The ambiguity score (divergences / (divergences + agreements)) turns "is this spec clear?" into a number you can gate on.
Usage
adlc parallax --request "text" | --file req.md | --edge T1 T2 | --route "question" [flags]Three modes: spec (default, fans readers over a raw request), edge (--edge T1 T2, authors the contract implied between two tickets), and route (--route, answers a mid-build question and checks that the answers agree).
| Flag | Description |
|---|---|
--request <text> / --file <path> | Spec mode: request text inline or from a file (stdin if neither). |
--edge | Edge mode: takes two ticket IDs as positionals. |
--route <text> | Route mode: the question to route. |
--context <file> | Route mode: context file, repeatable. |
--tickets <path> | Tickets file for edge mode (default .adlc/tickets.json). |
--n <int> | Fan width: number of independent readings (default 3, minimum 2). |
--allow-partial-fan | Accept a verdict computed from fewer readings than --n requested. Off by default: a narrowed sample biases the score toward a pass. |
--threshold <0-1> | Ambiguity gate threshold (default 0.25). |
--tier cheap|mid|frontier | Override the LLM tier. |
--json | Machine-readable output (score + divergences). |
--prompt-only | Print the exact prompts and exit 0. No API key needed. |
--record-verdict <file|-> | With --prompt-only: record the operator's answer into .adlc/manifest.jsonl via gate-manifest. Requires --prompt-only and --ticket. |
--ticket <id> | Ticket this run is evidence for. Required with --record-verdict — an unbound record can satisfy any ticket's P1 gate. |
What a verdict requires
parallax refuses to certify a reading it did not actually take. Two guards, both operational errors (exit 1), never a score:
- Off-schema divergence payload. The mid-tier divergence call is asked for
{agreements: [...], divergences: [...]}. A refusal object, a truncated{}, a bare array or a{result: ...}wrapper used to fall through to "zero divergences, zero agreements", which scores 0 and passes the gate — an unanalysed spec reported as unambiguous. Such a payload is now refused. - Shrunken fan. The score is measured across
--nindependent readings, so a fan narrowed by rate limits, timeouts or unparseable JSON measures a smaller sample and scores systematically LOWER — it biases toward a pass. When fewer readings survive than were requested, the verdict is refused unless--allow-partial-fanis given.requestedandusedappear in both--jsonand--questions-jsonso a machine consumer can see the effective width instead of having to notice awarningsentry.
--n 1 is rejected at parse time: one reading can never be compared against
another, so it could only ever spend an API call on the way to an error.
Exit codes
Example
$ adlc parallax --request "Add a login page" --n 5
# Parallax spec analysis
## Agreement set (draft spec)
- Email + password fields, submit button
## Divergences — answer these
**Q1: Social sign-in?**
A) email/password only
B) also Google OAuth
**Ambiguity score:** 0.33 (threshold 0.25) — gate FAILS ✗
exit 2Go deeper
packages/parallax · Why unexamined ambiguity is dangerous: Tests Are the Spec.