Act 2 Gate Spec: First People to First Outpost
Context
This doc authors the gate predicate that authorizes the
ActState.CurrentAct: 2 -> 3 transition (the Act 2 First Outpost act
finishing and Act 3 Settlement 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(2)
followed by OnActStarted(3) when the predicate becomes true.
The source act doc is ./gd-act-2-first-outpost.md. The "Boundaries Into Act 3" section at lines 61-69 names the act's end state: a functioning Outpost foothold whose next question becomes settlement-scale growth. The binding rule from ad-0010 lines 93-99 applies: named state on committed scopes only.
Gate Predicate
Act 2 is complete when the first Outpost-tier Settlement has been founded, is alive under pressure, and is structurally distinct from the Core/Camp layer. Expressed as named state on committed scopes:
ActState.CurrentAct == 2
&& Realm.CoveredSettlements.Count >= 1
&& Realm.CoveredSettlements.Any(s => s.IsFirstOutpost == true)
&& Realm.CoveredSettlements.Single(s => s.IsFirstOutpost).FoundingState == Founded
&& Realm.CoveredSettlements.Single(s => s.IsFirstOutpost).ClaimedTerritories.Count >= Config.Act2.MinClaimedTerritories
&& Realm.CoveredSettlements.Single(s => s.IsFirstOutpost).CoreBuilding.ConstructionState == Functioning
Named-state sources:
ActState.CurrentActis the saga-scoped Act ladder index per ad-0010 line 53.Realm.CoveredSettlementsis the per-Realm collection of Settlement scope rows under this Realm; the Realm scope is committed at ad-0009 lines 49-55.Settlement.IsFirstOutpostis the per-Settlement flag identifying the first-founded Outpost-tier Settlement of the campaign, matching the gd-act-2-first-outpost.md lines 13-15 commitment that the first Outpost is the first population-bearing rung of the Settlement ladder.Settlement.FoundingStatederives from the Settlement scope's lifecycle (per gd-settlements-and-outposts.md "Footprint Rule") and reachesFoundedwhen the Outpost is no longer provisional.Settlement.ClaimedTerritoriesis the connected-footprint claim list per gd-settlements-and-outposts.md lines 26-37.Settlement.CoreBuilding.ConstructionStateis the Outpost's central building production state (settlement layer infrastructure per gd-act-2-first-outpost.md lines 50-58).Config.Act2.MinClaimedTerritoriesis a UI-exposed Config field with world-size-parameterized defaults; concrete values live in Config, not in this predicate.
The predicate does not require Realm.PolityRank to have advanced;
the Realm remains at PolityRank.Outpost through Act 2 and Act 3
per ad-0009 lines 75-80. PolityRank promotion to BannerNetwork is
the Act 3 -> Act 4 transition, not this one.
Triggered Events
When the predicate transitions to true, the ActProgression system
fires:
OnActCompleted(ActProgressionArgs { PreviousAct = 2, NewAct = 3, TransitionDay = <current day> }).OnActStarted(ActProgressionArgs { PreviousAct = 2, NewAct = 3, TransitionDay = <current day> }).
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 3 unlock surface is broad settlement-scale play, as committed at gd-act-3-settlement.md lines 24-33. Concretely, on the Act 2 -> Act 3 transition:
- District grouping and designation logic become structurally legible per gd-act-3-settlement.md lines 26-27.
- Settlement-buildings and local economic chains become recurring priorities (gd-act-3-settlement.md lines 28-29).
- Training, recovery, and specialized production compete for labor and space (gd-act-3-settlement.md lines 30-31).
This gate authorizes only that Act 3 begins; the broad consolidation work and the Banner Network-ready state are Act 3 outcomes resolved by the next gate.
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 lives in
Content/acts/systems.secsand the matching Generated stand-in. - Read-model/UI owner: the React client's saga-position surface
reads
ActState.CurrentAct; the Settlement screen separately surfaces founding state per ../ux/gd-settlement-screen.md. - Tests:
<deferred-to-wave-5a>runtime-backing wave. - Illegal fallback behavior: if any named-state input cannot resolve
through the 6-phase channel pipeline, the system throws
IllegalTransitionExceptionrather than advancing or holding. No calendar-elapsed fallback, no time-since-founding fallback, no "first Settlement exists for a fixed tick window" heuristic. - Next closure wave: Wave 5a runtime-backing wave (per ad-0010 line 185).