ZeroModel: Evidence Before Ambition

ZeroModel: Evidence Before Ambition
Page content

ZeroModel is an attempt to compile useful parts of intelligence into identified, portable, inspectable decision artifacts — and to preserve enough evidence around those artifacts that we can reproduce, challenge and replay what they do.

That sentence now covers considerably more ground than I expected when I started.


Start with the strangest result

One ZeroModel policy contains 112 states.

It can be executed in Python.

It can also be exported into a completely dependency-free Lua module.

An independent reviewer cloned the repository, generated the Lua artifact, installed Lua 5.4 and executed it.

Python:

score: 4
steps: 22

Lua:

score: 4
steps: 22

Same policy. Same behaviour. Different runtime.

The generated Lua module is only about 21 KB.

More importantly, the policy itself retains an identity. The consumer plan retains a separate identity. So the runtime does not merely execute some copied decision logic — it can report exactly which policy artifact it executed and which consumer plan executed it.

That starts to hint at what ZeroModel is really becoming.

The unit being moved around the system is not just code. It is an identified decision procedure.


A policy can become an artifact

The core ZeroModel structure is the Visual Policy Map, or VPM.

Take a scored table. Rows might represent states, candidates, observations, reports, actions or anything else with a finite identity. Columns represent declared measurements.

Apply an explicit layout recipe. ZeroModel generates an identified artifact.

Every cell retains a route back to:

  • its original row;
  • its original metric;
  • its raw value;
  • its normalized value;
  • its position in the generated representation.

That means the visual representation is not merely an image of some data. It remains tied back to the data that produced it.

For finite policies, rows can represent states and columns can represent actions. The selected action then becomes a normal read operation over an identified artifact. No model invocation is required at decision time.

This sounds simple. That simplicity turns out to be useful.

    graph LR
    A[Scored Table] --> B[Layout Recipe]
    B --> C[VPM Artifact]
    C --> D[Each Cell Maps Back]
    D --> E[Original Row]
    D --> F[Original Metric]
    D --> G[Raw Value]
    D --> H[Normalized Value]
    C --> I[Decision Time]
    I --> J[Read Operation]
    J --> K[Selected Action]
  

31,213 visual decisions

We then asked a stranger question.

Could the policy be addressed visually instead of receiving a symbolic state identifier?

For a bounded arcade policy, ZeroModel built a deterministic visual codebook and a Visual Sign Reader. The hardened evaluation produced:

112 / 112 canonical state recoveries

112 / 112 canonical action recoveries

2,401 / 2,401 four-target waves completed

and

31,213 visual policy decisions

The runtime was being addressed by observations rather than being handed the symbolic state key directly.

This led to one of the most useful discoveries in the entire project.

    graph LR
    A[Visual Observation] --> B[Visual Sign Reader]
    B --> C[Deterministic Codebook]
    C --> D[Canonical State Recovery]
    D --> E[Policy Artifact]
    E --> F[Action Decision]
    F --> G[31,213 Visual Decisions]
    
    H[Space Invaders Environment] --> A
  

96.9% right can still mean 75% correct

In a later approximate-addressing experiment, normalized pixels produced:

1,302 / 1,344 correct actions

or:

96.9% action accuracy.

That looks excellent.

But exact state recovery was:

1,008 / 1,344

or:

75%.

That means there were hundreds of occasions where the system selected the correct action while identifying the wrong state.

That distinction is now a first-class concept inside ZeroModel.

Every decision can be adjudicated as:

Exact

Correct state. Correct action.

Action-equivalent

Wrong state. Same action.

Action-changing

Wrong state. Different action.

Rejected

No accepted decision.

This is much more useful than one accuracy number.

Suppose a model thinks a door is open when it is actually closed.

If both situations imply CONTINUE, the decision is behaviourally equivalent.

But if door open → CONTINUE and door closed → INSPECT, then the same perceptual mistake is action-changing.

That gives ZeroModel a very different way of thinking about uncertainty.


You do not always have to know the exact state

Suppose an observation cannot distinguish between three possible states.

A normal classifier is encouraged to pick one.

ZeroModel can instead retain all three.

Then ask: “What does the policy do in all three possible states?”

If every compatible state produces WAIT, then WAIT is safe with respect to the unresolved evidence.

If the compatible states disagree on the action, the system rejects the decision.

That pipeline now exists:

    graph TD
    A[Identified Observation] --> B[Typed Field Evidence]
    B --> C[Compatible States]
    C --> D[Policy Compatibility]
    D --> E{Common Action?}
    E -->|Yes| F[Execute Action]
    E -->|No| G[Reject Decision]
    
    H[Uncertainty Resolution] --> A
    I[Safe Ambiguity Handling] --> F
  

This is one of the directions I find most interesting.

Perception no longer has to solve every uncertainty. It has to solve the uncertainties that matter to the decision.


ZeroModel now also has a Search package.

But Search is not implemented as:

query → LLM → hopefully useful ranking

Instead, a relation can itself become a compiled artifact.

Start with a frozen representation. Measure the relation coordinates you care about. Fit a small deterministic readout from the representation into that declared relation space.

The result becomes an identified RelationReadoutArtifact.

At query time:

    graph LR
    A[Representation] --> B[Compiled Relation Readout]
    B --> C[Predicted Relation Coordinates]
    C --> D[Exact Relation Ranking]
    D --> E[Identified Candidates]
    F[Request] --> A
    E --> G[VPM Result]
  

The search result can then become another VPM.

The request is identified. The result is identified. The readout is identified. The corpus is identified. A receipt binds them together.

And replay can re-run the search and verify that the resulting identity has not changed.

This is a pattern that keeps appearing throughout ZeroModel.


Search is not the only thing that can be compiled

The Critic package does something similar.

Give ZeroModel a declared numeric feature surface:

feature A
feature B
feature C
...

and a narrow target judgement.

Critic can fit a lightweight linear classifier over those features. That critic then becomes an identified artifact.

Inference is basically:

standardise → linear weights → logit → sigmoid → score

It can expose the contribution of each feature. It can rank evidence. It can be replayed. And it can be exported as a portable arithmetic-only payload.

The default payload limit is 50 KiB.

So instead of repeatedly asking a large model to perform the same narrow judgement, one possible architecture becomes:

    graph LR
    A[Large/Expensive Process] --> B[Produce Evidence]
    B --> C[Small Specialised Critic]
    C --> D[Triage/Ranking/Escalation]
    E[50 KiB Payload Limit] --> C
  

This is one of the areas I intend to push much further.


Reports can be compiled too

The Artifacts package has another interesting mechanism.

Imagine an external system produces a report. ZeroModel can adapt that report into typed evidence and compile it into:

AdaptedReport
AdapterContract
ScoreTable
LayoutRecipe
VPMArtifact

Those are all independently identified artifacts.

But ZeroModel goes further. It validates that those objects actually belong together.

That matters. Five objects can each have valid hashes and still form an invalid aggregate.

For example:

ScoreTable      from report A
LayoutRecipe    from report B
VPMArtifact     from report C

Every object could individually be intact. The overall result would still be nonsense.

So the compiled-report loader reconstructs the relationship across the aggregate and verifies that the resulting VPM is exactly what the referenced table and recipe would deterministically produce.

This gives us a distinction I think matters a lot:

Object integrity is not aggregate integrity.

ZeroModel increasingly checks both.


Trust is also an artifact

Once artifacts become executable and portable, another question appears:

“Should this artifact be allowed to run here?”

ZeroModel Trust separates several questions that are often collapsed into one:

integrity
authenticity
signer trust
authorization
freshness
rollback
revocation

An artifact may be correctly signed and still not be authorized for a particular deployment. A signer may be trusted but the artifact may be stale. An artifact may have perfectly valid bytes and still be revoked.

The package uses Ed25519 through the standard cryptography library. There is no attempt to invent cryptography.

The interesting part is that the authorization decision becomes structured evidence rather than one opaque true/false.


Once there are many identified artifacts, they need structure.

ZeroModel Navigation builds deterministic hierarchies over them.

A hierarchy contains identified navigation tiles and leaf bindings. Traversal is governed by explicit rules. A traversal produces a receipt.

The traversal can later be replayed.

So a request can effectively say:

start from this identified hierarchy
use this declared traversal rule
follow these identified nodes
resolve this leaf artifact

and the entire route is retained.

This is separate from Search. Navigation handles a finite declared hierarchy. Search handles relation-based ranking.

That separation turned out to make the architecture considerably cleaner.

    graph TD
    A[Identified Hierarchy] --> B[Declared Traversal Rule]
    B --> C[Follow Identified Nodes]
    C --> D[Resolve Leaf Artifact]
    D --> E[Traversal Receipt]
    E --> F[Replay Possible]
    G[Search] --> H[Relation-Based Ranking]
    I[Navigation] --> J[Finite Hierarchy]
    H -.-> A
  

Video adds time

Static decisions are only part of the problem.

The Video package adds:

  • immutable frame identity;
  • clip manifests;
  • temporal evidence;
  • temporal policy decisions;
  • policy traces;
  • benchmark identities;
  • episode plans;
  • provider-evaluation runs;
  • operation chains.

A visual provider can therefore produce an address for each observation while the temporal policy layer reasons about the sequence.

Again, concrete vision providers are injected. Video consumes the contract. It does not need to own every possible perception implementation.

This separation between producer, evidence contract, and consumer is now common across the repository.


Provider evaluation became much more precise

The provider-evaluation infrastructure is particularly important because it uses the exact/action-equivalent/action-changing distinction.

A provider run can preserve:

provider configuration
observation identity
expected state
predicted state
expected action
selected action
raw response evidence
compiled policy identity
adjudicated outcome

That lets us answer two different questions:

Did the provider identify the state correctly?

and:

Did the provider nevertheless select the correct action?

Those are no longer allowed to collapse into one number.

This is exactly where the earlier 96.9% versus 75% result becomes operational rather than philosophical.


SQL persistence without leaking SQL everywhere

The SQLAlchemy package provides SQLite-backed persistence for the video/action-set domain.

The important architectural boundary is that application services still exchange DTOs. ORM objects do not escape the persistence layer.

The SQL implementation handles things SQLite is actually good at:

  • content-addressed blob deduplication;
  • relational ownership;
  • foreign-key enforcement;
  • transactional writes;
  • reopening durable evidence;
  • tamper detection.

This gives the evidence system a durable backend without making the rest of ZeroModel depend directly on an ORM.


Then there is Observer

Observer is probably the largest area currently being developed.

The basic idea starts with a mismatch between what a policy predicted would happen and what was actually observed.

That can become:

    graph LR
    A[Predicted Transition] --> C[Comparison]
    B[Observed Transition] --> C
    C --> D[Contradiction]
    D --> E[Repair Evidence]
  

But it has grown considerably beyond that.

The package now contains machinery for:

  • observation schemas;
  • comparison recipes;
  • hidden-state hypotheses;
  • transition verification;
  • deterministic transition ledgers;
  • replay;
  • rebuildable observation graphs;
  • promotion-candidate evidence;
  • shadow evaluation;
  • overlap analysis;
  • arbitration;
  • admission;
  • activation;
  • persistent registries.

One direction being explored is whether repeated, verified local structures can eventually become reusable habits.

That work is still actively being defined, but the amount of infrastructure around observation → contradiction → evidence → candidate → evaluation is now substantial.


And we keep the failures

Not everything worked.

This matters, but it is not the entire story.

The visual research alone now contains several recorded negative results:

  • normalized pixels;
  • frozen DINOv2 retrieval;
  • ridge probes;
  • registration/locality;
  • frame-local discriminative evidence;
  • several implicit PNG interventions against a fixed real provider.

Some retained strong ranking information but failed the acceptance criteria. Some were simply worse. Some produced no safe operating point.

Those experiments are still part of ZeroModel because knowing what doesn’t work changes what we build next.

The website now has an explicit failure register for exactly this reason.


The repository is now thirteen packages

The current package surface is:

analysis
artifacts
core
critic
navigation
observation
observer
perception
search
sqlalchemy
trust
video
vision

I don’t think that list is particularly interesting by itself. What is interesting is what happens when the pieces are connected.

A representation can become an artifact. An artifact can contain or address a decision. A decision can carry evidence. Evidence can be persisted. A decision can be adjudicated. A relation can become a readout. A judgement can become a critic. A hierarchy can become deterministic navigation. An artifact can be authorized for a deployment. A policy can leave Python and run in Lua. A sequence can become a replayable temporal trace. A contradiction can become structured evidence for changing a policy.

And all of those things can retain identities.

    graph TD
    A[Representation] --> B[Artifact]
    B --> C[Decision]
    C --> D[Evidence]
    D --> E[Persistence]
    C --> F[Adjudication]
    G[Relation] --> H[Readout]
    I[Judgement] --> J[Critic]
    K[Hierarchy] --> L[Navigation]
    M[Policy] --> N[Lua Runtime]
    O[Sequence] --> P[Temporal Trace]
    Q[Contradiction] --> R[Policy Change]
    B --> S[Identity]
    C --> S
    D --> S
    H --> S
    J --> S
    L --> S
  

This is why I rebuilt zeromodel.org

There is now too much inside ZeroModel for a normal project homepage.

A page saying “Fast | Explainable | Portable | Visual | AI” would tell you almost nothing.

So I rebuilt the website around claims.

The public site now has a structured claims registry. Every major claim gets an identifier.

For example:

ZM-CORE-VPM-001
ZM-CORE-POLICY-001
ZM-CORE-LUA-001
ZM-CORE-ADJ-001

ZM-VISION-ADDR-001
ZM-PER-STATE-001
ZM-VIDEO-EVAL-001

ZM-ART-CLOSURE-001
ZM-TRUST-AUTH-001
ZM-NAV-HIER-001

ZM-SEARCH-REL-001
ZM-CRITIC-LIN-001

The identifiers give us something stable to point at.

Each claim can carry:

status
package
claim
evidence
boundary
authority
source

And the registry can be filtered by evidence state.

The homepage shows only a handful of the most interesting results. The claims registry is where the project opens up.


There are far more claims than the homepage can show

This is perhaps the biggest reason for the redesign.

The homepage might show ten things. The repository now contains vastly more than ten things worth discussing.

There are claims about:

  • deterministic VPM identity;
  • source-to-cell mapping;
  • multiple policy views;
  • finite policy execution;
  • visual addressing;
  • provider-neutral observation contracts;
  • deployment bindings;
  • exact/action-equivalent adjudication;
  • immutable provider evaluations;
  • controlled representation experiments;
  • typed state evidence;
  • action-safe ambiguity;
  • fixed-camera evidence compilation;
  • temporal policies;
  • content-addressed matrix blobs;
  • compiled report closure;
  • artifact integrity;
  • signatures;
  • authorization;
  • revocation;
  • finite hierarchy compilation;
  • deterministic traversal;
  • relation-specific readouts;
  • Search receipts;
  • Search replay;
  • Critic compilation;
  • feature contributions;
  • portable Critic payloads;
  • persistent observation ledgers;
  • operation provenance;
  • SQLite deduplication;
  • transition verification;
  • observation graph rebuilding;
  • cross-runtime Lua execution.

And that is before getting into a large amount of research-stage and Observer work.

So the website is deliberately becoming less like a product landing page and more like a map of the system.


The recurring architecture

Looking across all of this, I keep seeing the same pattern:

    graph LR
    A[Declared Input] --> B[Deterministic Transformation or Fit]
    B --> C[Identified Artifact]
    C --> D[Bounded Execution]
    D --> E[Evidence]
    E --> F[Receipt]
    F --> G[Replay]
  

Sometimes the artifact is a policy. Sometimes it is a relation readout. Sometimes it is a critic. Sometimes it is a report. Sometimes it is a hierarchy. Sometimes it is a trust decision.

The implementation differs. The lifecycle is surprisingly similar.

That may ultimately be more important than any one VPM representation.


What I am trying to build

I increasingly think the interesting problem with AI is not simply making models more capable.

Models are already extraordinarily capable.

The harder engineering problem is what surrounds them.

How do we turn repeated reasoning into something cheaper?

How do we know which exact artifact made a decision?

How do we separate a correct answer from a correct understanding?

How do we preserve the alternatives?

How do we know what evidence was used?

How do we replay the result?

How do we move useful decisions into tiny runtimes?

How do we know whether an artifact is allowed to run?

How do we replace one component without quietly changing five others?

How do we know when uncertainty matters to the action and when it doesn’t?

And how do we retain enough evidence to discover when our own architecture is wrong?

Those are increasingly the questions ZeroModel is trying to answer.


See the current system

I have rebuilt the ZeroModel website around the actual repository rather than trying to fit everything into one description.

The best starting point is now:

https://zeromodel.org/

Then look at the claims registry:

https://zeromodel.org/claims/

And the reproduction page:

https://zeromodel.org/reproduce/

The source remains here:

https://github.com/ernanhughes/zeromodel

There is a lot more there now than I can reasonably fit into one article.

Which is probably the clearest sign that ZeroModel has become something considerably more interesting than the experiment I originally intended to build.


ZeroModel is not about building larger models. It is about building more accountable systems around the models we already have — one identified artifact at a time.