zeromodel

ZeroModel 1.0.13 Package System Architecture

Status: Historical baseline — describes the completed six-distribution split. Superseded as the current architecture by package-system-next.md, which documents the nine-distribution workspace (this document’s six packages plus zeromodel-artifacts, zeromodel-trust, zeromodel-navigation). This document is preserved unmodified below as the record of what Stage 1.0.13A–H actually delivered; it is not rewritten in place.
Release: 1.0.13
Repository model: one repository, multiple independently buildable Python distributions
Compatibility policy: breaking source and import changes are permitted
Release policy: no intermediate extraction stage is publishable

1. Decision

ZeroModel 1.0.13 will replace the current single-distribution package with a workspace of independently installable capability packages that share the implicit zeromodel namespace.

The package system will contain:

  1. zeromodel — the lightweight, complete artifact and bounded-policy core;
  2. zeromodel-analysis — deterministic analysis and verification over core artifacts;
  3. zeromodel-observation — provider-neutral observation and address contracts;
  4. zeromodel-vision — concrete deterministic visual-address runtime implementations;
  5. zeromodel-video — temporal policy and video action-set domain functionality;
  6. zeromodel-sqlalchemy — SQLAlchemy and SQLite persistence adapters.

Research experiments, benchmark orchestration, evidence generation, and failed or unpromoted provider implementations will not be shipped as production packages. They will live under research/ and may depend on production packages. Production packages must never import from research/.

This is an architectural extraction, not a compatibility migration. The current root re-export surface will be removed rather than redirected through compatibility aliases.

2. Why this change is required

The current distribution declares a small NumPy dependency surface while the zeromodel namespace now contains several distinct systems:

These concerns have different dependency, stability, testing, and release needs. Keeping them in one distribution makes the root API misleading, makes optional capabilities appear foundational, and allows accidental imports to erase the intended domain boundaries.

The existing RMDTO direction remains valid:

Runtime -> Facade -> Engine -> Service -> Store protocol -> Store implementation

The package split raises that rule to the distribution level. The domain package owns DTOs, services, and protocols. The persistence package owns ORM mappings, sessions, and SQL Store implementations.

3. Goals

ZeroModel 1.0.13 must provide all of the following:

4. Non-goals

The 1.0.13 package-system work will not:

5. Workspace layout

The final repository layout is:

packages/
├── core/
│   ├── pyproject.toml
│   ├── README.md
│   ├── src/zeromodel/core/
│   └── tests/
├── analysis/
│   ├── pyproject.toml
│   ├── README.md
│   ├── src/zeromodel/analysis/
│   └── tests/
├── observation/
│   ├── pyproject.toml
│   ├── README.md
│   ├── src/zeromodel/observation/
│   └── tests/
├── vision/
│   ├── pyproject.toml
│   ├── README.md
│   ├── src/zeromodel/vision/
│   └── tests/
├── video/
│   ├── pyproject.toml
│   ├── README.md
│   ├── src/zeromodel/video/
│   └── tests/
└── sqlalchemy/
    ├── pyproject.toml
    ├── README.md
    ├── src/zeromodel/persistence/sqlalchemy/
    └── tests/

research/
├── visual/
├── video/
├── benchmarks/
└── evidence/

integration_tests/
examples/
scripts/
docs/
pyproject.toml
package-boundaries.toml

The repository-root pyproject.toml is workspace and tool configuration. It is not a publishable ZeroModel distribution after the split. Every published package builds from its own package directory.

6. Shared namespace rule

zeromodel becomes a PEP 420 implicit namespace.

There must be no file at:

zeromodel/__init__.py

and no package may ship:

src/zeromodel/__init__.py

Each distribution owns one non-overlapping subtree:

Distribution Owned import subtree
zeromodel zeromodel.core
zeromodel-analysis zeromodel.analysis
zeromodel-observation zeromodel.observation
zeromodel-vision zeromodel.vision
zeromodel-video zeromodel.video
zeromodel-sqlalchemy zeromodel.persistence.sqlalchemy

No two distributions may contain the same import package or write files into the same owned subtree.

Public imports must identify capability ownership:

from zeromodel.core import ScoreTable, VPMArtifact, build_vpm
from zeromodel.analysis import SpatialOptimizer
from zeromodel.observation import VisualAddressProvider
from zeromodel.vision import VisualSignReader
from zeromodel.video import VideoPolicyReader
from zeromodel.persistence.sqlalchemy import SqlAlchemyVideoActionSetStore

The following compatibility surface is intentionally removed:

from zeromodel import ScoreTable
from zeromodel import VisualSignReader
from zeromodel import VideoPolicyReader

7. Distribution responsibilities

7.1 zeromodel / zeromodel.core

The core is the smallest complete expression of ZeroModel.

A core-only installation must support this complete path:

scored rows
    -> deterministic VPM artifact
    -> stable identity and source mapping
    -> serialization or rendering
    -> exact bounded row address
    -> policy action and evidence

Core owns:

Candidate current modules include artifact, bundle, matrix_blob, metrics, policy_lookup, render, and the minimal parts of views. The inventory stage must verify each candidate and split modules when only part belongs in core.

Core does not own:

Core runtime dependencies are limited to the Python standard library and NumPy. Importing zeromodel.core must not import any optional ZeroModel package or any tracked heavyweight external dependency.

7.2 zeromodel-analysis / zeromodel.analysis

Analysis owns deterministic transformations, diagnostics, and verification that operate on core artifacts but are not required to construct or address one.

Expected responsibilities include:

Analysis may depend on core. Core must not depend on analysis.

7.3 zeromodel-observation / zeromodel.observation

Observation defines provider-neutral contracts between runtime observations and policy addresses.

Observation owns:

Observation must not import Torch, Transformers, Pillow, concrete image encoders, video benchmark machinery, SQLAlchemy, or ORM classes.

Observation may depend on core. Core must not depend on observation.

7.4 zeromodel-vision / zeromodel.vision

Vision owns supported concrete image-to-address runtime implementations.

Expected responsibilities include:

Vision must depend on observation contracts rather than defining a competing provider seam.

Learned provider adapters with heavyweight dependencies should not be forced into the base vision distribution. A future adapter such as zeromodel-vision-huggingface may own Torch and Transformers integrations after its runtime contract is stable. Until then, learned baselines remain research.

Benchmark harnesses, architecture showdowns, calibration sweeps, and failed or unpromoted systems belong under research/visual/, not in the production wheel.

7.5 zeromodel-video / zeromodel.video

Video owns supported temporal policy and video action-set domain behavior.

Video owns:

Video must not import SQLAlchemy, ORM modules, database sessions, or SQL Store implementations. ORM objects must never cross into this package.

Experimental local-correlation, discriminative, joint-evidence, provider-showdown, and benchmark-only implementations remain research unless the inventory and review process identifies a separately supported runtime component.

7.6 zeromodel-sqlalchemy / zeromodel.persistence.sqlalchemy

The SQLAlchemy package is an adapter package.

It owns:

It may depend on core and video. It must implement Store protocols declared by the video domain. It must not move domain services or scientific computation into the persistence package.

SQLite remains authoritative for durable identity, relationships, ordering, deduplication, transactionality, and retrieval. Python and NumPy remain authoritative for scientific derivation, rendering, transformation, replay, and digest computation.

8. Dependency graph

The only allowed production distribution edges are:

zeromodel-analysis ---------> zeromodel

zeromodel-observation ------> zeromodel
          ^
          |
zeromodel-vision -----------> zeromodel
          ^
          |
zeromodel-video ------------> zeromodel
          ^
          |
zeromodel-sqlalchemy -------> zeromodel-video
zeromodel-sqlalchemy -------> zeromodel

In table form:

Package May depend on
core standard library, NumPy
analysis core
observation core
vision core, observation
video core, observation
sqlalchemy core, video

Research may depend on any production package. Examples and integration tests may depend on any packages they demonstrate. Production packages may not depend on research, examples, integration tests, or repository scripts.

Circular distribution dependencies are forbidden.

9. Cross-package data rule

Package boundaries are crossed only by deliberate public objects:

The following may not cross package boundaries:

A sibling package may import only from the owning package’s documented public surface or a documented public submodule. Imports from names beginning with an underscore are forbidden across distributions.

10. Production versus research

A module belongs in a published package only when all of the following are true:

  1. its runtime responsibility is stable and named;
  2. it is not tied to one benchmark fixture or one evidence package;
  3. its public inputs, outputs, rejection behavior, and identity behavior are defined;
  4. it has package-local tests independent of research fixtures;
  5. its dependencies are appropriate for the owning distribution;
  6. the project is willing to maintain it as a supported capability.

A module belongs under research/ when any of the following are true:

Moving a module to research does not diminish its scientific value. It clarifies that the module is evidence machinery rather than supported runtime API.

11. Package boundary manifest

Stage 1.0.13A will introduce a repository-root package-boundaries.toml as the machine-readable authority for package ownership and allowed dependencies.

The intended shape is:

schema_version = 1
release_version = "1.0.13"

[packages.core]
distribution = "zeromodel"
namespace = "zeromodel.core"
source_root = "packages/core/src"
depends_on = []

[packages.analysis]
distribution = "zeromodel-analysis"
namespace = "zeromodel.analysis"
source_root = "packages/analysis/src"
depends_on = ["core"]

[packages.observation]
distribution = "zeromodel-observation"
namespace = "zeromodel.observation"
source_root = "packages/observation/src"
depends_on = ["core"]

[packages.vision]
distribution = "zeromodel-vision"
namespace = "zeromodel.vision"
source_root = "packages/vision/src"
depends_on = ["core", "observation"]

[packages.video]
distribution = "zeromodel-video"
namespace = "zeromodel.video"
source_root = "packages/video/src"
depends_on = ["core", "observation"]

[packages.sqlalchemy]
distribution = "zeromodel-sqlalchemy"
namespace = "zeromodel.persistence.sqlalchemy"
source_root = "packages/sqlalchemy/src"
depends_on = ["core", "video"]

Architecture tooling must read this manifest. Package ownership and allowed edges must not be duplicated as unrelated hard-coded lists across scripts.

12. Versioning

All initial distributions use the synchronized version 1.0.13:

zeromodel                 1.0.13
zeromodel-analysis        1.0.13
zeromodel-observation     1.0.13
zeromodel-vision          1.0.13
zeromodel-video           1.0.13
zeromodel-sqlalchemy      1.0.13

Production package dependencies use exact synchronized pins for this release:

dependencies = [
    "zeromodel==1.0.13",
]

The release tooling must verify that:

Independent versioning is deferred until package boundaries and release cadence have proven stable.

13. Public API policy

Every package has a deliberately small __init__.py in its owned subtree.

For example:

packages/core/src/zeromodel/core/__init__.py
packages/video/src/zeromodel/video/__init__.py

These files may re-export public objects owned by that package. They must not re-export objects from optional sibling packages merely for convenience.

The namespace root has no initializer and no public exports.

Public API tests must enumerate the intended exports. Adding a new export is a deliberate API change, not an automatic consequence of creating a module.

14. Build and installation requirements

Each package must independently pass:

python -m build <package-directory>
python -m twine check <package-directory>/dist/*
install wheel into a clean virtual environment
pip check
import the package's public namespace
run package-local tests against the installed wheel

Tests that claim wheel isolation must not add the repository root or a package src directory to PYTHONPATH.

Every wheel must be inspected to confirm that it contains only its owned subtree. For example, the zeromodel-video wheel must not contain zeromodel/core, zeromodel/vision, or zeromodel/persistence files.

15. Test layers

The repository will use four explicit test layers.

15.1 Package unit tests

Located in each package’s tests/ directory. They test only the owning package and declared dependencies.

15.2 Package wheel tests

Build and install one wheel in a clean environment, then run import and behavior smoke tests against installed files.

15.3 Integration tests

Located under integration_tests/. They install the required package combination and test cross-package behavior such as:

15.4 Research tests

Located with the research system or in a clearly marked research test area. They may use benchmark fixtures and generated evidence but do not define the production package contract.

16. Import isolation requirements

At minimum, CI must prove:

import sys
import zeromodel.core

for forbidden in (
    "sqlalchemy",
    "torch",
    "transformers",
    "PIL",
    "zeromodel.analysis",
    "zeromodel.observation",
    "zeromodel.vision",
    "zeromodel.video",
    "zeromodel.persistence.sqlalchemy",
):
    assert forbidden not in sys.modules

Equivalent probes must verify that:

17. Architecture tooling

The existing architecture checker must evolve from one hard-coded source root to workspace discovery driven by package-boundaries.toml.

It must enforce:

The current quality ratchet remains in force. Package extraction is not permission to increase line ceilings or hide legacy debt under new paths.

18. CI requirements

The Python workflow must ultimately include:

  1. repository quality and architecture checks;
  2. package build matrix for all six distributions;
  3. clean-wheel import and pip check validation;
  4. Python 3.10, 3.11, and 3.12 package test coverage;
  5. integration combinations defined in section 15.3;
  6. Lua fixture validation if the Lua consumer remains supported;
  7. distribution-content inspection;
  8. synchronized-version verification.

Workflow path filters must include packages/**, research/**, integration_tests/**, package-boundaries.toml, and all workspace build scripts.

19. Staged implementation strategy

The package overhaul is implemented through an integration branch so main is not left in a partially extracted state.

main
  |
  +-- integration/package-system-1.0.13
          |
          +-- Stage A: workspace and core
          +-- Stage B: analysis
          +-- Stage C: observation contracts
          +-- Stage D: vision
          +-- Stage E: video
          +-- Stage F: SQLAlchemy
          +-- Stage G: research separation
          +-- Stage H: final integration and release readiness

Stage pull requests target the integration branch. The completed integration branch receives one final adversarial review and one final PR to main.

No package is published and no release tag is created from an intermediate stage. Temporary transitional source paths are permitted only on the integration branch, must be explicitly recorded, and must be eliminated before Stage H completes.

20. Stage definitions

Stage 1.0.13A — Workspace and core

Stage 1.0.13B — Analysis

Stage 1.0.13C — Observation

Stage 1.0.13D — Vision

Stage 1.0.13E — Video

Stage 1.0.13F — SQLAlchemy

Stage 1.0.13G — Research separation

Stage 1.0.13H — Final integration

21. Inventory gate

No production module moves before the repository inventory is reviewed.

The inventory must classify every current Python module as exactly one of:

A split classification must identify the responsibilities and target packages. An undecided classification blocks the extraction stage that would otherwise move the module.

The inventory must also record public exports, inbound and outbound imports, external dependencies, tests, CLI entry points, schema and digest ownership, and known architecture exceptions.

22. Definition of done

ZeroModel 1.0.13 package-system work is complete only when:

23. Architectural authority

When implementation convenience conflicts with this contract, the contract wins unless it is explicitly amended in the same reviewed change.

The inventory may refine module placement, but it may not silently change: