Files
sow-tools/docs/superpowers/plans/2026-05-22-class-progression-feat-projections.md
T

6.6 KiB

Class Progression Feat Projections Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Make class progression feat grouping configurable from wiki YAML so the module template can render granted feats and level-gated available feats separately.

Architecture: Extend the class_progression data provider config with named class-feat projection fields. The toolkit evaluates each configured projection against class feat rows and groups resolved feat links onto progression rows by level, while the module wiki config declares the project-specific List rules and the class template owns output wording.

Tech Stack: Go sow-toolkit, native topdata wiki YAML, HTML wiki templates, Go tests.


File Map

  • internal/topdata/wiki_data_providers.go: parse and validate data-provider projection configuration and pass it into class progression row assembly.
  • internal/topdata/wiki_tables.go: share class progression row assembly with configured class feat projections and keep default compatibility behavior.
  • internal/topdata/wiki_native_test.go: regression coverage for provider projection parsing, filtering, grouping, ordering, invalid config, and rendered template fields.
  • ../module/topdata/wiki/data.yaml: declare module-owned GrantedFeats and AvailableFeats projections for class progression.
  • ../module/topdata/wiki/templates/pages/classes.html: render bonus feats inline and use projected available feats in the Notes cell.
  • ../module/topdata/wiki/README.md: document configurable data-provider projections for template authors.

Task 1: Add Configured Class Feat Projection Tests

Files:

  • Modify: internal/topdata/wiki_native_test.go

  • Step 1: Write failing provider projection tests

Add tests that build wikiDataProviderDefinition from YAML such as:

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

Assert the parsed provider can render a progression row where GrantedFeats contains List == 3 feat links, AvailableFeats contains positive-level non-3 feat links, matched link order follows fixture source row order, and BonusFeat is still present.

  • Step 2: Add failing invalid configuration coverage

Add a test that loads a provider field with an empty projection name or empty when expression and expects an error containing data.yaml, the provider name, and the projection field context.

  • Step 3: Run focused tests to verify RED

Run:

go test ./internal/topdata -run 'TestWiki.*ClassProgression.*Projection|TestWikiData.*Provider.*Projection' -count=1

Expected: FAIL because wikiDataProviderDefinition does not yet accept class_feats.fields and progression rows do not expose AvailableFeats.

Task 2: Implement Generic Provider Projections

Files:

  • Modify: internal/topdata/wiki_data_providers.go

  • Modify: internal/topdata/wiki_tables.go

  • Test: internal/topdata/wiki_native_test.go

  • Step 1: Extend provider config types and validation

Add typed YAML support for:

type wikiDataProviderClassFeatConfig struct {
	Fields map[string]wikiDataProviderProjectionField `json:"fields" yaml:"fields"`
}

type wikiDataProviderProjectionField struct {
	When string `json:"when" yaml:"when"`
}

Validate each configured projection field name and when expression before provider execution.

  • Step 2: Carry projections into progression row assembly

Change the provider path so ClassProgression passes provider-owned class feat projection fields into progression row assembly. Preserve table-based class_progression callers by giving them the current default GrantedFeats behavior.

  • Step 3: Evaluate and group projections

In progression row assembly, resolve class feat links once per matching row, evaluate configured when expressions against class feat rows, and append matched links to the configured progression field for each positive GrantedOnLevel value in source row order.

  • Step 4: Run focused tests to verify GREEN

Run:

go test ./internal/topdata -run 'TestWiki.*ClassProgression.*Projection|TestWikiData.*Provider.*Projection' -count=1

Expected: PASS.

Task 3: Configure Module Wiki Output

Files:

  • Modify: ../module/topdata/wiki/data.yaml

  • Modify: ../module/topdata/wiki/templates/pages/classes.html

  • Modify: ../module/topdata/wiki/README.md

  • Step 1: Declare module projections

Update ClassProgression in ../module/topdata/wiki/data.yaml so module YAML owns GrantedFeats and AvailableFeats selection:

  ClassProgression:
    source: class_progression
    levels: 1-12
    class_feats:
      fields:
        GrantedFeats:
          when: "{{GrantedOnLevel > 0 && List == 3}}"
        AvailableFeats:
          when: "{{GrantedOnLevel > 0 && List != 3}}"
  • Step 2: Render projected fields in the class template

Keep bonus feats in the Feats cell with a conditional comma. Render AvailableFeats in the Notes cell with module-owned “becomes available” wording using supported template loop/filter syntax.

  • Step 3: Document the projection surface

Add a concise data.yaml note to the wiki README explaining that data-provider projection fields can expose configured per-level class feat lists to page templates and that wording stays in templates.

Task 4: Verify The Cross-Repo Wiki Path

Files:

  • Verify: internal/topdata/...

  • Verify: ../module/topdata/wiki/...

  • Step 1: Run toolkit regression tests

Run:

go test ./internal/topdata -count=1

Expected: PASS.

  • Step 2: Build the local toolkit

Run:

./build-tool.sh

Expected: exit 0 and refresh tools/sow-toolkit when source changes require it.

  • Step 3: Build module wiki with the local toolkit

Run from ../module:

SOW_TOOLS_DEV_BINARY=../toolkit/tools/sow-toolkit ./build-wiki.sh --force

Expected: exit 0 and regenerate class wiki pages under .cache/wiki/pages/.

  • Step 4: Inspect fighter output

Check generated fighter progression output for inline bonus feat text in Feats cells and becomes available notes for level-gated selectable feat links.

  • Step 5: Run diff checks

Run:

git diff --check

in both toolkit and module repos.