2.4 KiB
2.4 KiB
Class Feat Global Injection Contract
Status Snapshot
Current state as of 2026-06-05:
- Preferred class feat injection policy is authored in
topdata/data/classes/feats/global.json. global.jsonrows flow through the ordinary class feat expansion pipeline, including successor expansion, masterfeat expansion, class-skill filtering, reference resolution, deduplication, and final 2DA emission.- Legacy
topdata.class_feat_injectionsYAML still loads only as a compatibility path when no applicable class featglobal.jsonexists. - Toolkit hardcoded defaults are compatibility-only and must not be the normal source of project policy.
Objective
Native class feat generation must produce deterministic, legacy-equivalent effective output while keeping project policy in topdata authoring files.
Requirements
- For each class skill, inject the configured skill-focus masterfeat rows from
classes/feats/global.jsonusingFeatIndex.filter = "classskills". - Inject
feat:literateonly when the class table does not already includefeat:illiterate. - Inject the shared combat/menu feat rows declared in the manifest unless a
class already authors the equivalent
FeatIndex. - Explicit class feat rows take precedence over injected rows.
- Injections must be deterministic for identical inputs.
Manifest Shape
{
"position": "prepend",
"injections": [
{
"row": {
"FeatIndex": { "id": "feat:literate" },
"GrantedOnLevel": 1,
"List": 3,
"OnMenu": 0
},
"unless_present": [
{ "field": "FeatIndex", "id": "feat:illiterate" }
]
},
{
"row": {
"FeatIndex": {
"id": "masterfeats:skill_focus",
"filter": "classskills"
},
"GrantedOnLevel": -1,
"List": 1,
"OnMenu": 0
}
}
]
}
position defaults to append. The module uses prepend for class feat
injections to keep generated policy rows before per-class authored rows.
Acceptance Criteria
- Class feat output contains the same effective shared feats as the prior YAML policy.
- Literacy injection is skipped for illiterate classes.
- Skill-focus masterfeat rows expand only for class skills.
- YAML compatibility continues to work for consumers that have not migrated.
- A project with
classes/feats/global.jsondoes not also receive YAML or hardcoded default class feat injections.