feat(simulation): composable behavior engine — action+modifier+context primitives (#633)
Replaces flat culture×zone×role behavior strings with three-layer composition: BehaviorAction (role-generic), BehaviorModifier (culture coloring), BehaviorContext (situation gating). Assembly at NpcBlueprint instantiation. Backward compatible — falls back to legacy behaviors when primitives are empty. D-139 filed, Q-057 resolved. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+16
-1
@@ -433,6 +433,21 @@ How narrative, NPCs, and world content are created: content tiers, NPC generatio
|
||||
- **Resolves:** Q-057 (composable behavior generation), Q-012 (generation expansion method)
|
||||
- **Cross-reference:** [D-010](architecture.md#d-010) (information boundaries), [D-121](#d-121-voice-is-culture-driven--job-as-modifier) (culture-primary voice), [D-122](#d-122-all-npcs-generated--named-npcs-deferred) (all NPCs generated), [D-128](#d-128-culture-implicit-in-starting-location--krenn-system-equals-krenn-culture) (culture as generator input), [D-029](#d-029-population-entanglement-ratio--305020) (NPC tier model), [D-092](perception.md#d-092) (anchor lines)
|
||||
|
||||
### D-139: Composable behavior primitives — three-layer assembly model
|
||||
- **Date:** 2026-03-13
|
||||
- **Decision:** Observable NPC behaviors are composed from three layers rather than authored as flat strings per culture×zone×role combination. The three layers are:
|
||||
1. **BehaviorPrimitive** (on `RoleSpec`): role-generic physical stage directions (e.g., "moves freight containers", "runs diagnostics on a terminal"). Tagged with a `BehaviorContext` (OnShift/OffDuty/Social/Any) that gates when the behavior is eligible. Optional `modifier_hint` for category matching.
|
||||
2. **BehaviorModifier** (on `CultureProfile`): culture-specific clauses appended to actions (e.g., "with mechanical efficiency", "with a watchful eye"). Categorized for matching (work_style, demeanor, social, etc.).
|
||||
3. **Assembly function** (`assemble_behaviors`): at NpcBlueprint instantiation time, filters primitives by context, selects a culture modifier per primitive (preferring hint matches, falling back to any), concatenates `action + " " + modifier.clause`. No modifier → action text used as-is.
|
||||
- **Rationale:** The current model has `typical_behaviors: Vec<String>` on RoleSpec — flat strings per culture×zone×role. At ~50 behaviors × 4 roles × N zones × M cultures, this is O(roles × zones × cultures) custom content. Decomposition to primitives + modifiers reduces to O(roles + cultures) authored content. Assembly is deterministic via SimRng, so behavior output is reproducible for a given seed. The three-layer model maps directly to the existing CultureProfile/RoleSpec/NpcBlueprint data flow — no new serialization formats or pipeline stages.
|
||||
- **Implementation:** `server/src/npc/blueprint.rs` — `BehaviorPrimitive`, `BehaviorContext`, `BehaviorModifier` structs + `assemble_behaviors()` function. `RoleSpec.behavior_primitives: Vec<BehaviorPrimitive>` (serde default, backward-compatible). `CultureProfile.behavior_modifiers: Vec<BehaviorModifier>` (serde default). Legacy `typical_behaviors` field preserved until content migration complete.
|
||||
- **Migration path:** Copy team populates `behavior_primitives` on zone spec RON files and `behavior_modifiers` on culture RON files. Generator switches from `typical_behaviors` to `assemble_behaviors()` when primitives are present. Once verified equivalent for seed 42, legacy field can be removed.
|
||||
- **Source:** Sprint 26, ticket #633 (implements Q-057)
|
||||
- **Raised by:** Tyre (Technical Architect)
|
||||
- **Dissent:** None (design resolves the scaling problem identified in #630 sprint review)
|
||||
- **Resolves:** Q-057 (composable behavior generation — data structure definition)
|
||||
- **Cross-reference:** [D-138](#d-138-llm-re-voicing-pipeline-for-npc-voice) (resolved pipeline, this resolves data format), [D-121](#d-121-voice-is-culture-driven--job-as-modifier) (culture-primary voice), [D-122](#d-122-all-npcs-generated--named-npcs-deferred) (all NPCs generated)
|
||||
|
||||
---
|
||||
|
||||
*38 decisions. Last updated: 2026-03-07 (D-138 amended with Spike 2 findings: stdio IPC, tell differentiation results, double-prompt technique, ContentType::Factual, negative injectors moved to per-culture; D-123 amended; D-124 superseded — LLM Voice Pipeline Workshop)*
|
||||
*39 decisions. Last updated: 2026-03-13 (D-139 composable behavior primitives — Sprint 26 #633)*
|
||||
|
||||
Reference in New Issue
Block a user