Skip to main content

Act 1 Gate Spec: Arrival to First People

Context

This doc authors the gate predicate that authorizes the ActState.CurrentAct: 1 -> 2 transition (the Act 1 First People act finishing and Act 2 First Outpost beginning) per ../lore/adr/ad-0010-act-progression-actstate-scope.md. The transition is driven by the ActProgression system, which reads this predicate against committed scopes and fires OnActCompleted(1) followed by OnActStarted(2) when the predicate becomes true.

The source act doc is ./gd-act-1-first-people.md. The act progression envelope is ../systems/gd-act-progression.md. The binding rule from ad-0010 lines 93-99 is firm: gates read named state on committed scopes only — no calendar-day enumeration, no real-time clocks, no time-since-start counters.

Gate Predicate

Act 1 is complete when the Core can support life beyond the MC alone and the first named people around it are stable enough for the player to push outward into the first Outpost foothold. Expressed as named state on committed scopes:

ActState.CurrentAct == 1
&& MainCharacter.CoreEstablished == true
&& Core.NamedResidents.Count >= Config.Act1.NamedResidentThreshold
&& Core.ShelterCapacity >= Core.NamedResidents.Count
&& Core.WatchAndWardingState == Sustained
&& Core.NamedResidents.All(r => r.SubsistenceState == Fed)
&& MainCharacter.Camp.HasScoutedAdjacentTerritories >= Config.Act1.ScoutedAdjacentThreshold

Named-state sources:

  • ActState.CurrentAct is the saga-scoped Act ladder index per ad-0010 line 53.
  • MainCharacter.CoreEstablished is the late-threshold Act 0 completion flag set when "Establish the Core" resolves; the rule is authored at gd-act-0-arrival-and-core.md line 163 ("Establishing the Core is the completion gate for Act 0").
  • Core.NamedResidents is the household / retinue list on the Core scope that gd-act-1-first-people.md lines 50-52 require to exist with named-character semantics.
  • Core.ShelterCapacity and Core.WatchAndWardingState derive from the structural shelter / watch / ward obligations named at gd-act-1-first-people.md lines 26-30.
  • MainCharacter.Camp.HasScoutedAdjacentTerritories is the "Nearby land has been scouted far enough to support the first outward foothold" condition at gd-act-1-first-people.md line 67.
  • Config.Act1.NamedResidentThreshold and Config.Act1.ScoutedAdjacentThreshold are UI-exposed Config fields with world-size-parameterized defaults; concrete values live in the Config surface, not in this predicate.

Triggered Events

When the predicate transitions to true, the ActProgression system fires:

  • OnActCompleted(ActProgressionArgs { PreviousAct = 1, NewAct = 2, TransitionDay = <current day> }) per ad-0010 lines 62-66.
  • OnActStarted(ActProgressionArgs { PreviousAct = 1, NewAct = 2, TransitionDay = <current day> }) per ad-0010 lines 62-66.

Both events carry trigger on_action per ad-0010 lines 81-84 and the on_action allowlist in .claude/rules/behavior-vocabulary.md.

Capability Unlocks

The Act 2 unlock surface is the first population-bearing Outpost-tier Settlement layer, as committed at gd-act-2-first-outpost.md lines 22-32. Concretely, on the Act 1 -> Act 2 transition:

  • Settlement founding becomes available (the first Outpost-tier Settlement can be designated against a scouted adjacent Territory).
  • Claim-and-footprint affordances become legible per the Footprint Rule at ../systems/gd-settlements-and-outposts.md.
  • The Core and Camp remain visible and active; the Outpost is an additional layer, not a replacement.

The first Outpost founding event is the Act 2 milestone; this gate authorizes only that Act 2 begins, not that the Outpost has been founded yet.

Runtime Backing Status

Status at this doc's acceptance time: contract-only.

  • Host/runtime owner: the predicate is read by legacy/v1/examples/valenar/Host/Systems/ActProgressionSystem.cs (proposed; authored in Wave 5a per ad-0010 lines 155-158).
  • Source/generated owner: the predicate body and its named-state reads land in Content/acts/systems.secs and the matching Generated stand-in in Wave 5a.
  • Read-model/UI owner: the saga-position UI surface in the React client reads ActState.CurrentAct per ad-0010 lines 169-172; no new UI surface is required by this gate.
  • Tests: <deferred-to-wave-5a> runtime-backing wave.
  • Illegal fallback behavior: if ActProgressionSystem cannot resolve any named-state input above, it throws IllegalTransitionException rather than silently advancing or holding. No calendar-elapsed fallback, no "if the player has been in Act 1 for a fixed duration" predicate, no hidden host-side counter.
  • Next closure wave: Wave 5a runtime-backing wave (per ad-0010 line 185).

Cross-References