Files
sow-tools/internal/topdata/CLASS_FEAT_GLOBAL_INJECTS_CONTRACT.md
T

4.2 KiB
Raw Blame History

Global Feat Injection — Specification

Status Snapshot

Current state as of 2026-05-13:

  • This document is partially stale relative to the implementation in internal/topdata/native.go.
  • Current code injects:
    • always-on menu feats: feat:specialattacks, feat:throw, feat:grapple, feat:offensivefighting, feat:defensivefighting, feat:horsemenu
    • conditional combat feats: feat:powerattack, feat:combatexpertise
    • class-skill shorthand rows for masterfeats:skillfocus at level -1 and masterfeats:greaterskillfocus at level 12
  • This contract should be treated as a parity note, not as an exact implementation transcript, until it is fully rewritten around the current behavior.

Objective

Ensure the native class feat generation pipeline produces functionally identical output to the legacy system by applying deterministic global feat injections.


Requirements

R1 — Skill-based master feats

For every class skill, inject:

  • masterfeats:skillfocus
  • masterfeats:greaterskillfocus

With properties:

{
  "GrantedOnLevel": "-1",
  "List": "1",
  "OnMenu": "0"
}

For the current implementation, `masterfeats:greaterskillfocus` is injected with
`GrantedOnLevel = 12`, not `-1`.

---

### R2  Spellcasting master feats

If class core defines:

- `"SpellCaster" = 1`

Then inject:

- `masterfeats:spellfocus`
- `masterfeats:greaterspellfocus`

Historical note:

- This rule is not currently implemented as an automatic global injection in
  `native.go`.
- Spell-focus expansion is supported when the class feat data explicitly
  references `masterfeats:spellfocus`.

If automatic spellcaster-driven injection is still required, it remains
outstanding work.

With properties:

```json
{
  "GrantedOnLevel": "-1",
  "List": "1",
  "OnMenu": "0"
}

R3 — Literacy rule

Inject:

  • feat:literate

Only if:

  • feat:illiterate is NOT present

With properties:

{
  "GrantedOnLevel": "1",
  "List": "3",
  "OnMenu": "0"
}

R4 — Default combat/menu feats

Always inject:

  • feat:specialattacks
  • feat:throw
  • feat:grapple
  • feat:offensivefighting
  • feat:defensivefighting
  • feat:horsemenu

With properties:

{
  "GrantedOnLevel": "1",
  "List": "3",
  "OnMenu": "1"
}

R5 — Conditional combat feats

Inject:

  • feat:powerattack
  • feat:combatexpertise

With properties:

{
  "GrantedOnLevel": "-1",
  "List": "0",
  "OnMenu": "1"
}

R6 — Override precedence

  • Overrides MUST be applied after injection.
  • Overrides MUST take precedence over injected defaults.
  • Injection MUST NOT block or replace explicit override data.

Behavioral Rules

B1 — Output equivalence

  • The resulting feat set MUST match legacy output in substance.
  • Exact row ordering and numeric IDs are NOT significant.

B2 — Deterministic inclusion

  • All injections MUST occur consistently for identical inputs.
  • No randomness or order-dependent behavior is allowed.

B3 — Conditional correctness

  • feat:literate MUST NOT be injected if feat:illiterate exists.
  • Spell focus feats MUST ONLY be injected when "SpellCaster" = 1.

B4 — Integration with pipeline

  • Injected feats MUST flow through the same processing stages as authored feats.
  • They MUST be subject to:
    • overrides
    • deduplication
    • final emission rules

Acceptance Criteria

An implementation is considered correct if:

  1. Parity

    • For any given class input, native output produces the same effective feats as legacy.
  2. Injection coverage

    • All required feats (R1R5) appear when conditions are met.
  3. Exclusion correctness

    • No invalid injections occur (e.g., literacy conflict).
  4. Override dominance

    • Any override affecting injected feats is correctly applied.
  5. Stability

    • Repeated runs with identical input produce identical output.

Non-Negotiables

  • This is parity-critical, not a best-effort feature.
  • Native pipeline MUST be capable of fully replacing legacy output.
  • There MUST be zero dependency on legacy systems at runtime.
  • Any deviation from legacy-equivalent output is a defect.