Skip to content

🇬🇧 English · 🇪🇸 Español

puremacro — Path to 1.0

This document declares what shipping puremacro 1.0 means, the policy that activates at 1.0, and the concrete gates the maintainer commits to satisfying before tagging it. It is editable; revisions in future pre-1.0 releases are allowed. The doc declares intent, not contract.


1. What 1.0 means

1.0 is the point at which the public API stops renaming freely. The current pre-1.0 convention from README.md — "APIs rename freely with consumers updated in the same commit" — ends at 1.0. After 1.0, every public-symbol rename or removal goes through a deprecation cycle (§ 2).

The public API is the set of symbols listed in tests/fixtures/public_api_snapshot.json at the tag of 1.0. Anything not in that snapshot is implementation detail and may change without notice. Subpackages explicitly excluded from the 1.0 promise are listed in § 5.

The point of cutting 1.0 is not "the package is finished" — it is "users can depend on this surface across minor releases." Pre-1.0 freedom to rename is incompatible with that dependability.

2. Deprecation policy (active at 1.0)

A public symbol marked for removal stays callable for one minor release with a DeprecationWarning. Example: puremacro.lp.foo deprecated in 1.3.0 → still importable in 1.3.X (with warning) → removed in 1.4.0.

The warning text must name: 1. The deprecated symbol's fully-qualified path (puremacro.lp.foo, not just foo). 2. The version of removal (1.4.0). 3. The canonical replacement, or "no replacement; opening issue X" if none is planned.

Behavioural changes to existing symbols that change return shape or argument semantics require a major bump (1.X → 2.0), with deprecation of the old form in the prior 1.X release.

Internal refactors that don't change the public-API snapshot or behaviour are patch releases (1.X.Y → 1.X.Y+1).

The boundaries between minor, major, and patch are enforced by Gate 3 (public-API snapshot) and the maintainer's judgment on "is this a behaviour change" — there is no automated behaviour-equivalence check.

3. API freeze contract

tests/fixtures/public_api_snapshot.json is the source of truth for "public API". The fixture tracks:

  • all: __all__ exports per subpackage. Every puremacro.X.symbol reachable from puremacro/__init__.py's import graph with symbol in puremacro.X.__all__.
  • result_classes: dataclass field names for every frozen-dataclass result type returned by a public estimator. The field names are the API; the field types and values are not part of the snapshot.

The fixture explicitly does NOT track: - Docstrings (revisable any time). - Internal modules (_*.py, e.g. puremacro.lp._garch_utils). - puremacro.teaching.* (excluded by Gate 2's puremacro.teaching skip). - puremacro.examples.* (not part of the wheel surface). - Function bodies and behaviour. - Helper / non-__all__ symbols inside public modules.

At 1.0, Gate 3 becomes a stability gate, not a "diff against the prior release" gate. Any diff is a deliberate maintainer action; the snapshot file is the source of truth. Regenerating the snapshot outside of a deprecation cycle is a policy violation.

4. Gates to 1.0

Concrete checklist. The maintainer commits to all of these being satisfied before tagging 1.0:

  • [ ] tests/known_failures.json::entries empty for three consecutive non-patch releases. (Patches roll over the counter; minors reset it.)
  • [x] Real Pyodide CI green. Shipped at 0.49.0 as Gate 6 in tools/release_check.py (opt-in via --pyodide). Boots Pyodide via Node, installs the freshly-built wheel via micropip, runs pytest -m pyodide_smoke (8 curated tests across 7 subpackages). At 1.0 this becomes mandatory (not opt-in).
  • [x] PyPI publishing path proven. Shipped 2026-07-19: puremacro 0.92.0 uploaded to test.pypi.org (https://test.pypi.org/project/puremacro/0.92.0/) from the standalone-repo build, and verified end-to-end — pip install from test.pypi in a clean venv returned a working CholeskySVARResult from the quickstart estimator. Production PyPI is planned via trusted publishing (release.yml in the standalone repo), replacing the deferred tools/release_publish.py spec.
  • [ ] All examples under puremacro/examples/*.py carry status PASS or SKIP in docs/examples_gallery.json. Zero FAIL.
  • [ ] At least one external user has installed puremacro from a release artifact (wheel or sdist) and used it successfully. "External" means not the maintainer; "successfully" means at least one estimator returned the expected result class on the user's machine. This is judgement-call evidence, not a CI check.
  • [ ] ARCHITECTURE.md refreshed within the last release cycle. "Refreshed" = the module map matches the actual directory tree with no missing or stale entries.
  • [ ] A complete RELEASING.md covering the full release procedure (currently only CONTRIBUTING.md "Before tagging" partially covers this).

When all seven boxes are ticked, the maintainer may tag 1.0. Until then, the package stays pre-1.0 by default.

5. Scope at 1.0 vs experimental

Three categories:

1.0-blessed (stable API at 1.0)

The following subpackages and their public-API snapshot entries are stable at 1.0. Any rename / removal / behaviour change requires the deprecation cycle in § 2.

  • puremacro.var.* (excluding var/regime/* and var/gvar)
  • puremacro.lp.* (excluding lp/_garch_utils)
  • puremacro.inference.*
  • puremacro.var.identify.*
  • puremacro.dsge.klein (the QZ solver after 0.47.0 hardening)
  • puremacro.volatility.*
  • puremacro.cycles, puremacro.cointegration_modern, puremacro.factor, puremacro.korv_gmm, puremacro.midas, puremacro.spectral, puremacro.synthetic_control, puremacro.wavelet, puremacro.realized_vol, puremacro.labor_share

Research-experimental (out of the 1.0 promise)

These modules ship at 1.0 but their APIs may evolve in 1.X minor releases without the deprecation cycle. Document them with a top-of- module banner indicating their experimental status.

  • puremacro.dsge.smets_wouters — replication-grade Pfeifer port; may evolve as SW07 estimation lands (the P1 spec).
  • puremacro.dsge.gensys — brand-new at 0.45.0; needs at least one more user before the API is locked.
  • puremacro.narrative.* — schemas may still evolve as the LUI/LWUI work matures.
  • puremacro.uncertainty.* — early stage.
  • puremacro.models.* — research models tied to specific papers (DMP regime-dependent, etc.); paper revisions may force API changes.
  • puremacro.var.regime.* — regime-switching VARs are research- experimental.
  • puremacro.var.gvar — brand-new at 2.5.0; needs at least one more user before the API is locked.
  • puremacro.causal.* (dml_plr, DoubleMLPLR, DMLResult, the lasso / ridge learners) — inside 1.0, outside the 1.0 promise. Brand-new at 3.4.0; it ships and is covered by the release gate's test and API-snapshot checks, but the surface may still move in a 1.X minor. There is no elastic-net learner and the shipped learners are linear in the supplied columns of X, so a basis expansion or a custom learner= may change what the signature has to carry.
  • puremacro.vfi.*, including hjb_achdou (solve_hjb_achdou, solve_kfe_achdou, solve_aiyagari_continuous_hjb) — the continuous-time solvers reached their current shape at 3.4.0.
  • puremacro.spatial.* — the spatial-econometrics modules (spatial.weights, spatial.models, spatial.panel, spatial.lp) date to 2.4.0-2.5.0; the quantitative GE solver spatial.allen_arkolakis landed at 3.3.0 and was extended at 3.4.0 with the backend= keyword.
  • puremacro.dsge.occbin — solve_multiconstraint_occbin shipped at 2.8.0 and was hardened at 3.4.0 (regime splice, convergence reporting, argument validation).
  • Any smm.* subpackage that lands by 1.0.

Side-channel (out of the Pyodide promise + the 1.0 promise)

  • puremacro.teaching.* — intentionally wraps statsmodels / linearmodels / arch for MATLAB-parity comparisons. Documented as a teaching artifact, not a research-API surface.
  • puremacro.fetch.* — depends on external HTTP services that can change schemas independently of puremacro's release cycle. The fetch surface is best-effort.
  • puremacro.fetch.realtime.{banxico, inegi, bcb, bcch} — best-effort, like the rest of puremacro.fetch.*: four national APIs that can change endpoint, schema or authentication independently of this package's release cycle. The schema canary and the local snapshot cache exist precisely because that surface is not under our control.
  • puremacro.bartik.*, puremacro.instruments.*, the data-pipeline builders (build_panel, build_subnational_panel) — pragmatically stable, but the surfaces are tied to research workflows that may change. Treat as research-experimental for 1.0 unless explicitly promoted.

This document is updated each pre-1.0 release. When 1.0 ships, the relevant items here move into permanent project policy (likely a POLICY.md or expanded CONTRIBUTING.md).