# Global Feat Injection — Specification ## Status Snapshot Current state as of 2026-05-24: - Current code reads class feat injection policy from `topdata.class_feat_injections` in `nwn-tool.yaml`. - `global_feats` injects concrete `feat:*` references into each `classes/feats/*.json` table, unless the class already authors the same feat. - `global_feats` supports `require_present` and `unless_present` conditions against other feat references already present in the class feat table. - `class_skill_masterfeats` expands configured `masterfeats:*` rows once for each class skill. - If a project omits `topdata.class_feat_injections`, the toolkit keeps the former hardcoded default injections for compatibility. ## 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:special_attacks` - `feat:throw` - `feat:grapple` - `feat:offensive_fighting` - `feat:defensive_fighting` - `feat:horse_menu` With properties: ```json { "GrantedOnLevel": "1", "List": "3", "OnMenu": "1" } ``` --- ### R5 — Conditional combat feats Inject: - `feat:power_attack` - `feat:combat_expertise` With properties: ```json { "GrantedOnLevel": "-1", "List": "0", "OnMenu": "1" } ``` --- ### R6 — Override precedence - Explicitly authored class feat rows take precedence over injected rows. - Injection MUST NOT replace explicit class feat data. - Dataset overrides are applied before class feat injection in the native dataset merge pipeline; author a class feat row directly to override or suppress the injected equivalent for a class. --- ## 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**.