2.0.0: clean foundations#

Status: proposed · Base: 1.5.0

2.0.0 is the only release on this roadmap allowed to break things, and it breaks them on purpose and with a map. Three 1.x releases of features leave behind parallel ways of doing the same thing; 2.0 keeps the best one of each and makes it the only one. One space API, one clock, columns by default, typed scenarios, per-agent random streams, a stable C ABI and a checkpoint format that lasts. Every removal was deprecated in 1.5 at the latest, and modelly migrate --to 2.0 rewrites what can be rewritten. All on Windows, macOS and Linux (see Platforms).

Principles#

  1. No surprise breaks. Nothing is removed in 2.0 that did not warn in 1.5, naming the replacement.

  2. One way. Where 1.x grew two ways to do a thing, 2.0 keeps one.

  3. Same science. A model migrated to 2.0 gives statistically the same results as on 1.5; where the random streams change (per-agent streams), the migration guide says so and the agreement test (Welch, as in the playbooks) proves it.

  4. Faster everywhere. No playbook slower than 1.5 on any OS.

  5. Supported 1.x. 1.5 is a long-term-support line: it keeps receiving bug and security fixes after 2.0.0, so every user can migrate when their own work allows.

Epics#

H1 · Removals and the migration tool#

Goal: remove every deprecated name and make upgrading a command, not a project.

Work items: remove everything deprecated in 1.3 to 1.5; modelly migrate --to 2.0 (the codemod from modelly.migrate, extended to 1.x → 2.0 rewrites) with a dry run, a diff and a report of what needs a human; a migration guide with before/after for every removal; migration tested on every zoo and hub model.

Done when: every zoo model and the three community models migrate automatically, pass their validation tests, and agree with their 1.5 results.

Size: L

H2 · One space API#

Goal: grids, networks, continuous space and geographic space share one protocol: the same calls to place, move, query neighbours and iterate, whatever the geometry.

Design: a Space protocol (place, move, neighbors, within, positions as a column); discrete spaces keep cells, continuous and geographic spaces keep coordinates, both answer the same queries; property layers become fields (from 1.4 F6) on every space; old space classes kept as thin aliases through 2.x where they map cleanly.

Done when: every zoo model runs on the new protocol; a model can switch grid to network to continuous space by changing one line, verified by a tutorial.

Size: XL

H3 · Columns by default#

Goal: agent state lives in columns unless the model asks otherwise, so every model gets the 1.x column speed-ups without rewriting.

Design: typed attribute declarations (wealth: float = Column(0.0) or plain annotations) become columns automatically; attributes that cannot be columns (objects, lists) stay per-agent and are reported by modelly profile; DataCollector gathers columns without Python loops.

Done when: the classic playbook variants (per-agent code) run at least as fast as their 1.5 column variants after migration; no model loses an attribute in migration.

Size: L

H4 · One clock#

Goal: ticks and events on one scheduler with one documented ordering rule.

Design: steps are events at integer times; phases are priorities; tie-breaking is fully specified (time, priority, insertion order); the compiled scheduler from 1.4 is the only one; a schedule report shows what runs when.

Done when: every model with mixed ticks and events gives the same results as on 1.5 under the documented ordering; the ordering spec is a docs page with tests for each rule.

Size: M

H5 · Typed scenarios and configuration#

Goal: scenarios are typed, validated and loadable from files.

Design: Scenario as a dataclass_transform base (the default-type TODO in modelly/core/model.py that waits for Python 3.13); validation with clear errors (range, type, units); TOML and YAML loading; scenarios hashed into the manifest; sweeps over typed spaces.

Size: M

H6 · Per-agent random streams by default#

Goal: results independent of iteration order, partitioning and executor.

Design: opt-in in 1.4 (F1), default in 2.0; counter-based generators (Philox) keyed by run seed and agent id, shared by CPU and GPU; the model-level generators remain for model-level draws.

Done when: partition-independence holds for every space by default; agreement tests show the same distributions as 1.5 on every playbook.

Size: M · Depends on: 1.4 F1, F2

H7 · Stable ABI and native code#

Goal: one wheel per platform for every supported Python, and native code ready for every CPython build.

Design: the compiled modules move to the limited C API (abi3) where measurement shows no loss, keeping the version-specific build only where it matters; free-threaded builds are first-class; the private and unstable APIs left are inventoried and justified.

Done when: abi3 wheels for every row of the support matrix; no playbook slower than the version-specific build by more than 3%; a new CPython release installs on day one.

Size: M

H8 · Checkpoint and data formats v2#

Goal: a checkpoint written by 2.0 loads in every later 2.x release.

Design: a versioned, documented state format (columns as Arrow, structure as JSON, only user objects pickled); forward migrations between format versions; modelly checkpoint upgrade for 1.x files where the state maps; result stores and manifests versioned the same way.

Done when: a 2.0 checkpoint loads in a 2.1 test build; 1.5 checkpoints of every zoo model upgrade and resume with the same results.

Size: M

H9 · Python and platform baseline#

Work items: Python 3.13 minimum (3.12 dropped, as its own end of life approaches); a single test and release matrix covering every platform in the support table; installation verified on clean Windows, macOS and Linux machines with no compiler and no admin rights.

Size: S

H10 · Public API contract#

Work items: every public name listed in one place with its stability level (stable, provisional); the semantic-versioning promise written down; type-checked public API (strict); the plugin API v1 from 1.5 carried over unchanged.

Size: S

H11 · Documentation 2.0#

Work items: docs restructured around tasks (build, calibrate, scale, share, publish); every page tested (doctests and executed notebooks) on all three OSs; the migration guide and the “what is new in 2.0” tour; versioned docs keep /1.5/ as the LTS reference.

Size: M

Priorities#

Priority

Epics

Must

H1 Removals and migration, H2 One space API, H4 One clock, H8 Formats v2, H10 API contract

Should

H3 Columns by default, H5 Typed scenarios, H6 Per-agent streams, H11 Docs

Could

H7 abi3 (if measurement allows), H9 is required but small

Won’t

New features unrelated to the foundations; those go to 2.1

        flowchart LR
    F1["1.4 Distributed"] --> H6[H6 Per-agent streams]
    F2["1.4 GPU"] --> H6
    F6["1.4 Fields"] --> H2[H2 One space API]
    H2 --> H3[H3 Columns by default]
    H4[H4 One clock] --> H8[H8 Formats v2]
    H3 --> H8
    H5[H5 Typed scenarios] --> H8
    H8 --> H1[H1 Migration tool]
    H2 --> H1
    H4 --> H1
    H1 --> H11[H11 Docs 2.0]
    

Sprint plan#

2.0 has one more sprint than its features need: users migrate their models on the beta and report what the migration tool misses, and S7 fixes it.

Sprint

Goal

Main items

Exit

S1

Contract and clock

Public API inventory and stability levels; one scheduler with the ordering spec

Ordering spec tests pass on every example

S2

Space protocol

Space protocol; grids and networks on it

Grid and network zoo models pass on the protocol

S3

Columns and streams · a1

Continuous and geographic spaces on the protocol; columns by default; per-agent streams default

Playbooks agree with 1.5 (Welch)

S4

Formats and scenarios

Checkpoint and result formats v2; typed scenarios; Python 3.13 minimum

1.5 checkpoints upgrade and resume

S5

Migration tool

migrate --to 2.0 rewrites, report, guide; removals

Every zoo model migrates automatically

S6

Beta and abi3 · b1

abi3 builds measured; docs 2.0; call for migration testing

API frozen; hub models migrated

S7

Migration feedback · rc1

Fix what users’ migrations reveal

No open blocker

S8

Hardening · 2.0.0

Full matrix on all platforms; LTS branch 1.5.x; release notes

All gates pass

Release gates#

Release

Gate

2.0.0a1

Space protocol, one clock, columns by default and per-agent streams in; playbooks agree with 1.5

2.0.0b1

Every Must epic done; API frozen; every zoo and hub model migrated automatically

2.0.0rc1

No open blocker from user migrations

2.0.0

Determinism and agreement suites green on Windows, macOS and Linux; no playbook slower than 1.5 on any OS; LTS for 1.5 announced

Success metrics#

Metric

1.5.0

2.0.0 target

Ways to place and move an agent

one per space type

one

Schedulers

ticks plus events

one clock

Models migrated automatically

not applicable

every zoo and hub model

Checkpoint compatibility

same minor version

every later 2.x

Wheels per platform

one per Python version

one (abi3) where measured equal

Slowest playbook versus 1.5

not applicable

not slower on any OS

Risks#

Risk

Likelihood

Impact

Mitigation

Migration breaks user models silently

Medium

High

Agreement tests in the migration report; dry run by default; LTS for 1.5

The space protocol cannot express a space well

Medium

High

Prototype in S2 on all four space types before committing; keep thin aliases

Per-agent streams change results users have published

High

Medium

Documented in the guide; the 1.5 LTS reproduces old results; agreement tests prove the distributions match

abi3 is slower

Medium

Low

Keep version-specific wheels where measured slower

Too many changes at once

High

High

Won’t list strictly enforced: no new features in 2.0

Open questions#

  • [ ] Python 3.13 or 3.14 as the 2.0 minimum?

  • [ ] Do the old space classes stay as aliases through 2.x, or go in 2.1?

  • [ ] When does 1.5 LTS end: when 2.1 ships, or when the hub’s models have all migrated?

Sprint review log#

Sprint

Shipped

Slipped

Notes

S1

S2

S3

S4

S5

S6

S7

S8