Skip to content

fix: research_by_source window trim + wire research(source=) pin — dual-SDK, v1.12.0#108

Merged
helloiamvu merged 4 commits into
mainfrom
fix/mode2-window-trim-and-source-pin
Jul 8, 2026
Merged

fix: research_by_source window trim + wire research(source=) pin — dual-SDK, v1.12.0#108
helloiamvu merged 4 commits into
mainfrom
fix/mode2-window-trim-and-source-pin

Conversation

@helloiamvu

Copy link
Copy Markdown
Member

What

Two coupled fixes shipped in lockstep across both SDKs, plus the 1.12.0 release bump:

  1. mode2.research_by_source window leak (bug). It returned whole calendar months instead of the requested window — a KNYC Jan 6–12 query returned all 865 January rows; Jan 28–Feb 3 returned two full months. Triple-verified empirically (fresh-cache live run, sockets-blocked seeded-cache run, static path audit; 6-agent adversarial pass found zero evidence the behavior was intended — the TS port already shipped the correct strict filter). Rows are now trimmed to [from_date, to_date] by UTC date-part, inclusive, matching TS exactly. Every return shape fixed.
  2. research(source=...) single-source pin (feature). Functional in both SDKs (was NotImplementedError): pre-fetch validation against the 7-name Mode 2 vocabulary, post-merge alias-set filter before daily aggregation, cli_* untouched, df.attrs["source"] provenance, sources= (plural) stays v0.3 with a corrected message.

TS Parity

Identical API, shipped in this same PR (no parity ticket needed). packages-ts/meta: research({source}) wired with byte-identical vocabulary/alias tables (RESEARCH_SOURCE_ALIASES ≡ Python _SOURCE_ALIASES, verified entry-by-entry), same pre-fetch error shape, same post-merge filter placement; source: null follows the Phase 21 null-as-absent wire contract. mode2 window-boundary tests added for iem.archive + awc.live.

Parity firewall

source=None default path is byte-identical: every new statement is gated behind source is not None; full fast suite incl. tests/test_parity.py green (×3 runs: implementer, architect, pre-push hook); golden assert_frame_equal no-op test included. No merge-logic files touched.

Review loop (two-reviewer discipline)

  • Codex (codex review, high effort): GATE PASS — 1 P2 (TS source: null treated as present, violating the Phase 21 present() wire contract) → fixed in this PR + regression test.
  • Python/TS Architect (Opus): merge-ready, no P1/P2 — independently re-proved the parity firewall, alias-table equality, and observed_at string-schema safety. 6 P3 nits deferred.

Deferred follow-ups (P3s + stale __version__ + weather bundle growth): #107

Release

All 7 packages bumped 1.11.0 → 1.12.0 in lockstep (3 PyPI dists, 4 npm packages). Weather TS size-limit 25 → 26 KB — bundle was already 25.88 KB on main (pre-existing growth, this PR touches only meta; tracked in #107). pnpm run size green. Post-merge: tag v1.12.0 (PyPI trusted publishing) + vts-1.12.0 (npm OIDC).

Gates

  • Python fast suite incl. parity fixtures: ✅ (exit 0, ~4,500 tests)
  • TS: vitest ✅ (89/89 affected + full meta suite), tsc --noEmit ✅, pnpm run build ✅, biome ✅ (no new)
  • size-limit: ✅

🤖 Generated with Claude Code

minereda and others added 3 commits July 8, 2026 14:59
mode2.research_by_source returned whole calendar months (the month-granular
parquet cache flows through _fetch_observations_range unfiltered): a KNYC
Jan 6-12 query returned all 865 January rows; a Jan 28-Feb 3 query returned
two full months. Silent out-of-window leakage into backtest frames.

Rows are now trimmed to [from_date, to_date] by UTC date-part, inclusive,
matching the TS port's shipped filter (packages-ts/meta/src/mode2.ts) for
cross-SDK lockstep. The +1-day fetch extension remains fetch-width only.
Fixes every return shape (DataFrame, as_dataframe=False, wrapper/backends).
TS side adds the missing window-boundary tests for iem.archive + awc.live.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The singular source= kwarg is now functional (was NotImplementedError since
Phase 10): validated pre-fetch against the Mode 2 vocabulary (7 names,
byte-identical alias tables across SDKs — Python _SOURCE_ALIASES, TS
RESEARCH_SOURCE_ALIASES), then applied as a post-merge row subset before
daily obs_* aggregation. cli_* settlement columns unaffected; pinned
DataFrames carry df.attrs["source"]. sources=[...] (plural subset) stays
v0.3 with a corrected error message. source=None default path is
byte-identical (parity gate green). TS source: null follows the Phase 21
null-as-absent wire contract (codex P2, regression-tested).

Inherited v0.1 limitation documented: the AWC > IEM > GHCNh merge runs
before the pin filter, so pinning a lower-priority source yields only the
rows the merge did not supersede.

Review: codex GATE PASS (1 P2, fixed) + architect merge-ready (no P1/P2).
P3 follow-ups: #107

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… 26 KB

All Python dists (mostlyrightmd, -weather, -markets) and TS packages
(@mostlyrightmd/core|weather|markets, mostlyright meta) 1.11.0 -> 1.12.0
in lockstep. Weather TS size-limit 25 -> 26 KB: the bundle was already
25.88 KB on main (877 B over, pre-existing — this PR touches only meta);
growth investigation tracked in #107.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

Docs-required check: PASS

API-surface change includes docs updates — no reminder needed.

API-surface files changed:

packages-ts/meta/src/mode2.ts
packages-ts/meta/src/research.ts
packages/core/src/mostlyright/mode2.py
packages/core/src/mostlyright/research.py

Docs files changed:

CHANGELOG.md

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

Parity ticket gate: PASSED

parity-ticket-check: PR touches BOTH Python and TypeScript trigger surfaces — paired-language change satisfies the gate.

See CROSS-SDK-SYNC.md §2 for the workflow.

@helloiamvu helloiamvu merged commit e3d7831 into main Jul 8, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants