# V2 to Hathor Narrative Authoring Contract

V2 does not author Story, Side Story, Krypt, Chronicles, or DJ Story source
content in the Unreal editor. Hathor owns the source in
`apps/hathor/studio-web/`; V2 consumes only compiled artifacts emitted by
`@hathor/lore-compiler` and cooked by Bellona into generated UE assets.

## Ownership Boundary

| Surface                             | Source owner              | V2 input                                      |
| ----------------------------------- | ------------------------- | --------------------------------------------- |
| Cinematic Story                     | `apps/hathor/studio-web/` | compiled dialogue, Sequencer outlines, quests |
| Per-fighter Side Stories            | `apps/hathor/studio-web/` | compiled timelines, rivalry edges, endings    |
| Krypt / reward-vault lore           | `apps/hathor/studio-web/` | compiled codex, quest graph, localization     |
| Chronicles / Weapon Master campaign | `apps/hathor/studio-web/` | compiled quest graph and strategy scenes      |
| DJ Story / street career            | `apps/hathor/studio-web/` | compiled crew/faction arcs and cinematics     |

V2 may request a published Hathor world by immutable `worldId` and
`versionHash`, but it must not ingest mutable authoring metadata into rollback
or gameplay snapshots.

## Required Authoring Records

### `FighterTimeline`

Every launch fighter has one canonical per-fighter timeline record. Required
fields:

| Field               | Meaning                                                              |
| ------------------- | -------------------------------------------------------------------- |
| `fighterId`         | Stable roster id matching the V2 fighter data asset id               |
| `canonEvents`       | Shared-canon events used by Story, intros, codex, and sequencer refs |
| `storyChapters`     | Main Story chapter ids where the fighter appears                     |
| `sideStoryArcs`     | Non-canonical or branchable character episodes                       |
| `arcadeEndingIds`   | Ending graphs this fighter can resolve to                            |
| `careerForkInputs`  | MyRISE / MyCAREER branch seeds that can fork player-specific history |
| `compiledOutputKey` | `V2/ue/Content/Generated/Timelines/<fighter>.uasset` target key      |

Validation:

- `fighterId` must resolve to a V2 roster id.
- Every `storyChapters` entry must exist in the Story content pack.
- Every `arcadeEndingIds` entry must resolve to a `LadderEndingGraph`.
- Canon events are append-only once a Hathor world version is published.

### `RivalryMatrix`

The rivalry matrix is a roster-level relationship graph. Each edge contains:

| Field        | Meaning                                                                                                                           |
| ------------ | --------------------------------------------------------------------------------------------------------------------------------- |
| `a`, `b`     | Fighter ids; unordered for symmetric relationships                                                                                |
| `type`       | `nemesis`, `rival`, `friendly-rival`, `mentor`, `student`, `family-ally`, `family-nemesis`, `love-interest`, `respect`, `neutral` |
| `intensity`  | `0.0` to `1.0` value used by intros, Story branches, and barks                                                                    |
| `motif`      | Short stable motif key, such as `ice-vs-fire`                                                                                     |
| `canonScope` | `canon`, `what-if`, `career-fork`, or `post-launch-crossover`                                                                     |

Validation:

- No duplicate unordered pair exists in the same `canonScope`.
- `intensity` must be numeric and clamped to `[0.0, 1.0]`.
- A non-neutral edge must reference at least one dialogue bank or Sequencer
  beat.
- Cross-franchise edges must be gated by a release flag.

### `FactionMatrix`

The faction matrix maps fighters, crews, realms, stables, gyms, labels, and
Chronicles kingdoms into relationship edges. Each edge contains:

| Field               | Meaning                                                       |
| ------------------- | ------------------------------------------------------------- |
| `sourceFactionId`   | Stable Hathor faction id                                      |
| `targetFactionId`   | Stable Hathor faction id                                      |
| `stance`            | `ally`, `tense-ally`, `neutral`, `rival`, `war`, or `vassal`  |
| `modeScopes`        | V2 modes where the stance is active                           |
| `unlockConditions`  | Optional quest, timeline, or player-career gates              |
| `compiledOutputKey` | `V2/ue/Content/Generated/Rivalry/FactionMatrix.uasset` target |

Validation:

- Every faction referenced by Story, Krypt, Chronicles, or DJ Story appears in
  at least one matrix edge.
- Directed stances such as `vassal` must declare direction explicitly.
- Player-mutated career forks are emitted as save-scoped overlays, not changes
  to the published canonical matrix.

### `LadderEndingGraph`

Every fighter has at least one ladder ending graph. Required fields:

| Field               | Meaning                                                |
| ------------------- | ------------------------------------------------------ |
| `endingGraphId`     | Stable graph id                                        |
| `fighterId`         | Fighter this graph belongs to                          |
| `encounterNodes`    | Ordered or branched fight nodes                        |
| `bossNodeId`        | Required final boss encounter                          |
| `endingCinematicId` | Required Sequencer outline id                          |
| `canonScope`        | `canon`, `what-if`, `joke`, `crossover`, or `career`   |
| `compiledOutputKey` | `V2/ue/Content/Generated/Quests/Arcade/<fighter>.json` |

Validation:

- The graph is acyclic except for explicit challenge-loop nodes.
- Every terminal path reaches `bossNodeId` and then `endingCinematicId`.
- Non-canonical endings are tagged so Story Theater and codex do not present
  them as canon.

### `SideStorySequencerOutline`

Side Story cinematics are authored as Hathor Sequencer outlines, not UE Level
Sequence source assets. Required fields:

| Field               | Meaning                                                       |
| ------------------- | ------------------------------------------------------------- |
| `outlineId`         | Stable scene outline id                                       |
| `surface`           | `story`, `side_story`, `krypt`, `chronicles`, or `dj_story`   |
| `participants`      | Fighter, NPC, faction, or venue ids                           |
| `shots`             | Ordered shot ids with camera intent, dialogue ids, and timing |
| `branchHooks`       | Optional player-choice or career-fork hook ids                |
| `localizationKeys`  | String-table keys emitted with the compiled package           |
| `compiledOutputKey` | `V2/ue/Content/Generated/Sequencer/<outline>.uasset` target   |

Validation:

- Each shot has a deterministic order, stable id, and non-empty camera intent.
- Dialogue ids resolve to Hathor dialogue-bank records.
- Branch hooks name authored branches only; V2 does not invent branches in UE.

## Compiler Handoff

`@hathor/lore-compiler` emits:

- `V2/ue/Content/Generated/Dialogue/<surface>/`
- `V2/ue/Content/Generated/Sequencer/<outline>.uasset`
- `V2/ue/Content/Generated/Quests/<mode>/`
- `V2/ue/Content/Generated/Timelines/<fighter>.uasset`
- `V2/ue/Content/Generated/Rivalry/Matrix.uasset`
- `V2/ue/Content/Generated/Rivalry/FactionMatrix.uasset`
- `V2/ue/Content/Generated/Codex/`
- UE localization string-table exports

The compiler package must include a content-addressed manifest with `worldId`,
`versionHash`, compiler package version, artifact hashes, and Bellona cook
lineage ids. V2 stores only immutable ids and hashes in gameplay-facing
snapshots.

## Reciprocal Hathor Work

The reciprocal Hathor backlog lives in
`docs/domains/hathor/deep-dive/specifications.md` § 9.6. At minimum, Hathor must
extend `@hathor/domain-models`, `@hathor/narrative`, and `@hathor/lore-compiler`
with `FighterTimeline`, `RivalryMatrix`, `FactionMatrix`, `LadderEndingGraph`,
and `SideStorySequencerOutline` before V2 Story Mode, Side Stories, Krypt,
Chronicles, or DJ Story can ship.
