Implement the 012-turn-navigation feature that adds a RetreatTurn domain operation and relocates turn controls to a navigation bar at the top of the encounter tracker
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
55
specs/012-turn-navigation/contracts/domain-api.md
Normal file
55
specs/012-turn-navigation/contracts/domain-api.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# Domain API Contract: Turn Navigation
|
||||
|
||||
## retreatTurn(encounter: Encounter): RetreatTurnSuccess | DomainError
|
||||
|
||||
### Input
|
||||
- `encounter`: Encounter (combatants, activeIndex, roundNumber)
|
||||
|
||||
### Success Output
|
||||
```
|
||||
{
|
||||
encounter: Encounter // Updated state
|
||||
events: DomainEvent[] // TurnRetreated, optionally RoundRetreated
|
||||
}
|
||||
```
|
||||
|
||||
### Error Cases
|
||||
|
||||
| Condition | Error Code | Message |
|
||||
|-----------|------------|---------|
|
||||
| combatants.length === 0 | `invalid-encounter` | Cannot retreat turn on an encounter with no combatants |
|
||||
| roundNumber === 1 && activeIndex === 0 | `no-previous-turn` | Cannot retreat before the start of the encounter |
|
||||
|
||||
### Event Contracts
|
||||
|
||||
**TurnRetreated** (always emitted on success):
|
||||
```
|
||||
{
|
||||
type: "TurnRetreated"
|
||||
previousCombatantId: CombatantId // Was active before retreat
|
||||
newCombatantId: CombatantId // Now active after retreat
|
||||
roundNumber: number // Round number after retreat
|
||||
}
|
||||
```
|
||||
|
||||
**RoundRetreated** (emitted when crossing round boundary):
|
||||
```
|
||||
{
|
||||
type: "RoundRetreated"
|
||||
newRoundNumber: number // Decremented round number
|
||||
}
|
||||
```
|
||||
|
||||
**Emission order**: TurnRetreated first, then RoundRetreated (when applicable).
|
||||
|
||||
## UI Contract: TurnNavigation Component
|
||||
|
||||
### Props
|
||||
- `encounter`: Encounter (current state)
|
||||
- `onAdvanceTurn`: () => void
|
||||
- `onRetreatTurn`: () => void
|
||||
|
||||
### Behavior
|
||||
- Previous Turn button: calls onRetreatTurn; disabled when roundNumber === 1 && activeIndex === 0, or combatants.length === 0
|
||||
- Next Turn button: calls onAdvanceTurn; disabled when combatants.length === 0
|
||||
- Displays: round number and active combatant name
|
||||
Reference in New Issue
Block a user