Replaces the broken fraction-of-fee math with fraction-of-principal,
direction-aware. Pre-#38: super_fee_fraction was interpreted as
`round(fee_sats * super_fraction)`, paying super ~13× below intent on
every cashout since the bitspire wire-shape landed. Post-#38: super
and operator shares are computed independently against principal
using the per-direction fractions from SuperConfig + Machine.
Per workspace CLAUDE.md "Backwards-compatibility on pre-public-launch
code" (v2-bitspire hasn't shipped to users), no compat shims:
- calculations.py: delete `split_two_stage_commission` (legacy
fraction-of-fee). Keep `split_principal_based` as the sole split fn.
- migrations.py m009: extend to also DROP the deprecated
`super_fee_fraction` column after backfilling its value into the
new directional fields.
- models.py: drop `super_fee_fraction` from SuperConfig +
UpdateSuperConfigData entirely.
- bitspire.py parse_settlement: new signature takes `super_config:
SuperConfig` instead of `super_fee_fraction: float`. Resolves
directional fractions from super_config + machine by tx_type, then
computes via split_principal_based. Raises SettlementInvariantError
on unknown tx_type.
- tasks.py: pass `super_config` through to parse_settlement; assert
non-None (m001 inserts the singleton at install time — None is an
impossible state).
- partial-dispense ratio path in distribution.py is unchanged — still
uses `settlement.platform_fee_sats / settlement.fee_sats` from the
landed row, which is the right invariant (lock at landing) and
independent of the per-direction config.
Tests:
- Rename `test_two_stage_split.py` → `test_operator_split_legs.py`.
Drop the legacy-function test classes. Keep TestAllocateOperatorSplitLegs
(still-production fn) and TestPartialDispenseSplitRatio (inline ratio
math in distribution.py).
- New `test_principal_based_fees.py`: pure-math tests for
`split_principal_based` (six cases including a direct regression
test pinning the pre-#38 bug at 240→3000 sats per 100k principal at
3% super), plus parse_settlement directional dispatch tests
(cash-in routes through cash-in fractions; cash-out through
cash-out; unknown tx_type raises; zero-zero free-charge ATM; cross-
direction guard).
Migration verified end-to-end via container restart: super_config
columns post-m009 = id/super_fee_wallet_id/updated_at/
super_cash_in_fee_fraction/super_cash_out_fee_fraction (no
super_fee_fraction). dca_machines + dca_settlements gained the
expected new columns. 156/156 tests green.
Refs: aiolabs/satmachineadmin#37 (parent), #38 (this layer). Closes
the load-bearing super under-payment bug standalone.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>