Migration
→ v1.15
v1.15 is the general-first re-layering release. The venue-free core dataset() becomes an alignment engine with an explicit label axis; the prediction-market surfaces (Kalshi, Polymarket) become thin delegators on top of it. Your existing calls keep working — the default dataset() / research() output is byte-identical to 1.14.0 — but two deprecation trains start and one future default is announced. This page is ordered by what you need to act on first.
The one-page kwarg contract behind all of this lives in Source identity; the full dataset() walkthrough is the Research API guide.
1. The FutureWarning you will see first (D-22)
Section titled “1. The FutureWarning you will see first (D-22)”If you call dataset() without an explicit label=, you now get a one-time FutureWarning:
dataset() label default changes from 'cli' to None in 2.0; pass label='cli' to keep settlement labels or label=None to silence
Your data has not changed. dataset() with no label still returns the cli_* settlement columns byte-identically this release. The warning is an early notice that the default label flips to None (features-only) at 2.0, after a ≥2-minor bridge window. Silence it by saying what you mean:
# Keep today's behavior (settlement labels) — no warning.df = mostlyright.dataset("KNYC", "2025-01-06", "2025-01-12", label="cli")
# Opt in to the 2.0 default now (no label columns) — no warning.df = mostlyright.dataset("KNYC", "2025-01-06", "2025-01-12", label=None)import { dataset } from "mostlyright";
// Keep today's behavior (settlement labels) — no warning.const settled = await dataset("KNYC", "2025-01-06", "2025-01-12", { label: "cli" });
// Opt in to the 2.0 default now (features-only) — no warning.const features = await dataset("KNYC", "2025-01-06", "2025-01-12", { label: null });The bridge timeline
Section titled “The bridge timeline”| Release | dataset() with no label= | Warning | research() with no label= |
|---|---|---|---|
| 1.15 (now) | returns cli_* (byte-identical) | FutureWarning (once) | returns cli_*, never warns |
| 1.16 … 1.x | returns cli_* (byte-identical) | FutureWarning (once) | returns cli_*, never warns |
| 2.0 | default flips to label=None | — (default is now explicit) | (legacy alias retires at 2.0) |
research() is the legacy name — it keeps the implicit cli label forever with no new warning, because it retires at 2.0 anyway and there is nothing to migrate toward. If you want the settlement labels indefinitely, either keep calling research() or pass dataset(..., label="cli").
If you run -W error (opt-in)
Section titled “If you run -W error (opt-in)”Mostly Right’s own CI and test suites do not run Python with warnings-as-errors. The D-22 FutureWarning is purely a user-facing, opt-in concern. If you run your code under python -W error — or set filterwarnings = error in your pytest config — a bare dataset() call will raise instead of warn. The fix is the same one-liner: pass an explicit label="cli" or label=None.
Python vs TypeScript: how often the D-22 warning fires
Section titled “Python vs TypeScript: how often the D-22 warning fires”The Python and TypeScript SDKs emit this warning with deliberately different dedup granularity, matching each language’s idiomatic warning model — an intended divergence, not a bug:
- Python routes the warning through the stdlib
warningsmodule, whose default filter dedupes per call-site (module + lineno) per process. A baredataset()warns once per distinct call-site. - TypeScript has no per-call-site warnings registry, so the SDK uses a single process-wide latch (
console.warnfired at most once, resettable in tests via_resetDefaultLabelWarning()). The first baredataset()(or an omitted-labeldatasetPanel()) warns once for the whole process.
Both models guarantee the warning is never per-row and never per-station, and both are silenced identically by passing an explicit label. If you consume both SDKs, do not rely on the count of warnings being equal — rely only on “a bare default warns, an explicit label does not.”
2. include_* flags → features=[...]
Section titled “2. include_* flags → features=[...]”The four accreting include_* flags are now deprecated aliases of the dataset(features=[...]) selector. They still work this release, byte-identically, for at least two more minors — each True flag emits a DeprecationWarning.
| Old (deprecated) | New | Feature name |
|---|---|---|
dataset(..., include_forecast=True) | dataset(..., features=["forecasts"]) | "forecasts" |
dataset(..., include_satellite=True) | dataset(..., features=["satellite"]) | "satellite" |
dataset(..., include_cwop=True) | dataset(..., features=["cwop"]) | "cwop" |
dataset(..., include_trades=True) | dataset(..., features=["trades"]) | "trades" |
# Beforedf = mostlyright.dataset("KNYC", "2025-01-06", "2025-01-12", label="cli", include_forecast=True, include_satellite=True)
# After — byte-identical outputdf = mostlyright.dataset("KNYC", "2025-01-06", "2025-01-12", label="cli", features=["forecasts", "satellite"])features=[] (or omitting it entirely) composes exactly the built-in columns it always did — the parity fixtures are untouched. You can pass both forms during migration; they merge (order-stable, de-duplicated). Registering your own feature block goes through the public-experimental contributor registry — see Extending dataset().
3. contract= / include_trades= → the markets layer
Section titled “3. contract= / include_trades= → the markets layer”Venue knowledge is leaving the core. Passing contract= / contracts= or include_trades= to the core dataset() now emits a DeprecationWarning pointing at the thin markets delegators — behavior is byte-identical below the warning (the existing validation/raise is unchanged).
Old (deprecated on core dataset()) | New (thin markets sugar) |
|---|---|
dataset(contract=..., ...) | markets.kalshi.dataset(ticker, ...) |
dataset(contracts=[...], ...) | markets.kalshi.dataset(ticker, ...) per ticker |
dataset(include_trades=True, ...) | the venue’s trade timeseries lives in the markets layer (markets.kalshi / markets.polymarket) |
from mostlyright.markets import kalshi, polymarket
# Kalshi settles on NWS CLI → the delegator routes to label="cli".k = kalshi.dataset("KXHIGHNY-25MAY26-T79", "2025-05-26", "2025-05-26", outcome=True)
# Polymarket settles on WU/NOAA-WRH extremes → routes to label="daily_extremes".p = polymarket.dataset("<event_id>", "2025-05-26", "2025-05-26", outcome=True)import { kalshi, polymarket } from "mostlyright/markets-dataset";
// Kalshi settles on NWS CLI → routes to label: "cli".const k = await kalshi.dataset("KXHIGHNY-25MAY26-T79", "2025-05-26", "2025-05-26", { outcome: true,});
// Polymarket resolution is server-side — supply the resolved station.const p = await polymarket.dataset("<event_id>", "2025-05-26", "2025-05-26", { station: "KNYC", strikeText: "above 79F", outcome: true,});The delegators own all venue knowledge — station resolution, label-source routing (Kalshi → cli, Polymarket → daily_extremes), strike parsing, and the outcome=True binary settlement target — and forward the join to the venue-free core with zero duplicated join logic. Settlement comparison is inclusive (>= threshold, both range endpoints), matching the “N° or above” contract wording. See the Markets guide.
4. New this release (opt-in, no migration needed)
Section titled “4. New this release (opt-in, no migration needed)”dataset(label=...)— the label axis. Named recipes ("cli","daily_extremes"),None(features-only, works worldwide with no market), or a bring-your-own label DataFrame aligned by the SDK. See Choosing the label.dataset(stations=[...])— multi-station panels. Long-format, per-station settlement calendars, mixed-venue OK. See Extending dataset().- The contributor registry (
mostlyright.experimental, public-experimental, D-24) — register your own feature block behind the unconditional labels-only firewall. See Extending dataset(). - The fetch-provenance ledger (D-25) — ships dark this release: an append-only audit sidecar of re-fetchable cache writes, readable via
mostlyright.provenance.history(...), seeding a futurereconcile(). Python-only for now; no user-facing surface to configure.
5. The retrain-event reminder (unchanged rule, worth repeating)
Section titled “5. The retrain-event reminder (unchanged rule, worth repeating)”Pinning source= on a domain table (e.g. obs(..., source="awc")) returns a different row composition than the fused default — it is a retrain event, not a find-replace. This rule is unchanged from prior releases; the general-first re-layering does not alter it. The full statement lives in Source identity.
TypeScript notes
Section titled “TypeScript notes”The TS SDK reaches parity with the landed Python general-first re-layering this release (1.15.0), with three things to know:
- Subpath imports for the new surface. Only the label axis lands on the size-budgeted
mostlyrightroot barrel. The registry, panels, and markets delegators ship behind lean subpaths —mostlyright/experimental,mostlyright/panels, andmostlyright/markets-dataset— with the pure strike parsers in@mostlyrightmd/markets. Import from the subpath, not the root, for those. - The
research/datasetalias split.researchanddatasetwere object-identical (export { research as dataset }); D-22 requires divergent default-label warning behavior, so they are now distinct thin wrappers over one shared body. Both keep the full overloaded signature — the only observable difference is thatdataset()warns once on an omitted label andresearch()never does. - The warn latch. The D-22
FutureWarningand theExperimentalFeatureWarningfire once per process via a module-level latch (console.warn), matching the Python once-per-session behavior. Test hooks reset the latch. - The provenance ledger is N/A in TS (server-side only) — no TS parquet cache, no browser filesystem, no TS
reconcile().
Compatibility summary
Section titled “Compatibility summary”| Surface | 1.15.0 behavior |
|---|---|
dataset() / research() default (no explicit label) | byte-identical cli_* output; dataset() emits a one-time FutureWarning (D-22), research() never |
dataset(features=[]) / omitted | byte-identical to 1.14.0 (parity fixtures untouched) |
include_forecast/satellite/cwop/trades= | deprecated aliases of features=[...] (byte-identical, ≥2 minors) |
dataset(contract=/contracts=/include_trades=) | deprecated → markets layer (byte-identical below the warning) |
dataset(label=...), dataset(stations=[...]), contributor registry, provenance.history() | new, opt-in |
See also
Section titled “See also”- Choosing the label —
label="cli"vs"daily_extremes"vsNonevs BYO. - Markets guide — the thin
kalshi.dataset/polymarket.datasetdelegators +outcome=True. - Extending dataset() — station panels + the experimental contributor registry.
- Source identity — the
source=/delivery=/ grain contract. - Changelog — the complete change list for v1.15.