# 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: ````json { "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: ```json { "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: ```json { "GrantedOnLevel": "1", "List": "3", "OnMenu": "1" } ``` --- ### R5 — Conditional combat feats Inject: - `feat:powerattack` - `feat:combatexpertise` With properties: ```json { "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 (R1–R5) 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**.