pf_app/lib
Paul Trowbridge f70de94e61 Write one adjustment row per coordinate, not per row read
Every operation inherited the row count of everything before it. Scale read
the baseline's rows plus every prior adjustment's rows sitting at the same
dimensional coordinate, and wrote a delta for each -- so eight Pull Forward
entries meant the next scale over that slice wrote nine rows where one would
do, and the table grew super-linearly with how much work had been done on it.

The base sets are grouped now: scale's `base`, recode's `src`, and clone's
source, each by every stored dimension and date, summing the measures. The
collapse is over pf_logid and pf_iter alone, so no column goes null and
nothing becomes unsliceable by a later operation -- which is the trap in
collapsing to the display grain instead, where the non-grain dimensions would
have to be null and the next slice naming one would silently miss these rows.

The maths is unchanged. Scale's proportional split needs the total over the
pool, and sum(sum(x)) OVER () gives the same figure over collapsed
coordinates that sum(x) OVER () gave over raw ones -- the window runs after
the GROUP BY. Verified on a real slice: 3,989 rows collapse to 3,187 at
1,303,545.75 either way. Across the version's existing adjustments it is
149,458 rows against 124,474, and that understates it, since the point is
that the next layer no longer multiplies the last.

All three templates planned against the live table before committing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-18 09:59:14 -04:00
..
auth.js Put the app behind a login 2026-09-14 22:20:25 -04:00
sql_generator.js Write one adjustment row per coordinate, not per row read 2026-09-18 09:59:14 -04:00
utils.js Initial commit — pivot forecast application 2026-04-01 07:59:05 -04:00