Metadata-Version: 2.5
Name: kamino-lme
Version: 0.0.1
Summary: Versioned Gaussian linear mixed-model compatibility for Python
Project-URL: Homepage, https://github.com/joshuamyers22/kamino
Project-URL: Issues, https://github.com/joshuamyers22/kamino/issues
Project-URL: Repository, https://github.com/joshuamyers22/kamino
Project-URL: Changelog, https://github.com/joshuamyers22/kamino/blob/main/CHANGELOG.md
Project-URL: Documentation, https://github.com/joshuamyers22/kamino#readme
Project-URL: Security, https://github.com/joshuamyers22/kamino/security/policy
Author: Joshua Myers
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 2 - Pre-Alpha
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Requires-Python: >=3.11
Requires-Dist: formulae==0.5.4
Requires-Dist: numpy<3,>=1.26
Requires-Dist: pandas<4,>=2.2
Requires-Dist: scipy<2,>=1.12
Requires-Dist: threadpoolctl<4,>=3.5
Provides-Extra: postfit-statsmodels
Requires-Dist: statsmodels==0.14.6; extra == 'postfit-statsmodels'
Description-Content-Type: text/markdown

# Kamino

Native Python Gaussian linear mixed models with a versioned, tested subset of
lme4 compatibility.

Install the `kamino-lme` distribution; the Python import remains `kamino`:

```console
python -m pip install kamino-lme
```

Status: release-hardening pre-alpha; Phase 1, N03, F02, I01, I02, I03, A01,
A02, and E02 are complete. The public
vertical slice fits a Gaussian model with one grouping
structure and either a random intercept, a correlated numeric
random intercept/slope, or independent numeric intercept and slope terms, using
ML or REML and the owned block backend. The formula path uses one shared model
frame, stores group membership plus small row-level covariates, and never
constructs a dense random-effects indicator matrix. Numeric and categorical
fixed effects, treatment/sum contrasts, one pairwise `*` expansion, weights,
additive offsets, subsets, and explicit missing-row handling are covered by
pinned lme4 2.0-6 outputs. Ordinary nested or crossed random-intercept terms use
the coupled sparse backend and are verified on Pastes, Penicillin, and InstEval.
Ordinary categorical random slopes and rank-deficient fixed effects have pinned
fit, prediction, and estimability evidence.

```python
from kamino import lmer

fit = lmer(
    "yield_value ~ 1 + (1 | batch)",
    {
        "yield_value": [1.0, 1.2, 0.8, 3.0, 3.1, 2.9],
        "batch": ["a", "a", "a", "b", "b", "b"],
    },
    reml=True,
)
conditional = fit.predict(mode="conditional")
population = fit.predict(
    {"batch": ["a", "unseen"]},
    mode="population",
)

fit.save("yield-model.kamino")

from kamino import load_model_bundle

saved_model = load_model_bundle("yield-model.kamino")
saved_prediction = saved_model.predict(
    {"batch": ["a", "unseen"]},
    mode="conditional",
    allow_new_groups=True,
)

# sleepstudy_data is a pandas DataFrame with these three columns.
slope_fit = lmer(
    "reaction ~ days + (1 + days | subject)",
    sleepstudy_data,
    reml=True,
)

independent_fit = lmer(
    "reaction ~ days + (1 + days || subject)",
    sleepstudy_data,
    reml=False,
)

crossed_fit = lmer(
    "diameter ~ 1 + (1 | plate) + (1 | sample)",
    penicillin_data,
    reml=True,
)

nested_fit = lmer(
    "strength ~ 1 + (1 | batch/cask)",
    pastes_data,
    reml=False,
)

# Treatment coding is the default; use "sum" explicitly when required.
categorical_fit = lmer(
    "y ~ x * treatment + offset(exposure) + (1 | site)",
    model_data,
    weights=prior_weights,
    offset=argument_offset,
    contrasts={"treatment": "sum"},
    subset=analysis_rows,  # one Boolean per original row
    na_action="omit",  # or the fail-closed default, "error"
)

categorical_random_fit = lmer(
    "y ~ treatment + (1 + treatment | site)",
    model_data,
    contrasts={"treatment": "sum"},
    random_contrasts={"treatment": "sum"},
)

# Simulation mode is explicit; streams do not depend on worker order.
draws = fit.simulate(100, seed=20260915, mode="unconditional")

# The optional private ledger stores responses and outcomes for safe resume.
bootstrap = fit.parametric_bootstrap(
    1000,
    seed=20260916,
    workers=4,
    ledger_path="private-bootstrap-ledger",
)
failure_evidence = bootstrap.failure_accounting()
descriptive_interval = bootstrap.interval(method="percentile")

# Full (theta, sigma) derivatives; inference fails closed at boundaries.
satterthwaite = slope_fit.satterthwaite()
slope_test = satterthwaite.test([0.0, 1.0])
fixed_effects_test = satterthwaite.joint_test([[1.0, 0.0], [0.0, 1.0]])

# KR uses REML; an ML source fit is refitted separately and records provenance.
kr = slope_fit.kenward_roger()
kr_slope = kr.test([0.0, 1.0])
kr_fixed_effects = kr.test([[1.0, 0.0], [0.0, 1.0]])

# Profiles always use an ML baseline and reoptimize nuisance parameters.
profiles = slope_fit.profile(targets=[".sig01", ".sig02", ".sig03", ".sigma", "Days"])
slope_profile_interval = profiles.interval("Days", level=0.95)

# Postfit locks coefficient identity, covariance, and DF into one analysis.
postfit = slope_fit.postfit(inference="satterthwaite", data=sleepstudy_data)
slope_row = postfit.tidy()[1]

# Reference grids require the model-frame predictors because live Kamino fits
# deliberately do not retain caller data.
marginal_means = categorical_fit.postfit(data=model_data).reference_grid(
    specs=["treatment"],
    weights="cells",
)
pairwise = marginal_means.pairwise(adjustment="holm")

# CR2 uses marginal residuals and the fitted marginal covariance target.
cr2 = slope_fit.cluster_robust("Subject", covariance_type="CR2")
robust_slope = cr2.test([0.0, 1.0])
robust_fixed_effects = cr2.test([[1.0, 0.0], [0.0, 1.0]])
```

The accepted fixed side contains an intercept, additive numeric/categorical
identifiers, distinct pairwise `a * b` expansion, and `offset(name)`. The random
side is one intercept, one correlated numeric/categorical intercept/slope, or
equivalent independent numeric intercept/slope terms sharing one group. A
random-slope predictor must also be a supported fixed effect. Multiple grouping
structures accept random intercepts and ordinary categorical slopes; nested slash
syntax expands with lme4-compatible term and level ordering. Prediction
mode is explicit; conditional prediction rejects unseen groups unless
`allow_new_groups=True`. Safe prediction-only model bundles are supported;
training rows and responses are deliberately not stored, so reloading does not
support refitting or training prediction. Bundles for nested/crossed,
rank-deficient, and categorical-random fits remain fail-closed until the Phase 2
artifact-recovery schema milestone. Live fitted results support deterministic
conditional/unconditional simulation, exact response refitting, and retained-
fixed-effect parametric bootstrap with a resumable private ledger. Prediction-
only bundles still cannot refit, bootstrap, or run derivative inference.
Satterthwaite one- and multi-DF tests are available from regular live fits and
were calibrated only in the declared Gaussian random-intercept regime;
boundaries and unstable derivatives return unavailable. Percentile/basic
bootstrap intervals remain descriptive. Kenward–Roger adjusted covariance and
scaled F tests are available for regular unit-weight fits within an explicit
dense-memory ceiling; weighted and boundary cases fail closed. Named ML
likelihood profiles cover SD/correlation, residual scale, and retained fixed
coefficients with nuisance reoptimization and explicit endpoint status.
Live fits also expose bounded postfit contrasts, tidy coefficient inference,
reference grids with explicit weighting/offset semantics, and row-averaged
variance decomposition. Satterthwaite and Kenward–Roger keep their own
contrast-specific DF and covariance contracts. Install
`kamino[postfit-statsmodels]` for explicit statsmodels 0.14.6 OLS/WLS and
MixedLM adapters; statsmodels is not a core dependency. Robust OLS/WLS
covariance uses asymptotic inference rather than inheriting residual DF.
Live unit-weight Kamino fits support CR0/CR1 and fitted-target CR2 when every
random grouping factor is nested in the declared independent clusters. CR2
uses contrast-specific Satterthwaite and HTZ joint inference; weighted and
non-nested cluster structures fail closed. Tukey/multivariate-t adjustments
and a direct marginaleffects adapter remain
unsupported and fail closed or are absent.
Categorical double-bar expansion, numeric random slopes across
different grouping factors, transforms, and refit bundles remain unavailable. The
lower-level fixed-theta array API remains available for numerical development.

- [Production design and implementation plan](PROJECT_PLAN.md)
- [Compatibility contract](docs/COMPATIBILITY.md)
- [Dyestuff ML/REML and prediction evidence](docs/evidence/phase1-dyestuff.md)
- [Dyestuff2 block-boundary evidence](docs/evidence/phase1-dyestuff2-block.md)
- [Sleepstudy correlated-slope evidence](docs/evidence/phase1-sleepstudy.md)
- [Sleepstudy independent-term evidence](docs/evidence/phase1-independent-terms.md)
- [Shared model-frame and fixed-effect evidence](docs/evidence/phase1-model-frame.md)
- [Safe model bundles](docs/MODEL_BUNDLES.md)
- [Million-row single-group resource evidence](docs/evidence/phase1-single-group-resource.md)
- [General sparse nested/crossed evidence](docs/evidence/phase2-general-sparse.md)
- [Rank, estimability, and categorical random-term evidence](docs/evidence/phase2-f02-rank-categorical.md)
- [Parametric-bootstrap and refit-ledger evidence](docs/evidence/phase3-i01-bootstrap.md)
- [Satterthwaite derivative and calibration evidence](docs/evidence/phase4-i02-satterthwaite.md)
- [Kenward–Roger and likelihood-profile evidence](docs/evidence/phase4-i03-kr-profile.md)
- [Postfit capability evidence](docs/evidence/phase5-a01-postfit.md)
- [Cluster-robust CR2 evidence](docs/evidence/phase5-a02-cluster-robust.md)
- [Threat model](docs/THREAT_MODEL.md)
- [Privacy and data handling](PRIVACY.md)
- [Support policy](SUPPORT.md)
- [Release-readiness checklist](checklists/RELEASE_READINESS.md)
- [E02 production-hardening evidence](docs/evidence/release-e02-production-hardening.md)
- [Phase 0 production-readiness record](PRODUCTION_READINESS.md)
- [Third-party notices](THIRD_PARTY_NOTICES.md)
- [Pinned R oracle](oracle/README.md)
- [MIT license](LICENSE)
- [Original design, preserved for review history](docs/archive/lmerx-design.before-production-revision-2026-09-14.md)

The project and planned Python package are named `kamino` (formerly `lmerx`).
The plan applies the production-project-template baseline and defines statistical
fidelity, implementation milestones, and release evidence requirements.

For development, install the frozen environment with `make setup`, run the
offline gate with `make check`, and verify the built wheel with
`make wheel-smoke`. `make supply-chain` validates both distributions and emits
core/all-extra CycloneDX SBOMs, checksums, and a source manifest under the
ignored `build/release/` directory. Docker is required only for `make oracle`.
