Your agent reports “done, all tests pass.” Do you believe it?
The problem is not that AI writes bad code. The problem is that the same actor writes the code, writes the test, and declares success. The target moves to wherever the dart lands. A better model just paints a more convincing bullseye.
Ranex is a kernel that sits outside the agent’s loop and judges every step. It does not ask the model what to do next. Rules an agent can read are suggestions. Rules compiled into code are constraints.
The Three-Port Architecture
Ranex separates concerns across three isolated ports. Each has a different trust boundary and a different failure domain.
Model port
One completion, forced structured output. Stateless. This port translates machine state into plain language for intake and review. It never executes code or writes to disk.
Worker port
An agent with its own loop and tools, running in an isolated environment. This is where code generation happens. The worker can read the repo, run tests, and propose changes. It cannot merge, deploy, or touch production state.
Judge port
External verification that runs outside the worker’s environment. This port receives the worker’s output and applies a fixed evaluation pipeline. The judge decides whether the work is complete, incomplete, or unsafe.
The judge is the kernel. It never runs inside the agent’s sandbox.
Multi-Stage Verification Pipeline
When the worker reports completion, the judge runs a fixed sequence of checks. Each stage is a separate process with its own failure mode.
| Stage | What It Checks | Failure Mode |
|---|---|---|
| Syntax validation | Code parses in target language | Malformed output, incomplete generation |
| Isolated test execution | Tests pass in clean environment | Flaky tests, environment pollution |
| Security scan | No secrets, no unsafe syscalls | Credential leakage, sandbox escape attempts |
| Diff analysis | Changes match stated intent | Scope creep, unrelated modifications |
| Regression check | Existing tests still pass | Breaking changes to stable code |
Each stage runs in a fresh container. The worker’s environment is destroyed before the judge starts. This prevents the agent from pre-warming caches, modifying test fixtures, or leaving state that influences verification.
Handling Partial Correctness
Most agent failures are not binary. Code that passes some tests but fails edge cases is the common case. The judge classifies outcomes into three buckets:
Complete
All verification stages pass. The diff is scoped to the stated task. No new warnings or errors in static analysis. The work moves to human review for merge approval.
Incomplete
Tests pass, but coverage dropped or new edge cases were introduced. The judge returns specific failure details to the worker with a retry budget. The worker gets three attempts before the task is marked as blocked.
Unsafe
Security scan failed, secrets were committed, or the diff includes files outside the task scope. The work is rejected immediately. No retry. The failure is logged with full context for post-mortem.
Partial correctness is not a pass. The judge does not negotiate.
Isolation and Sandboxing
The worker runs in a gVisor sandbox with no network access after the initial repo clone. File system writes are limited to a scratch directory. The worker cannot:
- Install packages outside the declared dependency manifest
- Execute binaries not in the approved tool list
- Write to paths outside
/workspace/scratch - Make outbound network calls after setup
The judge runs verification in a separate container built from the same base image but with the worker’s proposed changes applied. This container has network access only to internal package mirrors. It cannot call the model API or access the worker’s scratch space.
If the worker tries to persist state between runs (writing to /tmp, modifying global config), the judge’s clean environment will surface the dependency. This is intentional. Code that requires environment mutation to pass tests is flagged as incomplete.
State Management Between Stages
The kernel maintains three pieces of state:
Task manifest
Immutable after creation. Includes the original issue description, acceptance criteria, and file scope. The worker reads this but cannot modify it.
Attempt log
Append-only record of every worker run and judge verdict. Includes full diffs, test output, and timing data. This log is the source of truth for retry logic and post-mortem analysis.
Approval queue
Work that passed all judge stages but requires human review before merge. Each entry includes the final diff, verification results, and a link to the attempt log.
State is stored in a Postgres database with row-level locks. The worker and judge never write to the same tables. The worker writes to attempts, the judge writes to verdicts, and the approval service reads from both.
Code Example: Judge Invocation
Here’s the simplified flow when the worker signals completion:
def judge_worker_output(attempt_id: str) -> Verdict:
# Fetch immutable task and worker's final state
task = db.get_task(attempt_id)
worker_state = db.get_attempt(attempt_id)
# Destroy worker environment
sandbox.terminate(worker_state.container_id)
# Build clean verification environment
judge_container = sandbox.create(
base_image=task.language_image,
network="internal-only",
filesystem="ephemeral"
)
# Apply worker's proposed changes
judge_container.apply_diff(worker_state.diff)
# Run verification pipeline
results = []
for stage in VERIFICATION_STAGES:
result = judge_container.exec(stage.command)
results.append(result)
if not result.passed:
break # Fail fast
# Classify outcome
if all(r.passed for r in results):
verdict = Verdict.COMPLETE
enqueue_for_human_review(attempt_id)
elif any(r.is_security_failure for r in results):
verdict = Verdict.UNSAFE
else:
verdict = Verdict.INCOMPLETE
maybe_retry(attempt_id, worker_state.retry_count)
# Persist verdict and clean up
db.insert_verdict(attempt_id, verdict, results)
sandbox.destroy(judge_container.id)
return verdict
The key detail: the judge never asks the model to interpret results. Every decision is a deterministic function of exit codes, diff size, and test output.
Observability and Failure Modes
Every judge run produces structured logs with:
- Full command output from each verification stage
- Timing data for each stage (p50, p95, p99)
- Diff stats (lines changed, files touched, scope violations)
- Resource usage (CPU, memory, disk I/O)
Common failure modes and how the kernel surfaces them:
Worker times out
The sandbox enforces a 15-minute wall-clock limit. If the worker does not signal completion, the attempt is marked incomplete and the container is killed. The attempt log shows partial progress.
Tests pass in worker, fail in judge
This means the worker polluted its environment. The judge logs the diff between worker and judge test output. The task is marked incomplete with a specific error: “Environment-dependent test passage.”
Security scan finds secrets
The verdict is UNSAFE. The diff is not stored in the approval queue. The attempt log is flagged for manual review. The worker does not get retry budget.
Diff includes out-of-scope files
The judge compares changed files against the task manifest’s file scope. Any file outside that list triggers an incomplete verdict with a scope violation error.
When to Use This Pattern
This architecture makes sense when:
- Agent output goes to production without line-by-line human review
- Test passage is not sufficient evidence of correctness
- You need an audit trail of every agent decision and its verification
- The cost of a bad merge is higher than the cost of running isolated verification
It does not make sense when:
- Agents are used for exploration or prototyping (the overhead is not worth it)
- Human review happens before any code runs (the judge is redundant)
- Your deployment pipeline already has equivalent isolation and verification
The kernel is not a replacement for CI/CD. It is a trust boundary between agent output and the commit log.
Technical Verdict
Use Ranex’s kernel pattern when you are deploying agent-generated code to production and need a deterministic verification layer that cannot be influenced by the agent itself. The multi-stage pipeline and isolated execution prevent the most common failure mode: agents that pass their own tests by moving the goalposts.
Avoid this pattern when your agents are used for drafting or exploration, or when you already have strong CI/CD isolation. The overhead of spinning up fresh containers for every verification stage is only justified if agent output is trusted enough to merge but not trusted enough to skip verification.
The insight is simple: rules an agent can read are suggestions. Rules compiled into a kernel are constraints. If you need constraints, build a judge that never asks the model what to do next.