Skip to content

fix(py): restore 68 batch indicators silently degraded to streaming classes (84cu)#14

Merged
lavs9 merged 1 commit into
mainfrom
fix/quantwave-84cu-registry-batch-symbol-names
Jul 15, 2026
Merged

fix(py): restore 68 batch indicators silently degraded to streaming classes (84cu)#14
lavs9 merged 1 commit into
mainfrom
fix/quantwave-84cu-registry-batch-symbol-names

Conversation

@lavs9

@lavs9 lavs9 commented Jul 15, 2026

Copy link
Copy Markdown
Owner

Summary

qw.supertrend was a class. qw.rsi was a function. Same registry, same generator, no error, no warning — and the difference was pure luck.

The generated TA registry added in 0.7.0 (5ipk.3) derives native batch symbol names with pascal_to_snake() (SuperTrendsuper_trend), but the export_*! macros emit pub fn [<$name:lower>] (SuperTrendsupertrend). Every multi-word name missed. The 44 single-word names (rsi, sma, atr) survived only because pascal_to_snake("Rsi") == "rsi".

_resolve_ta_binding treated the miss as a fallback and returned native_streaming — a class with a completely different calling convention. 68 of 221 indicators were affected. 0.6 had no registry layer and bound native symbols directly, which is why it was unaffected: this is a 0.7 regression.

Why this matters beyond the bug

This is the GMM::fit() disease from planning/BRUTAL_REVIEW_2026-07-07.md: a public API reporting success while doing something other than what the caller asked. The cost here was not just wrong behavior — the silence manufactured a false explanation. An agent investigating qw.supertrend being a class concluded 0.7 had intentionally moved SuperTrend to the .ta expression namespace, and planned a downstream compiler refactor around a two-line codegen bug.

The test could not catch it by construction:

assert (entry.get("native_batch") or entry.get("native_streaming")
        or entry.get("polars_method")), slug

It asserted a name was present, never that it resolved. native_batch: "super_trend" passed cleanly.

Changes

  • scripts/generate_api_stubs.py — derive batch names with .lower(), matching the macro. Repairs 61.
  • scripts/api_slug_aliases.json — 4 stale snake_cased names (fm_demodulator, fourier_series_model, my_rsi, precision_trend_analysis); 3 aliases declaring batch exports that do not exist now fall through to their polars methods (linreg, oc2, true_range); sr_monitor dropped SrInteractionMonitor, a class that exists only as a string in metadata_registry.rs and was never exported to Python.
  • quantwave-py/python/quantwave/__init__.py_resolve_ta_binding raises ImportError when a declared native_batch symbol is absent from the build, instead of silently substituting the streaming class. A native_batch of None still falls through to streaming/polars unchanged (intentionally streaming-only indicators keep working).
  • tests/python/test_api_surface.py — assert every declared native symbol resolves against the compiled module, plus a regression test that multi-word slugs bind as batch functions. This test found a 69th mismatch (sr_monitor) during development.
  • _ta_registry_generated.py — regenerated: 68 insertions, 68 deletions, exactly the predicted blast radius.

Compatibility

None required. qw.supertrend(period=10, multiplier=3.0, high=..., low=..., close=...) again returns list[SuperTrendResult] — the exact 0.6 calling convention.

Verification

Run against a real 0.7.0 environment:

  • 221 slugs · 0 declared-batch-bound-as-class · 0 registry names absent from build
  • 127 bound as batch functions; 2 legitimately streaming-only
  • tests/python/: 179 passed. The 2 failures (test_sma_parity, test_correctness_precheck_runs) are pre-existing and reproduce on a clean tree via git stash.

Follow-up (not in this PR)

test_sma_parity fails on df.lazy().ta.sma(...) with 'LazyFrame' object has no attribute 'ta'. The .ta namespace is registered on Expr, not LazyFrame — the test encodes the same wrong mental model that misled the agent investigating this bug. Worth fixing separately.

Closes quantwave-84cu

🤖 Generated with Claude Code

…4cu)

The generated TA registry added in 0.7.0 derived native batch symbol names
with pascal_to_snake() (SuperTrend -> super_trend), but the export_*! macros
emit `pub fn [<$name:lower>]` (SuperTrend -> supertrend). Every multi-word
name missed; the 44 single-word ones (rsi, sma, atr) passed only because
pascal_to_snake("Rsi") == "rsi".

_resolve_ta_binding treated the miss as a fallback and returned
native_streaming, so qw.supertrend was a *class* while qw.rsi was a
function -- no error, no warning, different calling convention. 68 of 221
indicators were affected. 0.6 had no registry layer and bound native
symbols directly, which is why it was unaffected.

- generate_api_stubs.py: derive batch names with .lower(), matching the macro
- api_slug_aliases.json: fix 4 stale snake_cased names; null out 3 aliases
  declaring batch exports that do not exist (fall through to polars); drop
  sr_monitor's SrInteractionMonitor, never exported to Python
- __init__.py: raise ImportError when a declared native_batch symbol is
  absent instead of silently substituting the streaming class. native_batch
  of None still falls through to streaming/polars unchanged.
- test_api_surface.py: assert declared symbols resolve against the build.
  The prior test only checked a name was present, never that it resolved,
  so native_batch: "super_trend" passed cleanly.

qw.supertrend(period=10, multiplier=3.0, high=..., low=..., close=...) again
returns list[SuperTrendResult]; callers need no changes.

Verified on a real 0.7.0 venv: 221 slugs, 0 declared-batch-bound-as-class,
0 registry names absent from build. Suite 179 passed; the 2 failures
(test_sma_parity, test_correctness_precheck_runs) are pre-existing and
reproduce on a clean tree.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@lavs9 lavs9 merged commit dc2ea89 into main Jul 15, 2026
6 checks passed
@lavs9 lavs9 deleted the fix/quantwave-84cu-registry-batch-symbol-names branch July 15, 2026 18:12
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.

1 participant