Skip to content

feat(pivot): roll-forward preferred-label bindings - #25

Merged
jfrench9 merged 1 commit into
mainfrom
feature/rollforward-labels
Jul 30, 2026
Merged

jfrench9 merged 1 commit into
mainfrom
feature/rollforward-labels

Conversation

@jfrench9

Copy link
Copy Markdown
Member

Summary

Implement the deferred half of preferred-label support: roll-forward bindings. periodStartLabel / periodEndLabel roles aren't just label text — the same concept appears under two presentation arcs (beginning balance at the top of the network, ending balance at the bottom), and the beginning row must bind the instant fact at each duration column's start date (dated the day before the start, per the XBRL/SEC convention). Previously the tree dedup silently dropped the second arc, opening balances were pruned as sparse noise columns, and equity statements showed only ending balances.

No converter or SEC-adapter changes needed — both already deliver the roles and strings (xbrl-holon#8, report-components#24); this is pivot-only.

Changes

  • src/pivot.ts
    • PresentationTree.childrenOf now carries arcs (child + label + binding + negated) instead of bare child ids; arcRef classifies periodStart* → 'start', periodEnd* → 'end'.
    • The walk dedups per (element, binding) so a roll-forward concept emits one row per arc, in arc order (beginning at the top, ending at the bottom); all other element repeats still drop.
    • Cell and member-combo lookups are binding-aware: 'start' rows read the instant at dayBefore(column.startDate) (exact start date as fallback); 'end'/default rows read the column end as before. A start/end row with no bindable fact anywhere doesn't render.
    • Standalone opening-instant columns are suppressed in roll-forward sections — their data now renders as the beginning-balance row inside the duration columns.
    • Row keys carry a rf:start/rf:end variant suffix so React keys and cell selection stay unique.
    • The 0.3.2 first-arc-wins label map is subsumed by the arc-carrying tree (also fixes labels when one concept has different labels under different arcs).

Testing

  • npm run test:all — green, exit 0 (109 tests across 13 files; the full prior suite passes unchanged through the tree refactor).
  • New test/rollforward.test.ts: beginning/ending rows for the same concept in arc order, opening-instant binding (start − 1 day) into the duration column with the fact identity asserted, standalone opening-column suppression, and row-key uniqueness.
  • Real-data verification on the NVDA 10-K equity statement (bundled sample holon): beginning balances 22,101 / 42,978 / 79,327 chain into ending 42,978 / 79,327 / 157,293 across FY24–FY26 — each year's ending equals the next year's beginning — with equity-component sub-rows, negated tax-withholding rows, and the beginning/ending share-count rows, matching the as-filed statement. Verified visually in the viewer dev server against the same sample.

Notes

  • SEC mode inherits the feature automatically: the graph's Association.preferred_label roles flow through the 0.3.3 adapter into the same pivot path.
  • No sample regen needed downstream — the bundled holon already carries the roles; a viewer dependency bump lights this up.

…balances)

periodStart*/periodEnd* preferred-label roles carry a binding semantic,
not just a label: the same concept appears under two presentation arcs
(beginning balance at the top of the network, ending at the bottom), and
the beginning row binds the INSTANT fact at each duration column's start
date — dated the day before the start per the XBRL/SEC convention, with
the exact start date as fallback.

The presentation tree now carries arcs (child + label + binding +
negation) instead of bare child ids, the walk dedups per (element,
binding) so both roll-forward rows emit in arc order, and cell/combo
lookups are binding-aware. Standalone opening-instant columns are
suppressed in roll-forward sections — their data renders as the
beginning-balance row inside the duration columns (previously openings
were dropped as sparse noise and only ending balances survived).

The per-arc label plumbing (0.3.2's first-arc-wins map) is subsumed by
the arc-carrying tree, which also fixes labels when one concept has
different labels under different arcs.

Verified on the NVDA 10-K equity statement: beginning balances
22,101 / 42,978 / 79,327 chain into ending 42,978 / 79,327 / 157,293
across FY24-FY26, with component sub-rows and negated withholding rows
matching the as-filed statement.
@jfrench9
jfrench9 merged commit b138897 into main Jul 30, 2026
1 check passed
@jfrench9
jfrench9 deleted the feature/rollforward-labels branch July 30, 2026 22:41
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