Labor and Capacity
This page owns Valenar's labor primitive: the typed worker pool partition inside a Settlement, the channels that surface labor demand and shortage against that pool, and the Province-level aggregation that the dynamic quest pressure model and Crown-scale planning surfaces consume. It is the shared input layer for building production, Force recruitment, and polity promotion gates.
Scope
This doc owns:
- The vocabulary partitioning settlement Population into worker classes (AvailableWorkers, DependentPopulation, SpecialistWorkers).
- The settlement-scope channels that surface labor demand and shortage (AssignedWorkers, LaborDemand, UnfilledLabor, LaborShortageSignal, CriticalShortageSignal, IdleLabor, OverassignedLabor).
- The Province-scope Contributed aggregate that rolls those Settlement-
scalar shortage signals into a Province-level contributory channel
(
ProvinceLaborShortage). - The source-fact contract the dynamic quest pressure model reads to surface labor-shortage missions and escalation triggers.
This doc does NOT own:
- Settlement-tier promotion thresholds (owned by gd-realm-ranks-and-polity.md).
- Settlement-tier footprint and connectivity rules (owned by gd-settlements-and-outposts.md).
- Per-building employment slot authoring (owned by gd-settlement-buildings-economy.md).
- Force lifecycle (owned by gd-forces.md); Force recruitment merely consumes the labor signals defined here.
- Garrison strength and defense composition (owned by gd-defense-zones.md).
Labor Vocabulary
The following terms are the canonical labor surface across Valenar docs, Generated channel declarations, and the dynamic quest pressure source- fact contract. Each term has exactly one meaning; aliasing is forbidden.
- Population — total resident headcount on a Settlement. Already
surfaced as
Population_ChannelinGenerated/Declarations.cs. The total is partitioned into AvailableWorkers and DependentPopulation by the settlement model below; it is not directly assigned. - AvailableWorkers — Population members eligible to fill an employment slot. Adults of working age, not currently bedridden, not permanently assigned to a Specialist role.
- DependentPopulation — Population members not eligible to be assigned to general employment slots: children, elders, and permanently incapacitated residents. DependentPopulation contributes to housing and food demand but never to AvailableWorkers.
- SpecialistWorkers — AvailableWorkers permanently bound to a Specialist role (Wardkeeper, Forge-Master, Ritualist, named-character retinue). Specialists are not pulled into general AssignedWorkers and are tracked separately so the player sees which labor capacity is locked.
- AssignedWorkers — AvailableWorkers currently occupying a building
employment slot. Per building, this is the count the settlement
production layer reads when computing throughput. The existing
EmploymentRatiochannel on the Building scope already carries the effective-ratio resolution; AssignedWorkers is the count input feeding that ratio. - LaborDemand — sum of building employment-slot openings on a Settlement. A building with three open Lumberyard slots and one open Granary slot contributes 4 to LaborDemand. LaborDemand is a Settlement- scope Contributed channel aggregated from per-building slot declarations.
- UnfilledLabor —
max(0, LaborDemand - AssignedWorkers - (AvailableWorkers - AssignedWorkers)). Reduces to `max(0, LaborDemand- AvailableWorkers)` and represents employment-slot openings that cannot be filled because the AvailableWorkers pool is exhausted. UnfilledLabor is a Settlement scalar channel.
- LaborShortageSignal — a discrete signal raised when UnfilledLabor exceeds the settlement's first-tier shortage threshold (authored as a clamp / source data input through the 6-phase channel pipeline, never as a magic-threshold aggregator). LaborShortageSignal is a Settlement scalar channel and a dynamic-quest-pressure source fact.
- CriticalShortageSignal — a discrete signal raised when UnfilledLabor exceeds the settlement's second-tier critical threshold, also authored as clamp / source data. CriticalShortageSignal is a Settlement scalar channel and a higher-urgency dynamic-quest-pressure source fact.
- IdleLabor —
max(0, AvailableWorkers - AssignedWorkers - LaborDemand). Surfaces when AvailableWorkers exceeds both AssignedWorkers and outstanding LaborDemand: the settlement has workers with no employment slot to fill. IdleLabor is a Settlement scalar channel; it never becomes a dynamic-quest-pressure source fact by itself but feeds the labor-surplus side of polity ceilings. - OverassignedLabor —
max(0, AssignedWorkers - AvailableWorkers). Surfaces only when the host attempts to assign more workers than the AvailableWorkers pool can supply. The illegal fallback (silent overrun, partial-fill mask, ratio cap) is forbidden: a Settlement that has fewer AvailableWorkers than AssignedWorkers throws an explicit runtime error against the labor-assignment surface (see Runtime Backing Status below). OverassignedLabor is the channel that exposes the inconsistency for diagnostic surfaces. - ProvinceLaborShortage — Province-scope Contributed channel
aggregating LaborShortageSignal and CriticalShortageSignal across the
Settlements within the Province. Resolved through the 6-phase channel
pipeline (
base->additive->multiplicative->HardOverride->clamp->return). The Crown-scale and dynamic-quest-pressure surfaces read ProvinceLaborShortage; per-Settlement UI reads the Settlement-scope signals directly.
Settlement Labor Model
A Settlement's labor capacity resolves in three stages and is read by production, recruitment, and polity surfaces in the same form.
- Population partition. Per-tick (or per-population-event)
resolution partitions
Population_Channelinto DependentPopulation, SpecialistWorkers, and AvailableWorkers. The partition is a function of the Settlement's authored age/role distribution and current modifiers; it is not a free-floating allocator the player tunes directly. - Demand resolution. Each Building owned by the Settlement
contributes its open employment-slot count to LaborDemand through a
Contributedchannel source on the Building's activation root. The existingEmploymentRatiochannel on Building reads AssignedWorkers against authored slot capacity; this doc adds the missing Settlement-scope rollup that aggregates demand across buildings. - Assignment and shortage signals. The host assigns workers from AvailableWorkers into AssignedWorkers per building. UnfilledLabor, LaborShortageSignal, CriticalShortageSignal, IdleLabor, and OverassignedLabor are derived from the three quantities above and resolved through the 6-phase channel pipeline. Threshold constants for the two shortage signals are clamp inputs, not architectural constants — "Never tune parameters as a substitute for fixing architecture" applies: the architecture is the pipeline, the thresholds are data.
The partition + demand + shortage trio is the only labor surface live
SECS systems and the host runtime read. Older "settlement.workers"
free-form fields or ad-hoc Headcount aliases are not part of this
contract.
Building Production Interaction
The existing EmploymentRatio channel on the Building scope is the
canonical interface between AssignedWorkers and per-building production.
It already resolves through the 6-phase channel pipeline. This doc does
NOT introduce a parallel building-side labor channel; the production
layer continues to read EmploymentRatio and the throughput formulas
authored in
gd-settlement-buildings-economy.md.
What changes is the upstream:
- Per-building employment-slot capacity authoring is the source for LaborDemand contributions to the parent Settlement.
- AssignedWorkers per building is the source the
EmploymentRatiochannel reads. - When LaborShortageSignal or CriticalShortageSignal is raised on the
parent Settlement, production reads no special compensation modifier —
the shortage simply manifests as reduced
EmploymentRatioon the buildings that could not be staffed. The signal exists for the dynamic-quest-pressure model and Crown-scale UI, not as a side-channel production penalty.
Force Recruitment Interaction
Force recruitment draws from AvailableWorkers. The interaction is:
- A Force in
Forminglifecycle state (see gd-forces.md "Force Lifecycle") binds a recruitment contract against the originating Settlement(s). - The Crown-scale recruit-garrison activity is gated by LaborShortageSignal: while the originating Settlement is raising LaborShortageSignal, the recruitment activity is blocked from consuming further AvailableWorkers without an explicit player override.
- CriticalShortageSignal escalates the block to a hard refusal until the shortage clears.
- A Force in
Operating,Returning,Disbanding, orLostlifecycle state does not draw from AvailableWorkers; onlyFormingdoes. Detachment absorption back into a Settlement at Disbanding returns AvailableWorkers via the standard Population partition, not via a parallel labor channel.
This is the contract the dynamic quest pressure model also relies on: recruitment that violates a CriticalShortageSignal is a pressure escalation source, not a free choice the player can ignore.
Polity Gate Interaction
Settlement-tier promotion is gated by Population thresholds owned in gd-realm-ranks-and-polity.md. Labor channels do not change promotion gating directly. They affect promotion in two indirect ways:
- A Settlement raising sustained CriticalShortageSignal cannot reach the effective Population required for the next tier, because shortage reduces production, which constrains the food, housing, and ward budgets the polity-rank ladder depends on.
- The Crown-scale polity layer reads
ProvinceLaborShortageas a contributing input to Crown-scale recruitment ceilings (Crown ceilings on Force creation across the Realm).
The promotion threshold itself stays in the polity doc; this doc defines only the labor surface that promotion indirectly consumes.
Dynamic Quest Pressure Source-Fact Contract
LaborShortageSignal and CriticalShortageSignal become source facts in the dynamic-quest-pressure model (see gd-dynamic-quest-pressure-model.md "Pressure And Escalation Triggers"). The contract is:
- The pressure delta (rising LaborShortageSignal on a Settlement that was previously below the first-tier threshold) emits a source fact, not the absolute signal value.
- CriticalShortageSignal emits a higher-urgency source fact than LaborShortageSignal; sustained CriticalShortageSignal across a defined number of ticks escalates urgency per the dynamic-quest-pressure escalation rules.
- ProvinceLaborShortage emits a Province-level source fact for Crown- scale Mission generation; the per-Settlement signals stay local to per-Settlement Mission generation.
- The dynamic-quest-pressure source-fact emit rules mirror the pressure- channel emit rules documented in gd-corruption-reclamation.md "Quest Hooks" — deltas, not absolute values, drive missions.
Runtime Backing Status
Status at this doc's acceptance time: contract-only.
- Host/runtime owner:
legacy/v1/examples/valenar/Host/Data/SettlementData.csremains the host-data anchor for Population; the newAvailableWorkers,DependentPopulation,SpecialistWorkers,AssignedWorkers,LaborDemand,UnfilledLabor,LaborShortageSignal,CriticalShortageSignal,IdleLabor,OverassignedLaborSettlement-scope channels and theProvinceLaborShortageProvince-scope channel are authored in the Wave 5a runtime-backing wave (parallel with ad-0008 labor + pressure runtime backing). - Generated/.secs owner: new channel declarations are authored under
legacy/v1/examples/valenar/Content/settlements/channels.secs(or the equivalent existing Settlement channel file) andlegacy/v1/examples/valenar/Content/provinces/channels.secsfor the Province aggregate. MatchingGenerated/declarations land in the same Wave 5a wave. - Read-model/UI owner: per-Settlement UI reads the Settlement-scope
signals; the Crown-scale strategic surface reads
ProvinceLaborShortage. Authored in the runtime-backing wave's UI follow-up. - Tests: deferred to the Wave 5a runtime-backing wave.
- Known gaps: the exact shortage-threshold clamp values per Settlement
tier; the per-building employment-slot authoring (currently scoped
by
EmploymentRatioonly); the Specialist-role authoring for named characters; the labor-side response to a sustained CriticalShortage (player UI prompt vs. autonomous reaction). - Current backing today:
Generated/Declarations.csdeclaresPopulation_Channel(line 457) andGarrison(line 461) on the Settlement scope;EmploymentRatioexists on the Building scope (lines 652 and 1404). None of the new Settlement-scope or Province-scope labor channels exist yet. - Illegal fallback behavior: a Settlement that has fewer AvailableWorkers than AssignedWorkers must throw an explicit runtime error against the labor-assignment surface, NOT silently cap the assignment, NOT silently partition the partial fill, and NOT default OverassignedLabor to zero. The OverassignedLabor channel is the legitimate diagnostic surface; the underlying assignment must fail loud rather than silently drift. Similarly, attempting to assign AvailableWorkers beyond the pool without OverassignedLabor signaling the inconsistency is forbidden.
- Next closure wave: Wave 5a runtime-backing wave (parallel with ad-0008 labor + pressure runtime backing per resolver R17).
Glossary Propagation
The following terms MUST land in gd-glossary.md, gd-canon.md, and
README.md:
AvailableWorkers,DependentPopulation,SpecialistWorkers(Population partition vocabulary).AssignedWorkers,LaborDemand,UnfilledLabor,IdleLabor,OverassignedLabor(Settlement-scope labor channels).LaborShortageSignal,CriticalShortageSignal(Settlement-scope shortage signals; also dynamic-quest-pressure source facts).ProvinceLaborShortage(Province-scope contributory aggregate).
Population is already glossary-surfaced via the Settlement scope and
is not re-introduced here.
AAA Precedent
The labor primitive draws on four AAA references:
- Manor Lords (primary) — the residents-vs-workers partition with per-burgage employment slots and an explicit IdleFamilies signal is the closest realization of the Population / AvailableWorkers / AssignedWorkers / IdleLabor split at multiple capacity tiers.
- Banished (secondary) — profession-typed worker slots with explicit shortage warnings is the precedent for SpecialistWorkers as a distinct partition from general AvailableWorkers.
- Anno 1800 (secondary) — the bidirectional "jobs need residents / residents need jobs" reciprocity is the precedent for surfacing both UnfilledLabor (jobs lacking workers) and IdleLabor (workers lacking jobs) as first-class signals rather than one-sided shortage.
- RimWorld (secondary) — the PriorityWork skill-typed labor pool is the precedent for partitioning AvailableWorkers into a Specialist pool that is not pulled into general assignment.
The combination of two-tier shortage (LaborShortageSignal + CriticalShortageSignal) with Province-level aggregation matches the ad-0008 ThreatSource / ProvinceThreatPressure two-tier shape — labor and pressure surface through the same architectural pattern so the dynamic-quest-pressure model reads both through one mechanism.