Skip to content

Document apply_transform POWER c1=0.0 fallback in docstring - #98

Open
kgdunn wants to merge 1 commit into
mainfrom
claude/ecstatic-johnson-lt0hp6
Open

Document apply_transform POWER c1=0.0 fallback in docstring#98
kgdunn wants to merge 1 commit into
mainfrom
claude/ecstatic-johnson-lt0hp6

Conversation

@kgdunn

@kgdunn kgdunn commented Jul 24, 2026

Copy link
Copy Markdown
Owner

Summary

src/scorepilot/core/transforms.py::apply_transform documented its power default as c1 = 0.5, but the signature is c1: float = 0.0 with a silent body-side substitution to 0.5 when the caller passes (or leaves) c1 == 0.0. The docstring bullet contradicted the signature. This PR rewrites that one bullet so the Notes section describes what the code actually does — no behaviour change.

Fixes

  • src/scorepilot/core/transforms.py (apply_transform, Notes → power bullet): replaced

    power: sign(x) * abs(x) ** c1 (default c1 = 0.5, i.e. signed root)

    with a bullet that spells out both facts:

    power: sign(x) * abs(x) ** c1. The signature default is c1 = 0.0, but the body substitutes 0.5 (signed square root) whenever c1 == 0.0 is passed. Pass any non-zero c1 to get that exponent verbatim.

    A reader looking only at the signature would previously have assumed c1=0.0 produced sign(x) * abs(x)**0 = sign(x) (a piecewise constant); the doc now surfaces the fallback (exponent = c1 if c1 != 0.0 else 0.5 in _transform_values).

  • pyproject.toml: PATCH bump 0.22.00.22.1 for the docs-only change.

Ruff check + format both pass on the touched file.

Bugs flagged for maintainer

The docstring is now honest, but the underlying API shape is still misleading and worth a follow-up:

  • apply_transform(..., c1: float = 0.0) with _transform_values doing exponent = c1 if c1 != 0.0 else 0.5 is a "signature default that lies". For every transform kind other than POWER, c1=0.0 behaves as documented; for POWER it silently rewrites to 0.5. A caller who reasons purely from help(apply_transform) (or an IDE tooltip) will build a mental model that disagrees with runtime behaviour. This is exactly the kind of foot-gun that gets caught later in a preview when a user thinks they asked for x**0 and got sqrt(|x|).
  • Ways to actually fix it (out of scope for this PR because we were asked not to change behaviour):
    1. Change the signature default to c1: float = 0.5 and drop the if c1 != 0.0 else 0.5 fallback. Cleanest; makes signature and behaviour agree. Requires auditing every caller that passes POWER with the default to confirm none of them rely on the 0.0 sentinel being reinterpreted.
    2. Keep the 0.0-as-sentinel semantics but make it explicit: c1: float | None = None, then exponent = 0.5 if c1 is None else c1. Removes the "silently rewrites a valid float" surprise and lets a caller who genuinely wants x**0 pass 0.0 and get it.
    3. Split POWER off from the shared c1 param entirely (e.g. a dedicated power_exponent: float = 0.5).

Option 1 or 2 is the sensible next step; picking between them depends on whether any preprocessing-spec serializer out there is relying on c1=0.0 round-tripping through POWER.


Generated by Claude Code

The Notes section for ``power`` claimed the default was ``c1 = 0.5``, but the
signature is ``c1: float = 0.0`` with a silent body-side substitution to
``0.5`` when ``c1 == 0.0``. Rewrite that bullet so it matches what the code
actually does (no behaviour change).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ocQ71UFry6rkJnBNLeQKg
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