Files
sow-tools/docs/superpowers/specs/2026-05-22-class-progression-feat-availability-design.md
T

4.3 KiB

Class Progression Feat Availability Design

Goal

Class progression wiki providers should let module-owned wiki configuration distinguish automatically granted class feats from level-gated selectable feats while also exposing bonus feat gains declared by class bfeat tables in the progression table.

Ownership

The authored wiki page layout and progression projection policy stay in sow-module/topdata/wiki/. The toolkit owns generic progression row data assembly from configured class feat and bonus-feat sources. The change should stay inside those boundaries:

  • module wiki YAML decides which class feat rows project into progression fields;
  • module page templates decide how progression row fields are rendered;
  • toolkit progression row assembly groups configured projections by level without hardcoding the module's class feat list semantics or note wording.

Behavior

Class feat rows with positive GrantedOnLevel values are not all equivalent. This module uses rows in class feat tables with List value 3 as automatically granted feats and positive-level selectable rows as feats that become available at the declared level. That distinction is repository policy and must be declared in wiki YAML rather than hidden in toolkit code.

The ClassProgression data provider should support configured class feat projection fields. This module can declare a shape such as:

providers:
  ClassProgression:
    source: class_progression
    levels: 1-12
    class_feats:
      fields:
        GrantedFeats:
          when: "{{GrantedOnLevel > 0 && List == 3}}"
        AvailableFeats:
          when: "{{GrantedOnLevel > 0 && List != 3}}"

For each progression row, the toolkit should:

  • continue exposing the per-level bonus feat count from the class bfeat table as BonusFeat;
  • expose each configured class feat field as a deterministic list of resolved wiki feat links for class feat rows whose configured expression matches the progression level;
  • leave non-matching class feat rows out of that configured field.

The default class_progression provider behavior should preserve the current GrantedFeats projection when no custom field configuration is declared.

Rendering

The class progression template can render BonusFeat inline in its existing Feats cell rather than adding another progression column. It should emit the separator only when GrantedFeats already rendered content so bonus-only rows do not start with a comma.

The existing Notes column should render AvailableFeats in the module template with module-owned wording such as <feat link> becomes available.. The lower class feat table remains useful for listing class feat membership and list metadata; its level label should not be interpreted as an automatic grant for selectable rows.

Data Flow

The toolkit resolves the class FeatsTable while building progression rows. Each configured class feat field evaluates its when expression against class feat rows, groups matched rows by positive GrantedOnLevel, resolves feat references to wiki link text, and writes the grouped list onto the progression row under the configured field name. Output order follows source table row order so repeated builds are deterministic.

The class BonusFeatsTable lookup continues to populate BonusFeat from the row whose id matches the progression level.

Errors And Compatibility

The change should preserve current behavior for missing class feat tables, missing bonus feat tables, unresolved feat references, and classes without custom class feat projections. Invalid projection configuration should fail early with the provider file path and field name. Existing module templates that only read GrantedFeats, BonusFeat, and Notes continue to use the same progression row fields.

Tests

Toolkit coverage should verify:

  • default progression behavior still exposes GrantedFeats;
  • configured class feat fields filter by expression and group by level;
  • configured output order follows source table row order;
  • invalid configured class feat fields fail clearly;
  • bonus feat counts remain available to the progression template.

Module validation should rebuild the generated wiki output with the local toolkit binary after the toolkit change and inspect a class that has both granted feats and level-gated selectable feats, such as fighter.