From afd40f06822c9cf39b994b6eb250dc0ffc426bc4 Mon Sep 17 00:00:00 2001 From: vickydotbat Date: Fri, 22 May 2026 01:18:18 +0200 Subject: [PATCH] Revise class progression feat availability design --- ...ss-progression-feat-availability-design.md | 96 ++++++++++++------- 1 file changed, 59 insertions(+), 37 deletions(-) diff --git a/docs/superpowers/specs/2026-05-22-class-progression-feat-availability-design.md b/docs/superpowers/specs/2026-05-22-class-progression-feat-availability-design.md index 4a4e996..1537489 100644 --- a/docs/superpowers/specs/2026-05-22-class-progression-feat-availability-design.md +++ b/docs/superpowers/specs/2026-05-22-class-progression-feat-availability-design.md @@ -2,39 +2,59 @@ ## Goal -Class progression wiki rows should 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. +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 stays in `sow-module/topdata/wiki/`. The toolkit -owns the progression row data assembled from class feat and bonus-feat tables. -The change should stay inside those boundaries: +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 decides which feats are granted and which - level-gated selectable feats become notes. +- 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. -Rows in class feat tables with `List` value `3` are automatically granted feats. -Rows with selectable list values such as `0` or `1` become available at the -declared level but are not granted by the progression itself. +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. -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`; -- keep the per-level bonus feat count from the class `bfeat` table in - `BonusFeat`; -- add level-gated selectable feat availability text to `Notes` in the form - ` becomes available.`; -- combine multiple availability notes for the same level deterministically in - source table order. +```yaml +providers: + ClassProgression: + source: class_progression + levels: 1-12 + class_feats: + fields: + GrantedFeats: + when: "{{GrantedOnLevel > 0 && List == 3}}" + AvailableFeats: + when: "{{GrantedOnLevel > 0 && List != 3}}" +``` -Selectable rows without a positive `GrantedOnLevel` remain available through -the class feat listing and do not create progression notes. +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 @@ -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 do not start with a comma. -The existing Notes column renders the toolkit-generated `Notes` text with wiki -links enabled. 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. +The existing Notes column should render `AvailableFeats` in the module template +with module-owned wording such as ` 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 resolved feat row contributes to exactly one progression-facing bucket: - -- `List == 3` and positive level: resolved feat link in `GrantedFeats`; -- positive level and selectable list: resolved availability note for that level; -- non-positive or missing level: no progression-row contribution. +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. @@ -64,18 +85,19 @@ row whose id matches the progression level. The change should preserve current behavior for missing class feat tables, missing bonus feat tables, unresolved feat references, and classes without -level-gated selectable feats. Existing module templates that only read -`GrantedFeats`, `BonusFeat`, and `Notes` continue to use the same progression -row fields. +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: -- automatically granted `List == 3` feats remain in progression feat output; -- positive-level selectable feats are excluded from `GrantedFeats`; -- positive-level selectable feats render availability notes with wiki links; -- multiple notes on one level have deterministic order; +- 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