629. Lesson identity
The previous lesson defined an encounter as a bounded lifecycle. This lesson turns that boundary into a coordination system with explicit phases, event contracts, ownership boundaries, interruption behavior, and a run identity that prevents delayed work from affecting a later activation.
630. Learning objective
After this lesson, you can create an encounter board that requests actor spawns, advances through explicit phases, handles valid late entry, rejects stale or duplicate events, and resets without copying actor, registration, health, or defeat authority into the encounter controller.
631. Core distinction: coordination is not ownership
An encounter controller owns encounter coordination state. It does not become a second actor, spawning, or combat system.
The encounter board may own:
- whether the encounter is inactive, active, complete, or resetting;
- the active phase;
- the identity of the current activation;
- which spawn requests it has issued;
- coordination counters derived from accepted events;
- which event identifiers it has already consumed.
Other systems retain authority over their domains:
- the spawner or actor system creates and registers actors;
- each actor owns its local behavior and life state;
- combat resolves damage and decides that an actor has been defeated;
- reward or progression systems own their own consequences.
The board can request work and consume reported facts. It must not copy health to determine defeat, directly register actors in another system's registry, or fabricate an actor reset.
Events report facts. Commands request work. The system responsible for a domain determines the result. The encounter board determines only what those results mean for encounter progression.
632. Board–Run–Actors–Events model
| Participant | Authoritative state | Receives | Sends |
|---|---|---|---|
| Encounter board | Phase, completion, active run identity, consumed-event set | Trigger, actor-registered fact, combat-confirmed defeat, actor exit | Spawn request, phase change, actor-reset request |
| Spawner or actor system | Actor creation and registration | Spawn and reset requests | Actor registered, actor exited |
| Actor | Local behavior and life state | Behavior, combat, and reset commands | Actor lifecycle facts |
| Combat system | Damage resolution and defeat decision | Attacks and targets | Combat-confirmed actor-defeated event |
A board should accept an event only when:
an active run exists
AND event.encounterId matches
AND event.runId matches the active run
AND the current phase accepts that event
AND event.eventId has not already been consumed
The phase check and the run check solve different problems. A phase can recur after reactivation, so a matching phase alone cannot prove that an event belongs to the current activation.
633. Correct reset contract
Reset must distinguish the run being interrupted from the identity of any later run. First capture the interrupted run, then invalidate it on the board, and finally ask the actor-owning system to reset actors associated with that interrupted run.
reset requested
-> capture interruptedRunId
-> invalidate activeRunId immediately
-> clear board-owned coordination state
-> request actor reset with targetRunId = interruptedRunId
-> remain inactive
-> a later activation receives a fresh runId
-> events from interruptedRunId are rejected
Do not send a newly generated run identity as though it identified the actors from the interrupted run.
634. Concrete example
run 8, PHASE_ONE
board requests two scouts with runId 8
spawner reports a late scout registration with runId 8
board accepts it because the current phase permits late entry
combat confirms both defeats with runId 8
board advances to PHASE_TWO
reset during PHASE_TWO
board captures interruptedRunId = 8
board sets activeRunId = null
board clears phase counters and consumed event IDs
board requests actor reset with targetRunId = 8
later activation
board creates runId 9 and enters PHASE_ONE
late defeat from run 8
board rejects it because 8 is not the active run
A minimal contract can be represented as:
type EncounterPhase = "inactive" | "phase-one" | "phase-two" | "complete";
type EncounterBoard = {
encounterId: string;
activeRunId: number | null;
nextRunId: number;
phase: EncounterPhase;
defeatedByPhase: Record<string, number>;
consumedEventIds: Set<string>;
};
type DefeatEvent = {
eventId: string;
encounterId: string;
runId: number;
phase: EncounterPhase;
actorId: string;
};
function activate(board: EncounterBoard) {
if (board.activeRunId !== null) return;
const runId = board.nextRunId++;
board.activeRunId = runId;
board.phase = "phase-one";
events.emit("encounter.spawnRequested", {
encounterId: board.encounterId,
runId,
group: "scouts"
});
}
function acceptsDefeat(board: EncounterBoard, event: DefeatEvent) {
return board.activeRunId !== null
&& event.encounterId === board.encounterId
&& event.runId === board.activeRunId
&& event.phase === board.phase
&& !board.consumedEventIds.has(event.eventId);
}
function reset(board: EncounterBoard) {
const interruptedRunId = board.activeRunId;
// Invalidate the run before external reset work can report more events.
board.activeRunId = null;
board.phase = "inactive";
board.defeatedByPhase = {};
board.consumedEventIds.clear();
if (interruptedRunId !== null) {
events.emit("encounter.actorsResetRequested", {
encounterId: board.encounterId,
targetRunId: interruptedRunId
});
}
}
Combat still decides whether an actor was defeated. The board uses the resulting event only to evaluate an encounter rule. Likewise, the spawner or actor system performs the actual reset; the board merely identifies the interrupted encounter run that should be reset.
635. Decision points
Before implementation, decide and record:
- Late entry: Can an actor registered after a phase begins join that phase? If so, does it alter the phase's expected count?
- Pending spawn: What happens when reset occurs before a requested actor is registered?
- Phase-late event: Is an event from the current run but a previous phase ignored, logged, or handled by a separate contract?
- Duplicate delivery: Which stable
eventIdprevents one fact from being counted twice? - Reactivation: What mechanism issues a fresh run identity?
These are contract decisions, not timing assumptions.
636. AI-native workflow
- Write the authority table first. State which system owns phases, registration, local actor state, damage resolution, and defeat decisions.
- Provide the existing interfaces. Ask AI for the smallest change that carries
encounterId,runId,phase, andeventIdthrough the required requests and events. - Constrain the request. Explicitly forbid copied health, duplicated defeat flags, a second authoritative actor registry, or direct mutation of actor state by the board.
- Inspect reset ordering. Confirm that the board invalidates the active run before external reset work can report more events and that the reset command targets the interrupted run.
- Test one edge case at a time. Exercise late registration, phase-late defeat, pending spawn during reset, old-run delivery after reactivation, and duplicate delivery.
AI may draft event wiring, but the authority boundaries and acceptance rules remain design decisions you must inspect.
637. Guided build
Step 1 — Create an authority table
For the encounter board, spawner or actor system, actor, and combat system, name:
- one state each participant controls;
- one fact it reports;
- one command it receives or sends.
List every proposed active, health, defeated, registered, phase, and completion field. Assign exactly one authoritative system to each field. Replace any board field that duplicates another system's authority with an event, command, reference, or coordination counter.
Include this rule in your board specification:
Combat decides defeat; the encounter board counts only accepted combat-confirmed defeat events for its phase rule.
Step 2 — Define phases and event context
Define at least these phases:
- inactive;
- first wave active;
- second wave active;
- complete.
Add an active run identity and a stable event identity. Document the phase completion rule and the event types accepted in each phase.
Step 3 — Wire activation and late entry
Create the smallest path that:
- activates the board from a trigger;
- issues a spawn request with the current run identity;
- consumes actor registration reported by the spawner or actor system;
- applies an explicit late-entry rule;
- consumes combat-confirmed defeat events only after validating encounter, run, phase, and event identity;
- advances the phase or completes the encounter.
Step 4 — Add interruption and reset
Capture the interrupted run, invalidate it on the board, clear only board-owned coordination state, and issue a reset request whose targetRunId identifies the interrupted run. A later activation must use a fresh run identity.
Step 5 — Exercise edge cases
Record the observed result for:
- valid late registration in the current run;
- a current-run defeat event from a previous phase;
- reset while a spawn request is pending;
- an old-run registration or defeat after reactivation;
- duplicate delivery of the same event.
For every case, identify which system has authority and why the board accepts, rejects, or ignores the event without editing that system's internal state.
638. Evidence and assessment
Submit the encounter board and its evidence through the linked practical assessment. The work must show authority boundaries, phase and run contracts, late-entry behavior, interruption, targeted reset, reactivation, stale-event rejection, and duplicate-event rejection.
The work must be revised if the board:
- maintains a second authoritative actor registry;
- decides defeat from copied health or actor-active state;
- accepts events without matching encounter and run identities;
- sends a fresh run identity as the target of the interrupted actors' reset;
- lets an old or duplicate event advance the current phase.
639. Key takeaways
- Coordination authority differs from spawning, actor, and combat authority.
- Combat decides defeat; the board determines what an accepted defeat fact means for phase progression.
- Commands request work from the responsible system; events report results.
- Run identity prevents delayed work from crossing activation boundaries.
- Reset must target the interrupted run while invalidating that run on the board before external work continues.
- Late entry, interruption, and duplicate delivery require explicit contracts.
640. Next lesson
Continue to 2.4 — Boss design: A boss is a readable contract. Boss design reuses the same encounter ownership, phase-contract, and stale-event reasoning, then adds the player-facing promise that makes those phases readable and meaningful.
641. Knowledge check
Answer these items for yourself before reading the answers.
Which responsibility belongs to the encounter board?
Show answer and feedback
Answer: Tracking the encounter phase and active run identity
Why: The board owns coordination state such as phase, completion, and active run identity. Spawning, actor, combat, and progression systems retain authority over their respective domains.
What is the correct relationship between a combat-confirmed defeat event and an encounter phase transition?
Show answer and feedback
Answer: Combat reports the defeat, and the board uses the accepted fact to evaluate its transition rule
Why: Combat remains authoritative for the defeat decision. The board validates and consumes that fact only to determine encounter progression.
Why must an encounter event include a run or generation identity?
Show answer and feedback
Answer: To reject delayed events from an interrupted or earlier activation
Why: The run identity distinguishes the current activation from earlier ones, even when phases or actor identifiers repeat.
What should the board do when reset interrupts an active run?
Show answer and feedback
Answer: Capture and invalidate the interrupted run, then request actor reset using that interrupted run as the target
Why: The board must invalidate the interrupted run before more external events can affect it. The reset command targets that interrupted run, while a later activation receives a separate fresh identity.