Revise class progression feat availability design

This commit is contained in:
2026-05-22 01:18:18 +02:00
parent 55794a9fde
commit afd40f0682
@@ -2,39 +2,59 @@
## Goal ## Goal
Class progression wiki rows should distinguish automatically granted class feats Class progression wiki providers should let module-owned wiki configuration
from level-gated selectable feats while also exposing bonus feat gains declared distinguish automatically granted class feats from level-gated selectable feats
by class `bfeat` tables in the progression table. while also exposing bonus feat gains declared by class `bfeat` tables in the
progression table.
## Ownership ## Ownership
The authored wiki page layout stays in `sow-module/topdata/wiki/`. The toolkit The authored wiki page layout and progression projection policy stay in
owns the progression row data assembled from class feat and bonus-feat tables. `sow-module/topdata/wiki/`. The toolkit owns generic progression row data
The change should stay inside those boundaries: 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; - module page templates decide how progression row fields are rendered;
- toolkit progression row assembly decides which feats are granted and which - toolkit progression row assembly groups configured projections by level
level-gated selectable feats become notes. without hardcoding the module's class feat list semantics or note wording.
## Behavior ## Behavior
Class feat rows with positive `GrantedOnLevel` values are not all equivalent. Class feat rows with positive `GrantedOnLevel` values are not all equivalent.
Rows in class feat tables with `List` value `3` are automatically granted feats. This module uses rows in class feat tables with `List` value `3` as
Rows with selectable list values such as `0` or `1` become available at the automatically granted feats and positive-level selectable rows as feats that
declared level but are not granted by the progression itself. become available at the declared level. That distinction is repository policy
and must be declared in wiki YAML rather than hidden in toolkit code.
For each class progression row: The `ClassProgression` data provider should support configured class feat
projection fields. This module can declare a shape such as:
- keep automatically granted feats in `GrantedFeats`; ```yaml
- keep the per-level bonus feat count from the class `bfeat` table in providers:
`BonusFeat`; ClassProgression:
- add level-gated selectable feat availability text to `Notes` in the form source: class_progression
`<feat link> becomes available.`; levels: 1-12
- combine multiple availability notes for the same level deterministically in class_feats:
source table order. fields:
GrantedFeats:
when: "{{GrantedOnLevel > 0 && List == 3}}"
AvailableFeats:
when: "{{GrantedOnLevel > 0 && List != 3}}"
```
Selectable rows without a positive `GrantedOnLevel` remain available through For each progression row, the toolkit should:
the class feat listing and do not create progression notes.
- 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 ## Rendering
@@ -43,19 +63,20 @@ Feats cell rather than adding another progression column. It should emit the
separator only when `GrantedFeats` already rendered content so bonus-only rows separator only when `GrantedFeats` already rendered content so bonus-only rows
do not start with a comma. do not start with a comma.
The existing Notes column renders the toolkit-generated `Notes` text with wiki The existing Notes column should render `AvailableFeats` in the module template
links enabled. The lower class feat table remains useful for listing class feat with module-owned wording such as `<feat link> becomes available.`. The lower
membership and list metadata; its level label should not be interpreted as an class feat table remains useful for listing class feat membership and list
automatic grant for selectable rows. metadata; its level label should not be interpreted as an automatic grant for
selectable rows.
## Data Flow ## Data Flow
The toolkit resolves the class `FeatsTable` while building progression rows. The toolkit resolves the class `FeatsTable` while building progression rows.
Each resolved feat row contributes to exactly one progression-facing bucket: Each configured class feat field evaluates its `when` expression against class
feat rows, groups matched rows by positive `GrantedOnLevel`, resolves feat
- `List == 3` and positive level: resolved feat link in `GrantedFeats`; references to wiki link text, and writes the grouped list onto the progression
- positive level and selectable list: resolved availability note for that level; row under the configured field name. Output order follows source table row
- non-positive or missing level: no progression-row contribution. order so repeated builds are deterministic.
The class `BonusFeatsTable` lookup continues to populate `BonusFeat` from the The class `BonusFeatsTable` lookup continues to populate `BonusFeat` from the
row whose id matches the progression level. row whose id matches the progression level.
@@ -64,18 +85,19 @@ row whose id matches the progression level.
The change should preserve current behavior for missing class feat tables, The change should preserve current behavior for missing class feat tables,
missing bonus feat tables, unresolved feat references, and classes without missing bonus feat tables, unresolved feat references, and classes without
level-gated selectable feats. Existing module templates that only read custom class feat projections. Invalid projection configuration should fail
`GrantedFeats`, `BonusFeat`, and `Notes` continue to use the same progression early with the provider file path and field name. Existing module templates
row fields. that only read `GrantedFeats`, `BonusFeat`, and `Notes` continue to use the same
progression row fields.
## Tests ## Tests
Toolkit coverage should verify: Toolkit coverage should verify:
- automatically granted `List == 3` feats remain in progression feat output; - default progression behavior still exposes `GrantedFeats`;
- positive-level selectable feats are excluded from `GrantedFeats`; - configured class feat fields filter by expression and group by level;
- positive-level selectable feats render availability notes with wiki links; - configured output order follows source table row order;
- multiple notes on one level have deterministic order; - invalid configured class feat fields fail clearly;
- bonus feat counts remain available to the progression template. - bonus feat counts remain available to the progression template.
Module validation should rebuild the generated wiki output with the local Module validation should rebuild the generated wiki output with the local