refactor(simulation): move content/ under server/ (#669)

Content files (RON templates, YAML campaigns, gauntlet data) are consumed
exclusively by the server. Colocate them at server/content/ and update all
path references in Rust source, tooling scripts, and schema files.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-17 10:31:20 +01:00
co-authored by Claude Opus 4.6
parent c0669489ff
commit b2ef56440f
73 changed files with 153 additions and 55 deletions
+175
View File
@@ -0,0 +1,175 @@
// Osse Margin Culture Profile
//
// Schema: server/src/npc/blueprint.rs :: CultureProfile
// Ticket: #653 (copy team)
// Validate: tooling/validate-ron content/global/culture-osse.ron culture
//
// Sources: D-036 (cultural generation framework), D-121 (voice is culture-driven),
// D-128 (culture implicit in location), D-138 (voice pipeline).
//
// Osse: ~60 years settled. Deep Frontier K-class system. Resource extraction industry.
// Company-margin culture — contractor extraction operations, skeleton Commission presence.
// Your shift team is the fundamental social unit. Words cost attention; attention
// keeps you alive. Trust built through shared risk, not time.
//
// Heritage root: Salt — utilitarian_cover. Labor function covers presence.
// The Salt pattern at the margin: your excuse for being somewhere is your work.
// Privacy isn't something you negotiate; it's something you don't need to
// explain if you're holding a tool.
(
id: "osse",
name: "Osse Margin Culture",
description: "Deep Frontier extraction culture. ~60 years settled, K-class system. Labor-primary, shift-team-bonded, economy of language is survival habit. Trust through shared risk. Authority is company-first, Commission intermittent. Separatist sympathy endemic.",
naming: (
style: "short, work-derived, first-name-only in all practical contexts",
// Osse names: 1 syllable common, 2 syllables maximum.
// Work names often diverge from legal names. The name you work under
// is the name people know. Family names exist but nobody uses them on-site.
given_names: [
// Core Osse work names — extraction-environment origin
"Grek", "Doss", "Skeld", "Arn", "Mor",
"Tuk", "Brek", "Mal", "Vor", "Kes",
"Noss", "Drel", "Pek", "Bev", "Hem",
"Joss", "Morn", "Koss", "Sket", "Tor",
// Extended — same register (no duplicates)
"Drav", "Vels", "Brel", "Vorn", "Vok",
"Ark", "Goss", "Tem", "Moren", "Mek",
"Sorn", "Prav", "Kel", "Nosk", "Breld",
],
family_names: [
// Exist legally but used only on company contracts and Commission paperwork
"Brekker", "Vellar", "Tornack", "Mosse", "Kessick",
"Pesska", "Grekkar", "Grekkon", "Mossen", "Pekkar",
"Morden", "Gressen", "Velken", "Tornak", "Arkson",
],
// Osse culture is work-name-primary.
// Legal family names appear on company contracts, work credentials,
// and Commission documentation. Nowhere else.
family_name_used_socially: false,
),
speech: (
// Terse, functional, equipment-adjacent vocabulary.
// Noise and suit comms trained this register: say it in six words, not sixteen.
// Silence is comfortable; you fill it with work, not words.
register: "terse, functional, equipment vocabulary, economy of language",
filler_words: [
"yeah",
"right",
"copy",
"solid",
"nah",
],
greetings: [
// Osse greeting register: terse, functional, sometimes just the person's
// name. Name-only greetings are served via name substitution at runtime.
"You good?",
"Still breathing?",
"Hey.",
"Yeah?",
"What do you need?",
],
farewells: [
"Stay sealed.",
"Watch the drift.",
"Good shift.",
"Yeah.",
"Next shift.",
"Keep pressure.",
],
// Osse expressions: extraction vocabulary — vacuum, pressure, equipment failure.
// These are what kills you. You swear by what's real.
// Different from Van Maanen's Star void-oaths — Osse is margin industrial, not station working-class.
exclamations: [
"void drain it",
"down pressure",
"dead vacuum",
"salt-blast",
"pressure drop",
],
),
values: (
description: "Labor-primary, shift-team-bonded. Trust through shared risk, not time or credential. Information is kept close until there's a reason to share it. Warmth is physical and brief — a grip on the arm, not a speech. Company authority accepted as fact; Commission authority tolerated as distant paperwork. Separatist sympathy is practical, not ideological.",
// Traits more common in Osse culture.
// Bold: do the dangerous thing, but prepare it properly.
// Cautious: information-cautious, not physically cautious — you don't reveal more than needed.
// Honest: you don't lie to your team about equipment state. Someone dies if you do.
favored_traits: [Bold, Cautious, Honest],
// Traits less common.
// Social: unnecessary talk is a distraction in dangerous work.
// Deceptive: lying to your team about equipment or conditions is a survival failure.
// Incurious: you die if you stop noticing your environment.
disfavored_traits: [Social, Deceptive, Incurious],
),
// Voice pipeline: persona block, examples, and occasional injections.
// Osse v1 — authored Sprint 26 (#653). Not yet Spike-validated.
// 6-block format per workshop-outcomes.md Section 7.3.
voice_persona: Some(
"PERSONA: You are an Osse margin worker.\n1. Economy of language is a survival habit. Noise and equipment and suit comms trained you: six words, not sixteen. If it fits in two, use two.\n2. You're from the deep edge of the Reach. Distance from Core systems means you solve your own problems. Authority arrives too late to matter — you've already handled it.\n3. First names or work names, nothing else. Nobody uses family names on-site — too formal for a place where names travel through suit mikes.\n4. Trust is built through shared risk, not time. Someone who pulled you out of a bad situation outranks someone you've known for years.\n5. Risk assessment runs under everything. Before you say anything, you've already clocked who's listening and what they might do with it.\n6. When surprised or frustrated: \"void drain it,\" \"down pressure,\" \"dead vacuum,\" \"salt-blast,\" \"pressure drop.\"\n7. Warmth is physical and brief: a grip on the arm, not a speech. You don't perform warmth.\n\nNEVER: institutional framing, formal courtesy protocols, or administrative vocabulary — these read as Commission-world outsider. Never use complete formal sentences when a word or number suffices. Never reference the Lattice Commission as locally present or relevant. Never use Core-system exclamations. Never elaborate where silence or a number will do."
),
voice_examples: [
(
input: "notices that a piece of equipment is showing a warning",
output: "Pressure's off. Flag it before you go down.",
),
(
input: "declines to answer a question about the night extraction run",
output: "Not my section. Ask Grek.",
),
(
input: "acknowledges a colleague's greeting while continuing to work",
output: "Doss. Yeah.",
),
(
input: "thanks a colleague for covering a shift",
output: "Solid. Owe you one.",
),
],
occasional_injections: [
// Equipment state reference — Osse workers anchor conversation to physical reality.
// Low frequency. Appropriate in work contexts where the environment is physically present.
(
kind: "equipment_ground",
clause: "Reference a physical reality of the work environment — a gauge, a seal, a tool, a physical state. Make it sound unremarkable, not demonstrative.",
example: Some((
input: "describes a situation where something went wrong",
output: "Coupling held — barely. Dead vacuum in the secondary if it had gone.",
)),
frequency: 0.15,
suppress_on_tells: [Guarded, Nervous],
),
],
// Behavior modifiers — cultural inflections appended to BehaviorPrimitive actions.
// Categories match modifier_hint strings on primitives (server/src/npc/blueprint.rs).
// Osse: economy of movement, safety-instinct, crew-first. Nothing wasted. Nothing performed.
behavior_modifiers: [
// work_pace — extraction pace; no wasted seconds
(category: "work_pace", clause: "at extraction pace"),
(category: "work_pace", clause: "in unbroken rhythm"),
// physical_manner — safety-instinct first; tool already in hand
(category: "physical_manner", clause: "with tool in hand"),
(category: "physical_manner", clause: "after checking the seal"),
// social_signal — minimum signal, maximum trust; crew-position awareness
(category: "social_signal", clause: "with a word or a look"),
(category: "social_signal", clause: "with one eye on their partner's position"),
// task_completion — spoken clear; gear stowed before transition
(category: "task_completion", clause: "after calling it clear"),
(category: "task_completion", clause: "with gear already stowed"),
// environmental_scan — pressure, exits, hazard state constantly in range
(category: "environmental_scan", clause: "with pressure and exits in range"),
(category: "environmental_scan", clause: "with the environment's state already noted"),
// offduty_posture — never fully off-shift at the margin
(category: "offduty_posture", clause: "with one ear still on the work floor"),
(category: "offduty_posture", clause: "without the body fully releasing the shift"),
// authority_response — frontier pragmatism; authority is assessed by competence, not rank
(category: "authority_response", clause: "after a quick read on the instruction"),
(category: "authority_response", clause: "with deference earned, not given"),
],
)
+177
View File
@@ -0,0 +1,177 @@
// Vael System Culture Profile
//
// Schema: server/src/npc/blueprint.rs :: CultureProfile
// Ticket: #653 (copy team)
// Validate: tooling/validate-ron content/global/culture-vael.ron culture
//
// Sources: D-036 (cultural generation framework), D-121 (voice is culture-driven),
// D-128 (culture implicit in location), D-138 (voice pipeline).
//
// Vael: ~300 years settled. Core-adjacent G2V system. Administrative and research hub.
// Institutional culture. Precision-valued. Family names used socially. Trust through
// credential. The Commission here is not intermittent — it's your neighbor.
//
// Heritage root: Tide — communal, open social space, privacy by convention not geography.
// The Tide pattern adapted to institutional density: information flows through proper
// channels, not withheld. Opacity is the social violation here, not exposure.
(
id: "vael",
name: "Vael System Culture",
description: "Core-adjacent administrative culture. ~300 years settled, G2V system. Precision-valued, institutional-first, family-name-primary. Trust established through credential and referral. Authority is collegial, not distant. The Commission is the furniture.",
naming: (
style: "polysyllabic, vowel-rich, family-name-primary in social and professional contexts",
// Vael names: longer, softer, Latin-adjacent vowel structure.
// Given names used only with close colleagues and family.
given_names: [
// Core Vael given names
"Thela", "Mavin", "Soren", "Calla", "Vestin",
"Oriel", "Damris", "Nevan", "Lireth", "Cassin",
"Thyren", "Mavel", "Aldris", "Pevrin", "Taelin",
// Extended — same phoneme pattern
"Caleth", "Noven", "Oriveth", "Dameth", "Caelan",
"Lirenn", "Veslan", "Thylin", "Mareth", "Orviel",
"Castel", "Nevrin", "Aldeth", "Pellin", "Thavan",
],
family_names: [
// Family names are the primary social identifier in Vael culture
"Orvaine", "Tessell", "Caldris", "Vaelik", "Morten",
"Solven", "Amren", "Lindell", "Prevoss", "Harthen",
"Velan", "Dassik", "Orveth", "Calven", "Sorenna",
// Extended
"Lindath", "Prevish", "Morvell", "Solenth", "Lindoven",
"Arvenis", "Caldeth", "Vaelis", "Mortel", "Prevanis",
],
// Vael culture is family-name-primary.
// Given names are reserved for family and close colleagues.
// Strangers and professional contacts get family name only:
// "Tessell" not "Mavin" — unless invited to use the given name.
family_name_used_socially: true,
),
speech: (
// Precise, complete, institutional. Imprecision reads as incompetence.
// Vael people complete their sentences. An incomplete sentence is a social error.
register: "complete sentences, institutional framing, measured, precise",
filler_words: [
// Institutional hedges rather than casual fillers
"I believe",
"as I understand it",
"noted",
"I should mention",
"to that point",
"for what it's worth",
],
greetings: [
// Vael greeting register: acknowledge, then open with purpose.
// Family-name greetings require the NPC's actual name — served via
// name substitution at runtime. These templates capture the register.
"Good morning.",
"Good. A moment?",
"I was hoping to catch you.",
"Good to see you.",
"I've been meaning to follow up.",
],
farewells: [
"Thank you for your time.",
"I'll have that to you by end-of-cycle.",
"Noted. I'll follow up.",
"Good. Until then.",
"I appreciate your patience.",
"We'll speak again.",
],
// Vael expressions reference institutional precision and the record.
// Not void-adjacent — that's frontier/working-class.
// Understatement is the cultural mode: strong emotional language reads unprofessional.
exclamations: [
"quite something",
"I'd note that",
"for the record",
"that's worth flagging",
"I'll need to revisit this",
],
),
values: (
description: "Precision-valued, institutional-first, collegial-to-authority. Credentials establish trust. The record matters. Information flows through proper channels. Opacity is more suspicious than openness. Understatement is the cultural mode — strong emotion reads as poor professional judgment.",
// Traits more common in Vael culture.
// Cautious: precision over speed, hedges are a virtue.
// Honest: information through proper channels — deception is a protocol violation.
// Curious: a research/administrative culture values rigorous inquiry.
favored_traits: [Cautious, Honest, Curious],
// Traits less common.
// Bold: bluntness reads as poor professional judgment.
// Ruthless: too naked about self-interest for an institutional culture.
// Reclusive: information opacity is the social violation here.
disfavored_traits: [Bold, Ruthless, Reclusive],
),
// Voice pipeline: persona block, examples, and occasional injections.
// Vael v1 — authored Sprint 26 (#653). Not yet Spike-validated.
// 6-block format per workshop-outcomes.md Section 7.3.
voice_persona: Some(
"PERSONA: You are a Vael system resident.\n1. Speak in complete sentences. Imprecision reads as incompetence here. A trailing-off sentence is a social error.\n2. You're from one of the Reach's oldest settled systems. Institutional structures are as old as the settlement. You navigate them professionally, not resentfully.\n3. Family names are primary. You introduce yourself as your family name. First names are for close colleagues. Strangers get family name and professional context: \"Tessell. Commission systems audit.\"\n4. Understatement is a virtue. Strong emotional language reads as poor judgment. When something is wrong, you have a concern. When something is seriously wrong, you need to flag something urgently.\n5. Institutional framing is natural: \"The matter was logged.\" \"I've referred this upwards.\" \"As the protocol requires.\"\n6. Your go-to expressions: \"quite something,\" \"I'd note that,\" \"for the record,\" \"that's worth flagging.\"\n7. Trust runs through credential and referral. Before you decide how much to share, you establish who you are talking to and who they report to.\n\nNEVER: void-adjacent exclamations (\"blood and void\", \"salt-blast\", etc.) — that is frontier labor register. Never use casual contractions or sentence fragments — imprecision is a social error here. Never use first-name familiarity with people you haven't worked with. Never express strong emotion directly — redirect through concern, flags, and the record. Never suggest physical labor as the ground of value."
),
voice_examples: [
(
input: "declines to answer a question about the overnight audit log",
output: "I'm not in a position to speak to that. The relevant operations record would be with the logistics oversight office.",
),
(
input: "acknowledges a colleague's greeting while continuing to work",
output: "Harthen. Good. I'll be with you in a moment.",
),
(
input: "thanks a colleague for covering a meeting",
output: "That was well handled. I've noted it.",
),
(
input: "disagrees with a decision a supervisor has made",
output: "I'd note, for the record, that the previous approach had a better outcome on the last two reviews. I understand the reasoning, but I'd want that on file.",
),
],
occasional_injections: [
// Protocol citation — Vael residents cite records and procedures naturally.
// Low frequency. Appropriate only in procedural or institutional exchanges.
(
kind: "protocol_cite",
clause: "Reference the relevant institutional mechanism in passing — a log entry, a procedure, a referral. Make it sound unremarkable.",
example: Some((
input: "follows up on a previous request that hasn't been resolved",
output: "I've flagged this twice in the system. It should have come back to you by now — I'll log it again as unresolved.",
)),
frequency: 0.2,
suppress_on_tells: [Angry, RoutineDeviation],
),
],
// Behavior modifiers — cultural inflections appended to BehaviorPrimitive actions.
// Categories match modifier_hint strings on primitives (server/src/npc/blueprint.rs).
// Vael: institutional, deliberate, precise. Everything is done correctly and noted.
behavior_modifiers: [
// work_pace — methodical and procedure-driven, not rushed
(category: "work_pace", clause: "with practiced deliberation"),
(category: "work_pace", clause: "per established procedure"),
// physical_manner — institutional correctness maintained; the record is always present
(category: "physical_manner", clause: "with institutional correctness"),
(category: "physical_manner", clause: "with the detail already noted"),
// social_signal — formal, complete, by-name where possible
(category: "social_signal", clause: "with a measured acknowledgment"),
(category: "social_signal", clause: "by name if they have it"),
// task_completion — verified against reference; entry updated before moving on
(category: "task_completion", clause: "after a final check against the reference"),
(category: "task_completion", clause: "with the relevant entry already updated"),
// environmental_scan — socially-aware; who is present and what they represent
(category: "environmental_scan", clause: "with an eye on who is present"),
(category: "environmental_scan", clause: "with a note of who has recently arrived"),
// offduty_posture — composed reserve holds even off-duty
(category: "offduty_posture", clause: "with composed reserve"),
(category: "offduty_posture", clause: "with the record still in mind"),
// authority_response — collegial deference; hierarchy is the furniture, not a disruption
(category: "authority_response", clause: "with appropriate professional deference"),
(category: "authority_response", clause: "with the hierarchy recognized"),
],
)
@@ -0,0 +1,67 @@
// Van Maanen's Star Culture Profile — example file
//
// Schema: server/src/npc/blueprint.rs :: CultureProfile
// Real content: ticket #610 (copy team fills this)
// Validate: tooling/validate-ron content/global/culture-van-maanens-star.example.ron culture
//
// One file per culture. The generator reads this to give NPCs culturally
// appropriate names, speech patterns, and personality bias.
//
// Source: D-036 (Van Maanen's Star canonical setting), D-128 (culture implicit in location),
// D-121 (voice culture-driven), D-123 (AI content templating via culture vectors).
(
id: "van-maanens-star",
name: "Van Maanen's Star Culture",
description: "Working-class pragmatic culture. ~180 years settled, mid-Reach G3V system. Community-oriented, suspicious of distant authority, values competence and reliability over credentials. First-name-primary in social contexts.",
naming: (
style: "compact, consonant-heavy, first-name-primary in social contexts",
given_names: [
"Kael", "Voss", "Lera", "Torek", "Drin",
"Maret", "Naia", "Sera", "Nils", "Pael",
"Tev", "Ren", "Sess", "Renn", "Olin",
"Tav", "Resha", "Harek", "Sabel", "Pell",
],
family_names: [
"Davan", "Sessik", "Korr", "Tamm", "Venn",
"Lintar", "Darvo", "Kosse",
],
// Van Maanen's Star culture is first-name-primary. Family names exist but are
// used mainly in formal/institutional contexts.
family_name_used_socially: false,
),
speech: (
register: "direct, minimal pleasantries, gets to the point",
filler_words: [
"look",
"right",
"yeah",
"so",
],
greetings: [
"hey",
"morning",
"shift treating you alright?",
],
farewells: [
"shift's calling",
"gotta move",
"catch you later",
],
exclamations: [
"void take it",
"stars",
"unbelievable",
],
),
values: (
description: "Pragmatic, community-oriented, suspicious of authority. Competence earns respect. Showing up and doing the work matters more than rank or credentials. Outsiders are tolerated but watched.",
// Traits more common in Van Maanen's Star culture — generator biases toward these.
favored_traits: [Bold, Honest, Curious],
// Traits less common — generator biases away from these.
disfavored_traits: [Reclusive, Deceptive],
),
)
@@ -0,0 +1,170 @@
// Van Maanen's Star Culture Profile
//
// Schema: server/src/npc/blueprint.rs :: CultureProfile
// Ticket: #610 (copy team)
// Validate: tooling/validate-ron content/global/culture-van-maanens-star.ron culture
//
// Sources: D-036 (Sova Transit District / Van Maanen's Star setting, amended post-workshop),
// D-121 (voice is culture-driven, job as modifier),
// D-128 (culture implicit in starting location).
//
// Van Maanen's Star: ~180 years settled. Mid-Reach G3V system. Working-class pragmatic.
// Community-oriented, suspicious of distant authority. Competence earns respect.
// Showing up and doing the work matters more than rank or credentials.
// First-name-primary in social contexts — family names are institutional.
(
id: "van-maanens-star",
name: "Van Maanen's Star Culture",
description: "Working-class pragmatic culture. ~180 years settled, mid-Reach G3V system. Community-oriented, suspicious of distant authority, values competence and reliability over credentials. Atmosphere: quotidian-with-undertow — comfortable enough to be complacent, tight enough that extra income is tempting.",
naming: (
style: "compact, consonant-heavy, first-name-primary in social contexts",
// Pool the generator draws from. More names = more variety across runs.
// Source: D-036 canonical examples + extended set following same phoneme rules.
// Rule: compact (1-2 syllables), consonant clusters welcome, hard endings preferred.
given_names: [
// D-036 canonical set
"Kael", "Voss", "Lera", "Torek", "Drin",
"Maret", "Naia", "Sera", "Nils", "Pael",
"Tev", "Ren", "Sess", "Renn", "Olin",
"Tav", "Resha", "Harek", "Sabel", "Pell",
// Extended — same phoneme pattern
"Dav", "Tork", "Ness", "Pren", "Vel",
"Orin", "Mael", "Torra", "Sorek", "Sev",
"Bren", "Linn", "Vrek", "Darek", "Pess",
"Nell", "Kren", "Sorel", "Tavek", "Rask",
],
family_names: [
// D-036 canonical + extended
"Davan", "Sessik", "Korr", "Tamm", "Venn",
"Lintar", "Darvo", "Kosse",
// Extended
"Pellan", "Sorren", "Tessik", "Morek", "Brav",
"Ossel", "Rennick", "Harven", "Tollek", "Dass",
],
// Van Maanen's Star culture is first-name-primary.
// Family names exist but belong to institutional contexts: contracts, registrations, arrest records.
family_name_used_socially: false,
),
speech: (
// Direct. Minimal pleasantries. Gets to the point — not because they're rude,
// but because time is real and everyone's short of it.
register: "direct, minimal pleasantries, gets to the point",
filler_words: [
"look",
"right",
"yeah",
"so",
"listen",
"well",
],
greetings: [
"hey",
"morning",
"shift treating you alright?",
"all good?",
"what's the word?",
"all in one piece?",
],
farewells: [
"shift's calling",
"gotta move",
"catch you later",
"take it easy",
"see you around",
"stay out of trouble",
],
// Van Maanen's Star oaths are void-adjacent — space is real here, and hostile.
// They don't swear by gods or governments. They swear by what kills you.
exclamations: [
"void take it",
"stars",
"blood and void",
"void's sake",
"damn all",
"cold vacuum",
],
),
values: (
description: "Pragmatic, community-oriented, suspicious of authority. Competence earns respect. Showing up and doing the work matters more than rank or credentials. Outsiders are tolerated but watched. Loyalty runs narrow and deep — to your crew, your shift, your street.",
// Traits more common in Van Maanen's Star culture — generator biases toward these.
// Bold: Van Maanen's Star people speak their mind. Honest: community trust is load-bearing.
// Curious: 180 years of problem-solving breeds intellectual appetite.
// Social: community-oriented culture; isolation is a warning sign.
favored_traits: [Bold, Honest, Curious, Social],
// Traits less common — generator biases away from these.
// Reclusive: red flag in a community that depends on showing up.
// Deceptive: betrayal of trust is the worst thing you can do here.
disfavored_traits: [Reclusive, Deceptive],
),
// Voice pipeline: persona block, examples, and occasional injections.
// These feed the composition engine (D-138) — the LLM sees exactly what's here.
// v2 injector validated in Spike 1 (59 prompts, 16.6 t/s CPU).
voice_persona: Some(
"PERSONA: You are a Van Maanen's Star station worker.\n1. Be direct. No pleasantries. Everyone is short on time.\n2. You're working-class and pragmatic. Competence earns respect, not rank.\n3. You're suspicious of distant authority — management that hasn't worked a shift.\n4. You're economical with language. You don't express what the situation doesn't call for.\n5. You use first names. Family names belong on contracts.\n6. Loyalty runs narrow and deep. Your crew, your shift, your street.\n7. You greet briefly: \"hey\", \"morning\", \"shift treating you alright?\"\n8. You're not rude — you're honest. If something's wrong, you say so.\n\nNEVER: corporate or institutional language — you're not management. Never effusive, never polished, never deferential to rank. Never flowery or verbose. Never use family names in casual conversation. Never express deference to authority that hasn't earned it."
),
voice_examples: [
(
input: "declines to answer a question about the overnight run",
output: "Look, that's not mine to say.",
),
(
input: "acknowledges a colleague's greeting while continuing to work",
output: "Hey. Yeah. Catch you at shift end.",
),
(
input: "thanks a colleague for covering a shift",
output: "Appreciated. See you at handoff.",
),
],
occasional_injections: [
// Oath vocabulary — void-adjacent exclamations. Van Maanen's Star swear by what kills you:
// vacuum, void, stars. Rolled at 25% frequency by the composition engine.
// Gated off for suppressive tells to avoid conflicting instructions (Spike 1 finding).
(
kind: "oath",
clause: "When something genuinely surprises or frustrates you, expressions like \"void take it,\" \"stars,\" \"cold vacuum,\" or \"blood and void\" come naturally. Use one in this line.",
example: Some((
input: "discovers a critical part is missing from a shipment",
output: "Void take it. The coupling's not here.",
)),
frequency: 0.25,
suppress_on_tells: [Guarded, RoutineDeviation, Friendly],
),
],
// Behavior modifiers — cultural inflections appended to BehaviorPrimitive actions.
// Categories match modifier_hint strings on primitives (server/src/npc/blueprint.rs).
// If no hint matches, engine falls back to any modifier in this list.
// Van Maanen's Star: terse, efficient, self-contained. No performance of effort or rest.
behavior_modifiers: [
// work_pace — how fast and efficiently they execute physical tasks
(category: "work_pace", clause: "without wasted motion"),
(category: "work_pace", clause: "at the pace the work demands"),
// physical_manner — body language and movement quality during tasks
(category: "physical_manner", clause: "with hands steady on the work"),
(category: "physical_manner", clause: "without ceremony"),
// social_signal — brief acknowledgments made during or between tasks
(category: "social_signal", clause: "with a direct look"),
(category: "social_signal", clause: "without lingering"),
// task_completion — how tasks are finished, wrapped up, or handed off
(category: "task_completion", clause: "letting the work speak for itself"),
(category: "task_completion", clause: "without breaking rhythm"),
// environmental_scan — awareness or vigilance while working
(category: "environmental_scan", clause: "with one eye on the surroundings"),
(category: "environmental_scan", clause: "at a glance, not a pause"),
// offduty_posture — body language and stance when off-shift (Social/OffDuty contexts)
(category: "offduty_posture", clause: "without making a show of it"),
(category: "offduty_posture", clause: "in no rush to be anywhere"),
// authority_response — behavior when supervisors or authority figures are present
// Van Maanen's Star: working-class defiance — authority that hasn't earned it gets no performance
(category: "authority_response", clause: "with no performance for the rank"),
(category: "authority_response", clause: "with no visible adjustment for who's present"),
],
)
@@ -0,0 +1,41 @@
# 5 access tier values (D-035, D-028 Layer 1)
# Hard filter on every dialogue line — determines who can hear what
name: access-tiers
decision_ref: D-035
description: >
Access tiers control which dialogue lines are available to the player based
on their current social standing at the NPC's social site. This is a hard
filter — lines are invisible if access doesn't match. A line can be eligible
for multiple access tiers (access is a list). The detective's institutional
Commission lattice registers as 'authority'; the smuggler's ring membership
provides 'insider' access.
values:
- value: public
description: >
Available to anyone. Surface-level conversation, safe topics, the social
wallpaper that everyone hears. Greetings, weather, the local complaint.
- value: insider
description: >
Available to people who belong. Ring members, established regulars, anyone
the NPC considers part of their social group. The smuggler starts here at
the logistics hub.
- value: authority
description: >
Available to institutional figures. Commission agents, station security,
anyone with formal investigative standing. The detective's default tier.
NPCs are more careful, more formal, less revealing.
- value: peer
description: >
Available to social equals who have earned personal trust. Not institutional,
not group membership — individual relationship. Requires repeated positive
interactions. The tier where real conversation happens.
- value: hostile
description: >
Available when the relationship has broken down. Accusations, threats,
defensive responses. Activates when trust drops below threshold or after
a confrontation event.
@@ -0,0 +1,55 @@
# NPC activity types for routine scheduling
# Derived from Gestalt routine format + Miri cultural patterns (Sova Transit District)
name: activities
decision_ref: D-024
description: >
Activity categories for NPC routine entries. Each routine schedule entry has a
phase (morning/afternoon/evening/night) and an activity describing what the NPC
is doing. Activities are used by the observation event generator to determine
what the player sees when observing an NPC, and by the situation activation
system to set dialogue context.
values:
- value: working
description: On-shift job duties — processing cargo, inspecting manifests, operating equipment
- value: supervising
description: Overseeing others' work — shift supervisor role, checking quality, giving orders
- value: maintaining
description: Maintenance and repair tasks — fixing equipment, cleaning, infrastructure upkeep
- value: patrolling
description: Security rounds — checking access points, monitoring areas, enforcement presence
- value: socializing
description: Casual social interaction — chatting at the bar, break room conversation, gossip
- value: drinking
description: At The Last Shift or similar — consuming drinks, unwinding after shift
- value: eating
description: Meal time — food vendors, break room, bar food
- value: resting
description: Off-shift downtime — in quarters, low activity, recuperating
- value: commuting
description: Moving between locations — corridor transit, shift change movement
- value: gambling
description: Card game at the bar — the regular social ritual, information exchange venue
- value: trading
description: Legitimate commerce — buying, selling, negotiating, market activity
- value: operating
description: >
Ring operations — contraband handling, manifest doctoring, coordination.
Only visible to characters with sufficient knowledge or direct observation.
- value: waiting
description: Idle between activities — lingering, watching, killing time
- value: meeting
description: Arranged or coincidental encounter with specific NPCs — planned conversation
+34
View File
@@ -0,0 +1,34 @@
# 8 mood values (D-035, D-028 Layer 4)
# Mood tags for weighted dialogue selection
name: moods
decision_ref: D-035
description: >
NPC mood tags for Layer 4 weighted selection. The engine matches NPC current
mood state against line mood tags to weight selection. NPC mood changes based
on simulation events (triangle pressure, time of day, recent interactions).
Lines can be appropriate for multiple moods.
values:
- value: anxious
description: Anxious about something specific. Distracted, checking surroundings. (Renamed from 'worried' in Sprint 14.)
- value: frustrated
description: Blocked, irritated, empathetically distressed. Outward-directed tension. (Renamed from 'concerned' in Sprint 14.)
- value: content
description: At ease, relaxed. Default positive-neutral state. (Renamed from 'comfortable' in Sprint 14.)
- value: suspicious
description: Guarded, measuring words. Something feels off to this NPC.
- value: warm
description: Warm, affectionate. Genuine positive feeling toward the listener. (Renamed from 'fond' in Sprint 14.)
- value: hostile
description: Actively antagonistic. Trust broken, relationship damaged. (Added in Sprint 14.)
- value: relieved
description: Tension has eased. Something feared didn't happen, or a burden lifted.
- value: focused
description: Thoughtful, assessing, task-oriented. Processing information rather than emoting. (Renamed from 'analytical', merged with 'conflicted' in Sprint 14.)
@@ -0,0 +1,41 @@
# 6 functional motivations — System B (D-050)
# NPC functional role in the conspiracy/investigation structure
name: motivations
decision_ref: D-050
description: >
Functional motivations (System B) define an NPC's role relative to the
conspiracy and investigation structure. Combined with thematic patterns
(System A) to produce the full NPC generation model. Motivations are
uppercase enum values referenced by npc-profile.schema.json.
values:
- value: HANDLER
description: >
Manages or coordinates others within the ring structure. Has authority
over ring operations and knowledge of the network. Devra-type.
- value: WITNESS
description: >
Has seen or knows something significant, possibly without realizing it.
Their testimony or observations are valuable to the investigation.
- value: TURNCOAT
description: >
Wavering loyalty. Could flip sides given the right pressure or
incentive. The uncertain element in any conspiracy.
- value: CIVILIAN
description: >
Genuinely uninvolved. Their mundane concerns and daily life provide
the substrate that makes the conspiracy invisible. The honest majority.
- value: OPERATOR
description: >
Active participant in ring operations. Handles logistics, moves product,
takes direct action. Kael, Renn — the workers of the conspiracy.
- value: SKEPTIC
description: >
Questions the status quo — institutional, criminal, or both. May be
suspicious of the ring, critical of the Commission, or both. Asks
uncomfortable questions.
+57
View File
@@ -0,0 +1,57 @@
# 9 thematic patterns — System A (D-050)
# NPC archetype patterns for character generation and narrative role
name: patterns
decision_ref: D-050
description: >
Thematic patterns (System A) define an NPC's narrative archetype — their
structural role in the story. Combined with functional motivations (System B)
to produce the full NPC generation model. Patterns are uppercase enum values
referenced by npc-profile.schema.json.
values:
- value: FRIEND
description: >
Production-level complex NPC bonded to a playable character (D-034).
Full 10-axis depth, contradiction arc, multi-phase relationship.
One per playable character in v0.1.
- value: MIRROR
description: >
Reflects the player character's situation from a different angle.
What the player could become, or what they might have been.
- value: ANCHOR
description: >
Stabilizing presence in the community. The person everyone knows,
who provides continuity and normalcy. The bar owner, the shift lead.
- value: GHOST
description: >
Absent or barely-present figure whose influence is felt through
others. Referenced in dialogue, effects visible, person rarely seen.
- value: CATALYST
description: >
Triggers change in others. Their actions or arrival destabilize
existing equilibria. The new hire, the returning contact.
- value: THRESHOLD
description: >
Gatekeeper between social worlds. Controls access to information,
spaces, or people. Their cooperation or opposition shapes player options.
- value: REMNANT
description: >
Carries the past. Remembers how things were before the current
situation. Provides historical context and perspective.
- value: SYSTEM
description: >
Represents institutional power. Their actions reflect organizational
priorities, not personal ones. The Commission agent, the inspector.
- value: NOBODY
description: >
Deliberately flat. Social wallpaper with one memorable trait.
Part of the 30% truly flat population (D-029). Provides the noise
floor that makes investigation signal meaningful.
@@ -0,0 +1,60 @@
# 14 situation values (D-035, D-028 Layer 2)
# Situation context for dialogue line eligibility — engine-state-to-situation mapping
name: situations
decision_ref: D-035
description: >
Dialogue situation tags. The engine activates situations based on simulation
state (time of day, interaction history, NPC routine state, triangle pressure).
Content authors tag lines with situations; the engine decides which situations
are currently active for a given NPC encounter.
values:
- value: arrival
description: Player has just arrived at this location (first visit this game-day)
- value: shift_start
description: NPC is beginning their work shift — settling in, task-focused
- value: shift_end
description: NPC is wrapping up their work shift — tired, ready to leave
- value: shift_transition
description: >
The gap between shifts when oversight is thinnest. Key operational window
for the ring. People are moving, handoffs happening, attention divided.
- value: bar_evening
description: Social hours at The Last Shift — off-duty, relaxed, drinks flowing
- value: night_shift
description: Late hours, skeleton crew. Quieter, more intimate conversations.
- value: investigation
description: Player is actively asking pointed or probing questions
- value: confrontation
description: >
Triangle tension has escalated past the pressure threshold. NPCs are
agitated, defensive, or aggressive. Activated by triangle pressure system.
- value: social
description: NPC is in a social activity — bar, break room, casual conversation
- value: alone
description: NPC is by themselves, no other NPCs nearby
- value: emergency
description: An urgent event is occurring — alarm, accident, security incident
- value: routine
description: Normal daily activity, nothing notable happening
- value: observation
description: Player is watching from a distance, not directly interacting
- value: greeting
description: >
Initial contact phase of an encounter. Layer 2 (D-028) uses greeting lines
with access tier filtering to differentiate first meeting vs established vs
post-confrontation greetings. Added Sprint 8 amendment. NOTE: server
derive_situations() does not yet push Situation::Greeting — pending Rust update.
+44
View File
@@ -0,0 +1,44 @@
# 9 topic values (D-035, D-028 Layer 4)
# Topic tags for weighted dialogue selection
name: topics
decision_ref: D-035
description: >
Dialogue topic tags for Layer 4 weighted selection. The engine matches NPC
current concern topics against line topic tags to weight selection. Lines can
cover multiple topics. Note: 'crime' is deliberately excluded — NPCs think
of smuggling as 'cargo' or 'money', not crime. The dual-lens interpretation
is what makes those topics crime-adjacent for the detective.
values:
- value: colleague
description: Talk about coworkers, workplace relationships, team dynamics
- value: routine
description: Daily schedules, habits, shift patterns, the rhythm of station life
- value: cargo
description: >
Freight, manifests, shipments — setting-specific. For ring members,
this covers contraband discussion without calling it that.
- value: money
description: Finances, costs, wages, spending. The economic squeeze.
- value: trust
description: Reliability, loyalty, who can be counted on, who's changed
- value: danger
description: Threats, risks, things to watch out for, security concerns
- value: institution
description: >
The Commission, station administration, regulations, official procedures.
How institutional power affects daily life.
- value: personal
description: Family, health, aspirations, feelings — non-work life
- value: investigation
description: >
Direct references to the detective's work, evidence, suspicions.
Typically only surfaces at higher trust levels or under pressure.
+56
View File
@@ -0,0 +1,56 @@
# 9 monologue trigger types (D-035, D-032)
# What causes an internal monologue line to fire
name: triggers
decision_ref: D-035
description: >
Monologue trigger types. The observation event generator detects simulation
events and fires triggers consumed by the monologue system. Each trigger type
selects from character-specific pools (D-032 hard partition) and applies
prerequisite knowledge gates before selection.
values:
- value: enter_location
description: >
Player enters a new area. First impressions, atmosphere, spatial awareness.
"The Last Shift. Lera's already got my usual poured."
- value: observe_npc
description: >
Player sees an NPC doing something notable — an activity, a posture, a
tell. "Kael's at the corner booth. He looks rough tonight."
- value: hear_sound
description: >
Sound event from fog edge — voices through walls, footsteps in corridors,
machinery changes. The player interprets what they can't see.
- value: observe_anomaly
description: >
NPC deviates from known routine. The character notices something out of
place. "That's not where they usually go." Requires prerequisite knowledge
of the NPC's normal pattern.
- value: post_conversation
description: >
After dialogue ends. The character reflects on what was said, what wasn't
said, what felt off. Processing and interpretation.
- value: discover_evidence
description: >
Player examines an informational object — a manifest, a terminal, a
personal item. The character interprets what they find.
- value: witness_interaction
description: >
Player sees two NPCs interacting with each other. The character reads the
body language, the tone, the context. Social observation.
- value: time_idle
description: >
Player hasn't acted for a while. The character's mind wanders — ambient
thoughts, rumination, noticing background details.
- value: return_visit
description: >
Player returns to a previously visited area. Changed perspective, new
details noticed, comparison to last time. "Something's different."
@@ -0,0 +1,28 @@
# 3 trust tier values (D-035, D-028 Layer 3)
# Hard filter for trust-gated gossip disclosure
name: trust-tiers
decision_ref: D-035
description: >
Trust tiers control information disclosure depth. Each NPC tracks trust
progression per player character, starting at surface. Trust advances
through repeated positive interactions. This is a hard filter — lines at
'real' or 'secret' trust are invisible until the player earns that level.
values:
- value: surface
description: >
Default tier. Safe, non-committal responses. What the NPC tells
strangers and acquaintances. The public face.
- value: real
description: >
Earned through repeated positive interactions. The NPC shares genuine
opinions, workplace complaints, personal concerns. What they tell
people they trust.
- value: secret
description: >
Highest tier. The NPC reveals information they'd normally hide —
involvement in the ring, knowledge of the smuggling operation,
fears and vulnerabilities. Reaching this tier with THE FRIEND is
where the contradiction arc becomes explicit.
@@ -0,0 +1 @@
# Faction: concord-assembly
@@ -0,0 +1 @@
# Faction: guardians-of-autonomy
@@ -0,0 +1 @@
# Faction: syndics
@@ -0,0 +1 @@
# Faction: the-ring
@@ -0,0 +1 @@
# Faction: the-unbound
@@ -0,0 +1 @@
# Faction: veil-institute
@@ -0,0 +1,42 @@
# Fact catalog: awareness
# Situational awareness — who's present, active threats, operational status
# Source: docs/design/knowledge-vocabulary-v01.md §4.2 (#368)
facts:
- fact_id: awareness.detective_presence
description: A Commission detective is operating on Sova Station
typical_confidence: knows_of
characters: [smuggler]
notes: "Smuggler learns through rumor or direct observation. Detective does not hold this fact about themselves."
- fact_id: awareness.detective_investigating_ring
description: The detective is specifically targeting the smuggling ring, not a routine audit
typical_confidence: knows_details
characters: [smuggler]
- fact_id: awareness.commission_audit_scheduled
description: A Commission audit is coming — officially scheduled
typical_confidence: knows_of
characters: [smuggler, detective]
- fact_id: awareness.ring_route_compromise
description: The current drop route may be compromised or under observation
typical_confidence: suspects
characters: [smuggler]
- fact_id: awareness.surveillance_change
description: Surveillance patterns in the maintenance corridors have changed recently
typical_confidence: suspects
characters: [smuggler]
- fact_id: awareness.ring_tension_escalation
description: Something is wrong inside the ring — someone is scared or making moves
typical_confidence: suspects
characters: [smuggler]
- fact_id: awareness.inspection_sweep_active
description: Active inspection sweep in progress right now
typical_confidence: direct
characters: [smuggler, detective]
notes: "direct confidence — set by environmental observation, not investigation"
@@ -0,0 +1,42 @@
# Fact catalog: behavioral
# Behavioral patterns recognized through repeated observation across multiple scenes
# Source: docs/design/knowledge-vocabulary-v01.md §4.3 (#368)
facts:
- fact_id: behavioral.kael_evasion
description: Kael looks left when lying — personal tell recognized post-conversation
typical_confidence: direct
characters: [smuggler]
notes: "Set during a conversation where evasion is detected. direct confidence = just confirmed."
- fact_id: behavioral.kael_behavioral_change
description: Kael's behavior has noticeably changed — quieter, distracted, different routine
typical_confidence: suspects
characters: [smuggler]
- fact_id: behavioral.sera_avoidance_pattern
description: Sera consistently avoids Torek Lintar — leaves when he arrives, repositions
typical_confidence: suspects
characters: [smuggler, detective]
notes: "One observation = suspects; three observations = knows_of (pattern confirmed for detective)"
- fact_id: behavioral.sera_topic_deflection
description: Sera deflects specific topics — Commission work, manifest audits, freight
typical_confidence: suspects
characters: [smuggler, detective]
- fact_id: behavioral.sera_kiosk_pattern
description: Sera habitually stops at the same Commission kiosk at the same time
typical_confidence: knows_of
characters: [smuggler, detective]
- fact_id: behavioral.sera_knowledge_detail
description: Sera's offhand comments reveal detailed knowledge of manifest routing she shouldn't have
typical_confidence: knows_of
characters: [smuggler]
- fact_id: behavioral.voss_awareness
description: Voss is tracking people — situational awareness beyond normal supervisor behavior
typical_confidence: suspects
characters: [detective]
@@ -0,0 +1,39 @@
# Fact catalog: contraband
# Smuggling ring world facts — existence, components, operations, supply chain
# Source: docs/design/knowledge-vocabulary-v01.md §4.5 (#368)
facts:
- fact_id: contraband.ring_exists
description: A smuggling operation is running through Sova Transit District
typical_confidence: suspects
characters: [smuggler, detective]
notes: "Smuggler starts at knows_details (Background — they ARE in the ring). Detective starts at suspects."
- fact_id: contraband.ring_lattice_components
description: The ring moves unlicensed lattice components — aftermarket neural mods
typical_confidence: knows_of
characters: [smuggler, detective]
notes: "Smuggler starts at knows_details (Background). Detective discovers through investigation."
- fact_id: contraband.ring_medical_components
description: The ring also diverts medical-grade lattice replacements from Syndic supply chains
typical_confidence: knows_details
characters: [smuggler, detective]
notes: "Deep investigation only — the moral dimension of the operation"
- fact_id: contraband.supply_chain
description: Understanding of the ring's supply chain — where components come from
typical_confidence: knows_details
characters: [smuggler, detective]
- fact_id: contraband.severance_tech_presence
description: Severance counter-surveillance technology is in play on the station
typical_confidence: suspects
characters: [detective]
- fact_id: contraband.drop_tonight
description: A drop is scheduled for tonight specifically
typical_confidence: knows_details
characters: [smuggler]
notes: "Seed-dependent — only relevant in seeds where a drop is scheduled during play session"
@@ -0,0 +1,235 @@
# Entity Knowledge Attributes — 16 canonical keys
# Source: D-024 (10-axis model), wiki-review workshop A7, v01-content-scoping workshop
# All keys are observer->target, stored in EntityKnowledge.known_attributes BTreeMap<String, String>
# Reference: docs/wiki/knowledge/entity-attributes.md
# Categories: identity (4), social (2), behavioral (2), leverage (2), investigation (2), role-perspective (4)
# History: 14 original keys + 4 new role-perspective keys + 2 renames (secret_held -> leverage_held, secret_confidence -> leverage_confidence)
attributes:
# --- Identity Attributes (4) ---
- key: name
category: identity
value_type: freeform
description: >
Full name as known to the observer. If absent or generic,
monologue and dialogue use role descriptor instead.
examples:
- "Kael Davan"
- "Kael"
- "the dock worker"
- key: role
category: identity
value_type: freeform
description: >
Occupational or social role. Default descriptor when name is unknown.
Used in access tier calculation.
examples:
- "dock worker"
- "shift supervisor"
- "bartender"
- "ring coordinator"
- key: faction
category: identity
value_type: freeform
description: >
Institutional or organizational allegiance. Commission-tagged individuals
trigger different NPC behavior. Used for authority/peer dialogue filtering.
examples:
- "Commission"
- "civilian"
- "ring member"
- "unknown"
- key: species
category: identity
value_type: freeform
description: >
Species identifier. Not load-bearing in v0.1 (all human).
Placeholder for future non-human NPCs.
examples:
- "human"
# --- Social Attributes (2) ---
- key: relationship_type
category: social
value_type: freeform
description: >
Relationship category from observer's perspective.
Drives RelationshipState calculation and monologue emotional tone.
examples:
- "colleague"
- "friend"
- "authority figure"
- "suspect"
- "partner"
- "stranger"
- key: trust_level
category: social
value_type: enum
values:
- trusted
- reliable
- uncertain
- suspicious
- compromised
description: >
Trust assessment — observer's subjective judgment. Encompasses both the
read action and the state. No separate trust_read key. Gates trust-tier
dialogue (surface/real/secret).
# --- Behavioral Attributes (2) ---
- key: routine_pattern
category: behavioral
value_type: freeform
description: >
Observed routine description. Deviation detection triggers monologue
when current behavior doesn't match known pattern.
examples:
- "morning shift 06:00-14:00, bar after shift"
- "arrives 06:00, break 10:30, departs 14:00"
- "irregular schedule, seen at odd hours"
- key: behavior_flags
category: behavioral
value_type: freeform
description: >
Comma-separated behavioral observations. Multiple flags accumulate
as evidence. Detective's analytical lattice auto-flags some behaviors.
examples:
- "nervous,lattice_checking"
- "avoidance_pattern,evasive"
- "spending_beyond_means"
- "reliable,punctual"
# --- Leverage Attributes (2) ---
# Renamed from secret_held/secret_confidence per workshop A7
- key: leverage_held
category: leverage
value_type: freeform
renamed_from: secret_held
description: >
What the observer believes gives them power over this entity.
Covers secrets, debts, promises, obligations, and compromising positions.
Drives PersonOfInterest state. Gates confrontation dialogue.
examples:
- "ring membership"
- "unreported evidence"
- "gambling debt"
- "exit attempt"
- "owes favor to Voss"
- key: leverage_confidence
category: leverage
value_type: enum
renamed_from: secret_confidence
values:
- suspected
- likely
- confirmed
description: >
How certain the observer is about the leverage. Suspected allows
fishing questions; confirmed enables direct confrontation.
# --- Investigation Attributes (2) ---
- key: tell_observed
category: investigation
value_type: freeform
description: >
Specific tell noted by observer. Captures the observer's interpretive
conclusion about behavior. Accumulated tells build case strength.
Monologue references specific tells when they recur.
examples:
- "looks left when lying"
- "leaves when Torek arrives"
- "checks lattice before answering"
- "forced casualness after shift supervisor passes"
implementation_note: >
Server may track tells via behavior_flags internally. tell_observed is
retained as a content-authoring key for its distinct narrative purpose.
- key: contradiction_flagged
category: investigation
value_type: freeform
description: >
Boolean-ish flag — presence of value means contradiction detected.
THE FRIEND arc trigger. When set, monologue tone shifts, dialogue
options change, RelationshipState moves toward PersonOfInterest.
examples:
- "meeting_unknown_contact"
- "avoidance_inconsistency"
- "manifest_access_mismatch"
implementation_note: >
Server may track via behavior_flags with contradiction: prefix.
Retained as documented key for arc transition gating.
# --- Role-Perspective Attributes (4 new per workshop A7) ---
# Same enums across all archetypes; interpretation is archetype-dependent.
# Smuggler reads "risk" as operational exposure; detective reads it as
# threat to investigation. See wiki entity-attributes.md for full mapping.
- key: risk_assessment
category: role-perspective
value_type: enum
values:
- none
- low
- moderate
- high
- critical
description: >
Observer's assessment of how much danger this entity poses or attracts.
Gates operational monologue. High-risk triggers cautionary dialogue.
Nature of "risk" depends on observer archetype.
- key: loyalty_assessment
category: role-perspective
value_type: enum
values:
- solid
- dependable
- uncertain
- wavering
- hostile
description: >
Observer's assessment of this entity's reliability and loyalty.
Determines how much the observer relies on or confides in the target.
Wavering triggers monitoring; hostile triggers defensive posture.
- key: position_integrity
category: role-perspective
value_type: enum
values:
- solid
- thin
- cracking
- blown
- "N/A"
description: >
Observer's assessment of this entity's cover, position stability,
or facade status. When degraded, monologue reflects increasing anxiety
or strategic recalculation. N/A when cover concept does not apply.
- key: moral_weight
category: role-perspective
value_type: enum
values:
- innocent
- peripheral
- complicit
- compromised
- willing
description: >
Observer's assessment of this entity's moral involvement. Shapes the
observer's moral arc and internal conflict. Smuggler assesses complicity
in ring operations; detective assesses culpability in the crime.
Same scale, different lens.
@@ -0,0 +1,32 @@
# Fact catalog: knowledge
# Operational knowledge — ring procedures, social dynamics, institutional mechanics
# Source: docs/design/knowledge-vocabulary-v01.md §4.4 (#368)
facts:
- fact_id: knowledge.ring_routing_knowledge
description: Full knowledge of the ring's drop routes and timing protocols
typical_confidence: knows_details
characters: [smuggler]
notes: "Smuggler starts at knows_details (Background). Not available to detective through normal investigation paths."
- fact_id: knowledge.ring_bar_operations
description: The bar (The Last Shift) has a role in ring communications or social cover
typical_confidence: knows_of
characters: [smuggler, detective]
- fact_id: knowledge.bar_back_room_significance
description: The bar's back room is significant — meeting space, handoff point, or storage
typical_confidence: suspects
characters: [detective]
- fact_id: knowledge.bar_ring_awareness
description: Bar regulars have varying levels of awareness of the ring — open secret at some level
typical_confidence: knows_of
characters: [smuggler, detective]
- fact_id: knowledge.kael_exit_plan
description: Kael has a specific exit plan — timing, conditions, contact
typical_confidence: knows_details
characters: [smuggler, detective]
notes: "Only available through Kael's deep trust disclosure or independent investigation"
@@ -0,0 +1,51 @@
# Fact catalog: location
# Location-specific access, restrictions, and significance
# Source: docs/design/knowledge-vocabulary-v01.md §4.6 (#368)
facts:
- fact_id: location.corridor_b7_restricted
description: Corridor B-7 is a restricted access zone — requires credentials
typical_confidence: knows_of
characters: [smuggler, detective]
notes: "Both characters have this from Background (signage, institutional knowledge)"
- fact_id: location.corridor_b7_drop_site
description: B-7 is an active drop site for the ring
typical_confidence: knows_details
characters: [smuggler, detective]
notes: "Smuggler from Background. Detective through investigation."
- fact_id: location.maintenance_corridors_access
description: Character knows the maintenance corridor layout and can navigate it
typical_confidence: knows_of
characters: [smuggler, detective]
notes: "Smuggler at knows_details (Background — daily operational space). Detective at knows_of after investigation."
- fact_id: location.bay4_sealed
description: Bay 4 is sealed — inspection or deliberate cover
typical_confidence: suspects
characters: [smuggler, detective]
- fact_id: location.span_gate_schedule_gap
description: The span gate schedule has a window that enables unseen cargo drops
typical_confidence: knows_details
characters: [smuggler]
- fact_id: location.smuggling_route
description: The complete physical route the ring uses through the station
typical_confidence: knows_details
characters: [smuggler, detective]
notes: "Smuggler from Background. Detective from deep investigation."
- fact_id: location.surveillance_gaps
description: Specific camera blind spots in the maintenance corridor network
typical_confidence: knows_details
characters: [smuggler, detective]
notes: "Smuggler from Background. Detective must discover independently."
- fact_id: location.dead_drop_location
description: Specific dead drop location(s) used for handoffs
typical_confidence: knows_details
characters: [smuggler]
notes: "Smuggler operational knowledge"
@@ -0,0 +1,36 @@
# Fact catalog: progress
# Narrative milestone flags
# Note: progress.* facts are NOT recommended for direct authoring in prerequisite blocks.
# Use investigation fact chains and relationship states instead.
# These exist for potential storyteller/arc-tracking use.
# Source: docs/design/knowledge-vocabulary-v01.md §3.2 (#368)
facts:
- fact_id: progress.friend_arc_phase_1
description: FRIEND arc Phase 1 warmth established (baseline positive relationship)
notes: "Set by relationship state transition to Friendly. Do not author directly — use relationship checks."
- fact_id: progress.friend_arc_phase_2
description: FRIEND arc Phase 2 trust built (deep rapport + initial social context)
notes: "Set by trust tier advancement. Do not author directly — use investigation + relationship checks."
- fact_id: progress.friend_arc_contradiction
description: FRIEND contradiction discovered (KnowledgeState → Contradicted)
notes: "Set by contradiction detection system. Use relationship state person_of_interest + investigation fact instead."
- fact_id: progress.friend_arc_confrontation
description: FRIEND confronted about contradiction
notes: "Set post-confrontation by dialogue system."
- fact_id: progress.opening_complete
description: Opening tutorial sequence completed (first 5 minutes)
notes: "Set by storyteller after initial objective sequence."
- fact_id: progress.first_ring_contact
description: Smuggler completed first ring operation during play session
characters: [smuggler]
- fact_id: progress.first_evidence_filed
description: Detective filed first manifest discrepancy evidence
characters: [detective]
@@ -0,0 +1,33 @@
# Fact catalog: relationship
# Inter-NPC connections — what one character knows about relationships between others
# Source: docs/design/knowledge-vocabulary-v01.md §4.7 (#368)
facts:
- fact_id: relationship.kael_naia_connection
description: Kael and Naia are romantically partnered — not just colleagues
typical_confidence: knows_of
characters: [smuggler, detective]
notes: "Smuggler may know from background or Kael mentioning Naia. Detective through social observation."
- fact_id: relationship.ring_membership
description: Character has identified specific ring members
typical_confidence: knows_of
characters: [smuggler, detective]
notes: "knows_of = partial list; knows_details = full ring membership identified"
- fact_id: relationship.trust_network
description: Understanding of who trusts whom inside the ring — operational reliability mapping
typical_confidence: knows_details
characters: [smuggler]
notes: "Smuggler-specific operational knowledge"
- fact_id: relationship.tamm_family
description: Connection between Naia Tamm and her family situation
typical_confidence: knows_of
characters: [smuggler, detective]
- fact_id: relationship.torek_bar_arrangement
description: Torek has a financial arrangement related to the bar or its operations
typical_confidence: knows_of
characters: [smuggler, detective]
+106
View File
@@ -0,0 +1,106 @@
# Fact catalog: ring
# Smuggling ring module event trail — observable evidence produced by module events.
# These facts are made discoverable by specific events in smuggling_ring_v0_1.yaml.
# Stub entries — description and confidence level confirmed; progression text TBD.
# Ticket: #158 | Sprint 18
facts:
- fact_id: ring.cargo_discrepancy_pattern
description: Cargo manifests at The Terminal show small, systematic discrepancies — weight variances, unverified entries, containers with no return log
typical_confidence: suspects
characters: [smuggler, detective]
notes: >
Detective's analytical lattice may flag this automatically during Terminal walkthrough.
Smuggler encounters it during operational paperwork checks. Pattern becomes clearer over
multiple observations (once: false event — repeats). Starting entry point for both
investigation arcs.
- fact_id: ring.kael_missed_verification
description: Kael Davan was absent from a scheduled cargo verification — another dock worker covered without explanation
typical_confidence: suspects
characters: [smuggler, detective]
notes: >
Discoverable via cargo manifest review (Terminal office) or analytical lattice flag
(detective). Smuggler notices the irregularity in their own paperwork. First concrete
evidence that Kael is deviating from his normal operational reliability.
- fact_id: ring.kael_unauthorized_corridor_access
description: Kael was observed in restricted maintenance corridor B-7 during off-shift hours with an unknown contact
typical_confidence: knows_of
characters: [smuggler, detective]
notes: >
Core FRIEND contradiction observable (D-034). Player must be in visual range of B-7
to discover this, OR examine the corridor door access log (investigative action).
Both characters can discover this fact — interpreted differently (smuggler: security
breach / detective: suspicious contact). Upgrades from suspects to knows_of when
contact identity confirmed, knows_details when purpose confirmed.
- fact_id: ring.kael_unusual_meridian_activity
description: Encrypted Meridian packets sent from cargo bay terminals — frequent, patterned, not from personal devices
typical_confidence: suspects
characters: [detective]
notes: >
Detective-only. Requires analytical lattice to flag the outgoing packet pattern.
Player must be in or adjacent to The Terminal cargo bay. Content not accessible —
only the existence and frequency of the encrypted messages. Hints at Kael's
off-district contact without revealing who.
- fact_id: ring.voss_kael_private_meeting
description: Voss called Kael into the supervisor's office — closed door, raised voices audible from adjacent position
typical_confidence: suspects
characters: [smuggler, detective]
notes: >
Observable via spatial positioning (supervisor's office area). Smuggler can witness
the approach and departure without hearing content. Detective observes Kael's visible
strain immediately after if present in The Terminal. Upgrade to knows_of via
trust-gated dialogue with Kael ("Are you alright?" option unlocks post-meeting).
- fact_id: ring.voss_accelerating_timeline
description: Voss is pushing to close ring operations faster than normal — someone is watching
typical_confidence: knows_of
characters: [smuggler, detective]
notes: >
Smuggler: Voss mentions "the schedule moving up" in guarded conversation (trust-gated,
ring-insider access required). Detective: observe Voss and Nils in two exchanges within
the same shift and note behavioral change. Not directly stated — inferred from context.
- fact_id: ring.commission_cargo_flag
description: A Commission internal note flags The Terminal's cargo variance rate as statistically unusual
typical_confidence: knows_of
characters: [detective]
notes: >
Detective-only. Accessible via institutional Commission query (authority access tier,
Terminal records). Not a formal investigation — just an internal flag from Maret Korr.
Confirms the detective's suspicions with institutional weight. Smuggler has no way to
know this exists.
- fact_id: ring.final_shipment_scheduled
description: The ring has scheduled a major final drop — after it clears, operations go dark
typical_confidence: knows_of
characters: [smuggler, detective]
notes: >
Smuggler: direct notification from Voss (ring-insider access). Detective: cargo manifest
shows an unusually large entry scheduled 3 days out — no obvious legitimate reason for
the volume. This fact creates the closing window — both characters know time is running
out, for different reasons.
- fact_id: ring.sera_avoidance_behavior
description: Sera Venn takes longer routes through The Last Shift to avoid standing near Torek Lintar
typical_confidence: suspects
characters: [detective]
notes: >
Detective-only observable. Player must observe Sera's movement pattern on two separate
occasions — requires forward vision cone and awareness of her baseline route. The
avoidance is visible but not explained. Points toward Sera holding information about
Torek's investigation without having acted on it.
- fact_id: ring.nils_unlogged_cargo
description: Nils makes regular supply runs to maintenance corridor C-7 with containers that never appear in return logs
typical_confidence: suspects
characters: [smuggler, detective]
notes: >
Discoverable by watching Nils's cargo handling pattern over two shifts, or by examining
the maintenance corridor C-7 access log directly. The missing return entry is the tell —
the container went in but never came back. Both characters can find this; smuggler may
already suspect given operational context.
@@ -0,0 +1,11 @@
# Fact catalog: social
# Social positioning facts — standing in a specific social context
# Source: docs/design/knowledge-vocabulary-v01.md §4.8 (#368)
facts:
- fact_id: social.bar_regular_status
description: Character is an established regular at The Last Shift — recognized, trusted in that context
typical_confidence: knows_of
characters: [smuggler, detective]
notes: "Smuggler may have this from Background. Detective builds it through multiple bar visits."
@@ -0,0 +1,35 @@
# Fact catalog: world
# Faction and institutional knowledge — Commission, lattice regulation, broader context
# Source: docs/design/knowledge-vocabulary-v01.md §4.6 (#368)
facts:
- fact_id: world.lattice_regulation_active
description: Commission actively regulates neural lattice component access in this system
typical_confidence: knows_of
characters: [smuggler, detective]
notes: "Both characters have this from Background"
- fact_id: world.unlicensed_lattice_demand
description: High demand for unlicensed lattice upgrades on working-class stations like Sova
typical_confidence: knows_of
characters: [smuggler, detective]
notes: "The moral context of the operation — smuggler knows it as justification; detective may learn it as complication"
- fact_id: world.commission_sova_jurisdiction
description: Commission has jurisdiction over Sova Transit District
typical_confidence: knows_details
characters: [detective]
notes: "Detective Background knowledge — institutional mandate"
- fact_id: world.ring_cross_system
description: The ring operates across multiple star systems — Sova is one node
typical_confidence: knows_details
characters: [smuggler, detective]
notes: "Late-game discovery — changes scope of the operation"
- fact_id: world.shift_schedule
description: Sova Transit District shift schedule — who works when
typical_confidence: knows_of
characters: [smuggler, detective]
notes: "Smuggler from Background (colleague). Detective through investigation."
+49
View File
@@ -0,0 +1,49 @@
// Trait Modifier Clauses for Voice Pipeline (D-138)
//
// One clause per PersonalityTrait. Injected into LLM prompts to modify
// speech style based on NPC personality. Stacks with culture persona
// and tell-state injectors.
//
// Schema: map of trait name → clause string
// Used by: server/src/voice/prompt_builder.rs
//
// Writing notes:
// - Behavioral, not emotional. Never label a feeling.
// - Each clause targets a distinct speech dimension so traits stack cleanly.
// Bold = delivery force. Cautious = word selection. Curious = sentence shape.
// Compassionate = cadence (engaged). Incurious = cadence (flat). Ruthless = position.
// A Bold+Compassionate NPC speaks with force but gives the answer room to land — no conflict.
// - Kept to 1-2 sentences. LLM context is limited and these share space with
// persona, tell-state, and epistemic marker instructions.
{
// Delivery: force and directness. Short sentences land without hedging.
"Bold": "This character doesn't soften the landing. Statements arrive short and flat — no qualifiers, no trailing uncertainty.",
// Word selection: nothing committed without cover. Hedges stay.
"Cautious": "This character hedges where the situation allows it. \"Probably,\" \"might,\" \"I'd say\" — these aren't weakness, they're habit.",
// Sentence shape: questions surface. Interest pulls the line open.
"Curious": "This character lets interest show at the end of a line — a beat longer than needed, a question that wasn't required.",
// Framing: the useful version, not the true version. Nothing false, just selected.
"Deceptive": "This character leads with what serves them. The useful detail arrives early; the less useful one doesn't arrive at all.",
// Framing: no softening, no omission. The whole thing, bluntly.
"Honest": "This character gives the whole answer, including the part that doesn't reflect well. Nothing is softened to spare anyone.",
// Cadence: open, engaged. Responses arrive with momentum and care.
"Compassionate": "This character gives the answer room to land. There's no rush past the difficult part — it gets said, plainly, without looking away.",
// Cadence: flat, unengaged. The response does its job and stops.
"Incurious": "This character answers what was asked. Nothing extra surfaces — no follow-up, no interest, no second look at what was just said.",
// Volume and reach: minimal, inward-facing. Not interested in being heard widely.
"Reclusive": "This character answers what was asked and closes the door. There is no invitation for follow-up.",
// Texture: open, inclusive. Others are assumed to be present and welcome.
"Social": "This character addresses the conversation, not just the question. A word or two lands that wasn't strictly necessary — the kind that keeps things warm.",
// Position: sharp, economical. Nothing is offered that doesn't serve the speaker.
"Ruthless": "This character cuts to the useful part. Courtesy is absent, not hostile — just unnecessary. The sentence ends when the point is made.",
}
@@ -0,0 +1,62 @@
// Van Maanen's Star Industrial Zone — location metadata
//
// Schema: server/src/npc/blueprint.rs :: ZoneSpec
// Ticket: #609, #630, #661 (copy team)
// Validate: tooling/validate-ron content/global/van-maanens-star-industrial-zone.ron zone
//
// Location-specific metadata for a Van Maanen's Star industrial freight district.
// Behavior primitives have moved to the zone-type template:
// content/global/zone-types/industrial_freight.ron
//
// This file holds: zone_type reference, location metadata, role weights, social sites.
// The generator reads zone_type to find the primitive pool; overrides come from here.
//
// Character: freight handling, manufacturing, maintenance. High throughput.
// Shift rhythms. Functional over comfortable. Nobody lingers — unless they're on break.
(
zone_type: "industrial_freight",
label: "Industrial Zone",
description: "Freight handling, manufacturing, and maintenance. High throughput, shift-based work rhythms, functional over comfortable. Faces are known by role and bay number more than name. The work doesn't stop between shifts — people do.",
// 1-10. Industrial Van Maanen's Star: steady credit flow, but it all goes somewhere.
economic_level: 7,
// 1-10. Dense. Multiple shifts overlap. Crowds at handover.
population_density: 6,
// Role presence and weights for this location.
// skill_focus / combat_eligible / behavior_primitives live in the zone-type template.
role_weights: [
( id: "dock_worker", weight: 5 ),
( id: "technician", weight: 4 ),
( id: "foreman", weight: 2 ),
( id: "security", weight: 2 ),
],
social_sites: [
(
site_type: "break_room",
label: "Worker Break Room",
// Between shifts. Decompression. People stop performing for a moment.
min_npcs: 2,
max_npcs: 5,
),
(
site_type: "maintenance_bay",
label: "Maintenance Bay",
// Active work site. Technicians and dock workers cross paths here.
min_npcs: 2,
max_npcs: 4,
),
(
site_type: "loading_platform",
label: "Loading Platform",
// The operational center. Busy, loud, coordinated.
min_npcs: 3,
max_npcs: 8,
),
],
abandoned: false,
poi_overlay: None,
)
@@ -0,0 +1,44 @@
// Van Maanen's Star Rural Zone — location metadata
//
// Schema: server/src/npc/blueprint.rs :: ZoneSpec
// Ticket: #609, #630, #661 (copy team)
// Validate: tooling/validate-ron content/global/van-maanens-star-rural-zone.ron zone
//
// Location-specific metadata for a Van Maanen's Star rural agricultural settlement.
// Behavior primitives have moved to the zone-type template:
// content/global/zone-types/rural_agricultural.ron
//
// This file holds: zone_type reference, location metadata, role weights, social sites.
// The generator reads zone_type to find the primitive pool; overrides come from here.
//
// Character: scattered homesteads and small workshops. Unhurried. Community-bound.
// Low throughput, high familiarity. Everyone knows who belongs here.
(
zone_type: "rural_agricultural",
label: "Rural Settlement",
description: "Scattered homesteads, small workshops, and communal gathering points. Low population density, strong community bonds, subsistence-plus economy. Work is seasonal and visible — everyone knows what everyone else is doing.",
// 1-10. Rural Van Maanen's Star: self-sufficient, low cash flow, barter supplements credits.
economic_level: 3,
// 1-10. Sparse. Faces are familiar. Strangers stand out.
population_density: 2,
// Role presence and weights for this location.
// skill_focus / combat_eligible / behavior_primitives live in the zone-type template.
role_weights: [
( id: "farmer", weight: 5 ),
( id: "mechanic", weight: 3 ),
( id: "trader", weight: 2 ),
( id: "militia", weight: 1 ),
],
social_sites: [
( site_type: "tavern", label: "Local Tavern", min_npcs: 3, max_npcs: 6 ),
( site_type: "workshop", label: "Community Workshop", min_npcs: 2, max_npcs: 4 ),
( site_type: "market_stall", label: "Settlement Market", min_npcs: 1, max_npcs: 3 ),
],
abandoned: false,
poi_overlay: None,
)
@@ -0,0 +1,97 @@
// Zone Identity Spec — example file
//
// Schema: server/src/npc/blueprint.rs :: ZoneSpec
// Real content: ticket #609 (copy team fills this)
// Validate: tooling/validate-ron content/global/zone-identity-spec.example.ron zone
//
// One file per zone type. The generator reads this to decide NPC count,
// role distribution, and social site placement.
//
// Format: RON (Rusty Object Notation) — the Rust structs ARE the schema.
// Comments are allowed. Trailing commas are allowed.
(
zone_type: "rural",
label: "Rural Settlement",
description: "Scattered homesteads, small workshops, and communal gathering spots. Low population density, strong community bonds, subsistence-plus economy.",
// 1-10 scale. Rural = low economic activity, mostly self-sufficient.
economic_level: 3,
// 1-10 scale. Rural = sparse, everyone knows everyone.
population_density: 2,
roles: [
(
id: "farmer",
label: "Farmer",
weight: 5,
skill_focus: ["technical"],
combat_eligible: false,
typical_behaviors: [
"tends crops in the field",
"hauls produce to the market stall",
"repairs equipment by hand",
],
),
(
id: "mechanic",
label: "Settlement Mechanic",
weight: 3,
skill_focus: ["technical"],
combat_eligible: false,
typical_behaviors: [
"works on machinery with focused intensity",
"wipes grease on coveralls between tasks",
"explains repairs in terse technical shorthand",
],
),
(
id: "trader",
label: "Itinerant Trader",
weight: 2,
skill_focus: ["persuasion", "observation"],
combat_eligible: false,
typical_behaviors: [
"arranges goods on a portable display",
"haggles with quiet persistence",
"watches foot traffic from market stall",
],
),
(
id: "militia",
label: "Settlement Militia",
weight: 1,
skill_focus: ["combat", "observation"],
combat_eligible: true,
typical_behaviors: [
"patrols the settlement perimeter",
"checks credentials at the gate",
"leans on rifle while scanning the horizon",
],
),
],
social_sites: [
(
site_type: "tavern",
label: "Local Tavern",
roles: ["farmer", "mechanic", "trader", "militia"],
min_npcs: 3,
max_npcs: 6,
),
(
site_type: "workshop",
label: "Community Workshop",
roles: ["mechanic", "farmer"],
min_npcs: 2,
max_npcs: 4,
),
(
site_type: "market_stall",
label: "Market Stall",
roles: ["trader", "farmer"],
min_npcs: 1,
max_npcs: 3,
),
],
)
@@ -0,0 +1,168 @@
// Industrial Freight Zone-Type Template
//
// Schema: server/src/npc/blueprint.rs :: ZoneTypeTemplate
// Ticket: #661 (copy team)
// Validate: tooling/validate-ron server/content/global/zone-types/industrial_freight.ron zone_type
//
// Sources: D-142 (zone-type template architecture).
//
// Zone character: freight handling, cargo throughput, shift-based manufacturing.
// High throughput, functional over comfortable. Faces known by role and bay number.
// The work doesn't stop between shifts — people do.
//
// Primitives are CULTURE-NEUTRAL. Culture modifiers (culture-*.ron files) append
// cultural flavor at assembly time. Do not encode cultural attitudes in action text.
//
// Roles: dock_worker, technician, foreman, security
// Social site types: break_room, maintenance_bay, loading_platform
(
id: "industrial_freight",
subtype: None,
label: "Industrial Freight Zone",
description: "Freight handling, cargo throughput, shift-based work rhythms. Functional over comfortable. Faces known by role and bay number. The work doesn't stop between shifts — people do.",
// Default economic/density profile. Location specs override.
economic_level: 7,
population_density: 6,
roles: [
(
id: "dock_worker",
label: "Dock Worker",
skill_focus: ["technical"],
combat_eligible: false,
// weight omitted — location specs declare role_weights
behavior_primitives: [
// OnShift
( action: "guides a freight container into position with hand signals", context: OnShift, modifier_hint: Some("work_pace") ),
( action: "checks a manifest against a handheld scanner", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "waits at the loading bay apron, watching the clock", context: OnShift, modifier_hint: Some("environmental_scan") ),
( action: "calls bay numbers to a colleague across the noise of the floor", context: OnShift, modifier_hint: Some("social_signal") ),
( action: "hooks a cargo sling and steps clear before signaling the lift", context: OnShift, modifier_hint: Some("physical_manner") ),
( action: "stacks empty pallets against a wall", context: OnShift, modifier_hint: Some("work_pace") ),
( action: "wipes sweat from their face with a forearm and keeps moving", context: OnShift, modifier_hint: Some("physical_manner") ),
( action: "drags a heavy case along the deck plating one-handed, leaning into the weight", context: OnShift, modifier_hint: Some("physical_manner") ),
( action: "re-checks a seal on a container door after a colleague already checked it", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "flags a damaged pallet to the foreman without stopping the line", context: OnShift, modifier_hint: Some("authority_response") ),
( action: "shoulders a cargo rig harness and clips in without looking down", context: OnShift, modifier_hint: Some("physical_manner") ),
( action: "sweeps debris off the loading apron with a long push broom", context: OnShift, modifier_hint: Some("work_pace") ),
( action: "braces a container with a boot while reaching for the locking pin", context: OnShift, modifier_hint: Some("physical_manner") ),
( action: "reads the load ticket twice, then flips the handheld over to check the back", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "waves off a crane operator when the angle is wrong, holds up a fist", context: OnShift, modifier_hint: Some("social_signal") ),
( action: "steps over a bundled cable run without breaking stride", context: OnShift, modifier_hint: Some("work_pace") ),
( action: "peels off a work glove with his teeth to check a handheld display", context: OnShift, modifier_hint: Some("physical_manner") ),
( action: "exchanges a brief look with a nearby colleague when the supervisor passes", context: OnShift, modifier_hint: Some("authority_response") ),
// OffDuty / break room
( action: "slumps into a break room chair and stares at nothing for a full minute before reaching for a drink", context: OffDuty, modifier_hint: Some("offduty_posture") ),
( action: "unwraps a meal packet in the break room and eats standing at the counter", context: OffDuty, modifier_hint: Some("offduty_posture") ),
( action: "passes a drink to the person next to her without being asked", context: OffDuty, modifier_hint: Some("social_signal") ),
( action: "leans back in a break room chair with eyes closed, boots crossed at the ankle", context: OffDuty, modifier_hint: Some("offduty_posture") ),
( action: "laughs at something across the break room table, loud enough to carry", context: OffDuty, modifier_hint: Some("social_signal") ),
( action: "shows something on a handheld to a colleague and both of them look at it", context: OffDuty, modifier_hint: Some("social_signal") ),
( action: "sits with elbows on knees, turning an empty cup in both hands", context: OffDuty, modifier_hint: Some("offduty_posture") ),
( action: "splashes water on his face at the sink and stands there a moment before turning off the tap", context: OffDuty, modifier_hint: Some("offduty_posture") ),
( action: "talks over the break room noise at volume, gesturing with a fork", context: OffDuty, modifier_hint: Some("social_signal") ),
( action: "falls asleep in a break room chair, chin on chest, arms folded", context: OffDuty, modifier_hint: Some("offduty_posture") ),
],
),
(
id: "technician",
label: "Systems Technician",
skill_focus: ["technical"],
combat_eligible: false,
behavior_primitives: [
// OnShift
( action: "runs a diagnostic routine on a floor console, eyes on the readout", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "traces a conduit run along the ceiling with a handheld light", context: OnShift, modifier_hint: Some("environmental_scan") ),
( action: "swaps a panel module, tools back in the pouch before the cover is latched", context: OnShift, modifier_hint: Some("work_pace") ),
( action: "logs a fault code into a datapad before moving on", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "presses an ear to a vibrating duct and listens", context: OnShift, modifier_hint: Some("physical_manner") ),
( action: "argues quietly with a display that isn't giving the right numbers", context: OnShift, modifier_hint: Some("social_signal") ),
( action: "queries a fault log through a terminal, eyes briefly unfocused", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "taps a wrench against a junction box lid to test for rattle", context: OnShift, modifier_hint: Some("physical_manner") ),
( action: "pulls a burnt relay from a panel and holds it up to the light", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "clips a sensor lead to two terminals and watches the readout settle", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "photographs a fault site with a handheld before touching anything", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "threads a cable through a conduit run without looking, hands working by feel", context: OnShift, modifier_hint: Some("physical_manner") ),
( action: "checks a pressure gauge by putting a thumb on the dial housing and reading the needle", context: OnShift, modifier_hint: Some("physical_manner") ),
( action: "labels a repaired junction with tape and a marker, block letters", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "reads a service manual on a battered datapad, scrolling with one finger", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "kneels under a raised floor panel with a light between her teeth", context: OnShift, modifier_hint: Some("physical_manner") ),
( action: "closes a maintenance hatch and shoulder-checks it twice", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "stands on the second rung of a ladder and reaches without climbing higher", context: OnShift, modifier_hint: Some("physical_manner") ),
// OffDuty / break room
( action: "stretches both arms overhead in the break room doorway, blocking it without noticing", context: OffDuty, modifier_hint: Some("offduty_posture") ),
( action: "sits sideways in a break room chair, back against the wall, feet on the seat beside her", context: OffDuty, modifier_hint: Some("offduty_posture") ),
( action: "pulls up a schematic on a personal handheld and looks at it between bites", context: OffDuty, modifier_hint: Some("offduty_posture") ),
( action: "refills someone else's cup from the urn without commenting on it", context: OffDuty, modifier_hint: Some("social_signal") ),
( action: "puts her boots on the break room table when off-shift", context: OffDuty, modifier_hint: Some("offduty_posture") ),
( action: "describes a problem to a colleague who doesn't follow it but nods anyway", context: OffDuty, modifier_hint: Some("social_signal") ),
( action: "argues a point at the break room table, tapping the surface for emphasis", context: OffDuty, modifier_hint: Some("social_signal") ),
( action: "reads something on a personal device with his head tipped back and the screen held at arm's length", context: OffDuty, modifier_hint: Some("offduty_posture") ),
( action: "laughs until he has to set down his drink", context: OffDuty, modifier_hint: Some("social_signal") ),
],
),
(
id: "foreman",
label: "Shift Foreman",
skill_focus: ["observation", "persuasion"],
combat_eligible: false,
behavior_primitives: [
// OnShift
( action: "walks the floor with a datapad under one arm and says nothing", context: OnShift, modifier_hint: Some("environmental_scan") ),
( action: "pulls a worker aside for a quiet word near the far wall", context: OnShift, modifier_hint: Some("authority_response") ),
( action: "marks a line off a production board and moves to the next one", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "stands at the mezzanine rail watching throughput without expression", context: OnShift, modifier_hint: Some("environmental_scan") ),
( action: "reviews shift handover notes and circles something with a stylus", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "speaks to a crew in a low voice — they listen without nodding", context: OnShift, modifier_hint: Some("authority_response") ),
( action: "covers a worker's absence from the shift log by redistributing the bay assignments", context: OnShift, modifier_hint: Some("authority_response") ),
( action: "eats lunch standing at a wall terminal so she can keep an eye on the work", context: OnShift, modifier_hint: Some("environmental_scan") ),
( action: "takes the call herself instead of forwarding it", context: OnShift, modifier_hint: Some("authority_response") ),
( action: "corrects a worker's form on a piece of equipment without making it a lesson", context: OnShift, modifier_hint: Some("authority_response") ),
( action: "walks a new hire through the handover checklist once, point by point, no shortcuts", context: OnShift, modifier_hint: Some("authority_response") ),
( action: "keeps a junior worker between herself and the inspection team as the inspectors pass through", context: OnShift, modifier_hint: Some("authority_response") ),
( action: "finds a reason to be nearby when a new worker makes her first solo lift", context: OnShift, modifier_hint: Some("authority_response") ),
( action: "absorbs a production shortfall report without passing the frustration down the line", context: OnShift, modifier_hint: Some("authority_response") ),
( action: "hands a worker an extra meal packet and walks away without explaining it", context: OnShift, modifier_hint: Some("social_signal") ),
( action: "signs off on a repair they didn't personally inspect", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "stands at the edge of the loading floor for a long moment before walking back", context: OnShift, modifier_hint: Some("environmental_scan") ),
( action: "makes a note in the shift log that takes longer to write than it takes to read", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "tells a bad joke to nobody in particular while marking off the production board", context: OnShift, modifier_hint: Some("social_signal") ),
// OffDuty
( action: "sits alone in the break room rubbing the back of her neck, datapad face-down on the table", context: OffDuty, modifier_hint: Some("offduty_posture") ),
( action: "laughs at something a colleague says, then catches herself and goes quiet", context: OffDuty, modifier_hint: Some("social_signal") ),
( action: "sits next to someone in the break room and doesn't talk, just sits", context: OffDuty, modifier_hint: Some("social_signal") ),
],
),
(
id: "security",
label: "Facility Security",
skill_focus: ["combat", "observation"],
combat_eligible: true,
behavior_primitives: [
// OnShift
( action: "sweeps the access corridor on a timed circuit, same path each time", context: OnShift, modifier_hint: Some("work_pace") ),
( action: "waves a regular through the checkpoint on sight — scans the one behind them out of procedure", context: OnShift, modifier_hint: Some("social_signal") ),
( action: "leans at the restricted bay entrance, arms folded, watching the corridor", context: OnShift, modifier_hint: Some("environmental_scan") ),
( action: "notes something in a shift log without reacting to it outwardly", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "watches a handover between crews from across the loading floor", context: OnShift, modifier_hint: Some("environmental_scan") ),
( action: "stops at a junction, looks both ways, and picks the longer route", context: OnShift, modifier_hint: Some("environmental_scan") ),
( action: "runs an ID check on someone whose face she recognizes, procedure is procedure", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "stands with her back to a structural column where both exits are visible", context: OnShift, modifier_hint: Some("environmental_scan") ),
( action: "glances at a badge without stopping the person wearing it", context: OnShift, modifier_hint: Some("social_signal") ),
( action: "checks the restricted bay door seal before settling in to watch the corridor", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "runs the same check routine when the supervisor is watching as when she isn't", context: OnShift, modifier_hint: Some("authority_response") ),
( action: "acknowledges the facility manager's walk-through with a nod and doesn't change her position", context: OnShift, modifier_hint: Some("authority_response") ),
],
),
],
// Valid social site types for this zone type.
// Location specs declare which appear, with their own label, min_npcs, max_npcs.
social_site_types: [
( site_type: "break_room", eligible_roles: ["dock_worker", "technician", "foreman"] ),
( site_type: "maintenance_bay", eligible_roles: ["technician", "dock_worker"] ),
( site_type: "loading_platform", eligible_roles: ["dock_worker", "foreman", "security"] ),
],
)
@@ -0,0 +1,165 @@
// Rural Agricultural Zone-Type Template
//
// Schema: server/src/npc/blueprint.rs :: ZoneTypeTemplate
// Ticket: #661 (copy team)
// Validate: tooling/validate-ron server/content/global/zone-types/rural_agricultural.ron zone_type
//
// Sources: D-142 (zone-type template architecture).
//
// Zone character: scattered homesteads, small workshops, open agricultural land.
// Seasonal work rhythms, low population density, strong community familiarity.
// Work is visible and shared — everyone knows what everyone else is doing.
//
// Primitives are CULTURE-NEUTRAL. Culture modifiers (culture-*.ron files) append
// cultural flavor at assembly time. Do not encode cultural attitudes in action text.
//
// Roles: farmer, mechanic, trader, militia
// Social site types: tavern, workshop, market_stall
(
id: "rural_agricultural",
subtype: None,
label: "Rural Agricultural Zone",
description: "Crop farming, small workshops, communal settlement. Low density, community-bonded, self-sufficient economy. Work is visible to neighbors — everyone knows what everyone else is doing.",
// Default economic/density profile. Location specs override.
economic_level: 3,
population_density: 2,
roles: [
(
id: "farmer",
label: "Farmer",
skill_focus: ["technical"],
combat_eligible: false,
// weight omitted — location specs declare role_weights
behavior_primitives: [
// OnShift
( action: "works back along a crop row, stopping to pull weeds by the root", context: OnShift, modifier_hint: Some("work_pace") ),
( action: "lifts a crate of produce onto a flatbed and reaches for the next before it settles", context: OnShift, modifier_hint: Some("physical_manner") ),
( action: "checks the section's light cycle timer before deciding whether to water", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "patches a cracked irrigation pipe with bonding tape", context: OnShift, modifier_hint: Some("work_pace") ),
( action: "calls across a field to a neighbor without looking up from work", context: OnShift, modifier_hint: Some("social_signal") ),
( action: "hauls produce to the market stall before the morning exchange opens", context: OnShift, modifier_hint: Some("work_pace") ),
( action: "crouches over seedling trays and pinches back a leggy stem that grew sideways", context: OnShift, modifier_hint: Some("physical_manner") ),
( action: "runs a thumb along the edge of a cracked irrigation seal, then sets it aside", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "stacks empty crates at the end of a row", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "drags a length of hose to a dry section and clamps the fitting by hand", context: OnShift, modifier_hint: Some("work_pace") ),
( action: "kneels at the base of a struggling plant and parts the soil with two fingers", context: OnShift, modifier_hint: Some("physical_manner") ),
( action: "leans on a fence post and watches the sky before going back to the row", context: OnShift, modifier_hint: Some("environmental_scan") ),
( action: "refills a handheld sprayer from a standing drum", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "ties a row marker to a stake with a short length of wire", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "pulls a glove off to wipe her face, pulls it back on without looking", context: OnShift, modifier_hint: Some("physical_manner") ),
( action: "loads a wheelbarrow and tips it into a compost bin at the field edge", context: OnShift, modifier_hint: Some("work_pace") ),
( action: "pulls a dead plant by the roots and carries it to the burn pile", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "tests soil moisture by pressing a thumb into the ground beside a seedling", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "walks the field edge, pulling the wire taut at each span to test the tension", context: OnShift, modifier_hint: Some("environmental_scan") ),
( action: "sets two crates down on the market floor and counts the lids twice", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "answers an inspector's question without breaking the task rhythm", context: OnShift, modifier_hint: Some("authority_response") ),
( action: "waits for the settlement head to finish speaking before going back to work", context: OnShift, modifier_hint: Some("authority_response") ),
// Social / off-duty
( action: "nurses a drink at the end of the bar with both hands wrapped around the glass", context: Social, modifier_hint: Some("offduty_posture") ),
( action: "trades short words with the person at the next seat without turning fully around", context: Social, modifier_hint: Some("social_signal") ),
( action: "sits with boots off under the table, socked feet flat on the floor", context: Social, modifier_hint: Some("offduty_posture") ),
( action: "refills a neighbor's cup from her own jug without being asked", context: Social, modifier_hint: Some("social_signal") ),
( action: "plays a slow tile game with two others at the corner table", context: Social, modifier_hint: Some("offduty_posture") ),
( action: "slides a credit chit across the bar and waits for change without counting it", context: Social, modifier_hint: Some("offduty_posture") ),
( action: "leans back in the chair and stares at the ceiling for a long moment", context: Social, modifier_hint: Some("offduty_posture") ),
],
),
(
id: "mechanic",
label: "Settlement Mechanic",
skill_focus: ["technical"],
combat_eligible: false,
behavior_primitives: [
// OnShift
( action: "pulls a drive unit from a tiller and examines the worn housing", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "wipes grease on the thigh of her coveralls between jobs", context: OnShift, modifier_hint: Some("physical_manner") ),
( action: "explains a repair in clipped shorthand without looking up", context: OnShift, modifier_hint: Some("social_signal") ),
( action: "lines up salvaged parts on a workbench and assesses them", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "welds a seam on a cracked water tank with slow, careful strokes", context: OnShift, modifier_hint: Some("work_pace") ),
( action: "borrows a tool from a neighbor and returns it without being asked", context: OnShift, modifier_hint: Some("social_signal") ),
( action: "taps a seized bolt with a mallet twice before reaching for a longer bar", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "threads a wire through a conduit clip and bites the insulation back with her teeth", context: OnShift, modifier_hint: Some("physical_manner") ),
( action: "sets a part down, picks up the spec card beside it, and reads it once", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "uses a straight edge to check the flatness of a repaired flange", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "drains a coolant line into a catch tray and marks the container", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "torques a fastener by feel and then confirms it with a wrench click", context: OnShift, modifier_hint: Some("physical_manner") ),
( action: "stacks finished repairs in a corner and photographs them with a handheld", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "jots a note on a strip of tape and sticks it to a part's casing", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "squeezes into a narrow access panel and works by touch", context: OnShift, modifier_hint: Some("physical_manner") ),
( action: "straightens up and rolls her neck once before kneeling back down", context: OnShift, modifier_hint: Some("physical_manner") ),
// Social / off-duty
( action: "rinses her hands twice at the basin before sitting down at the bar", context: Social, modifier_hint: Some("offduty_posture") ),
( action: "drops her toolkit bag under the stool and orders without looking at the board", context: Social, modifier_hint: Some("offduty_posture") ),
( action: "listens to a complaint about a piece of equipment and nods once or twice", context: Social, modifier_hint: Some("social_signal") ),
( action: "draws a rough diagram on a napkin to explain something, then folds it away", context: Social, modifier_hint: Some("social_signal") ),
( action: "buys a round for the table and returns to her seat before anyone can thank her", context: Social, modifier_hint: Some("social_signal") ),
],
),
(
id: "trader",
label: "Itinerant Trader",
skill_focus: ["persuasion", "observation"],
combat_eligible: false,
behavior_primitives: [
// OnShift
( action: "squares goods on a fold-out portable display", context: OnShift, modifier_hint: Some("work_pace") ),
( action: "leans back on a stool and tracks a browser who has checked the same display twice without committing", context: OnShift, modifier_hint: Some("environmental_scan") ),
( action: "flicks credit chits across the counter with one thumb", context: OnShift, modifier_hint: Some("physical_manner") ),
( action: "holds eye contact through a long pause, waiting for the price to land", context: OnShift, modifier_hint: Some("social_signal") ),
( action: "watches a regular browse the same shelf as last time and says nothing", context: OnShift, modifier_hint: Some("environmental_scan") ),
( action: "packs unsold goods without reacting", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "unrolls a cloth display on the counter and weights the corners with small stones", context: OnShift, modifier_hint: Some("work_pace") ),
( action: "lifts a sample item and sets it in the light where a browser can see it clearly", context: OnShift, modifier_hint: Some("social_signal") ),
( action: "rewraps an unsold item and tucks it back in the case with a specific order", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "counts coins into a small tray and slides it across the counter", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "pulls a ledger from the bag, checks one line, and closes it", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "marks a price down on the board with a grease stylus and steps back", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "holds a cracked item up to show where it failed before handing it back", context: OnShift, modifier_hint: Some("social_signal") ),
( action: "folds the portable display flat and straps it to the pack in two moves", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "lays two items side by side on the counter for a customer to compare", context: OnShift, modifier_hint: Some("social_signal") ),
( action: "wipes down the counter surface with a cloth before setting out the next goods", context: OnShift, modifier_hint: Some("work_pace") ),
// Social
( action: "nurses a drink at the far end of the bar, watching who comes in", context: Social, modifier_hint: Some("environmental_scan") ),
( action: "talks price with whoever's sitting nearest without making it a pitch", context: Social, modifier_hint: Some("social_signal") ),
( action: "buys a round and tracks who accepts and who doesn't", context: Social, modifier_hint: Some("social_signal") ),
( action: "listens more than she talks at the bar, refilling her glass slowly", context: Social, modifier_hint: Some("offduty_posture") ),
],
),
(
id: "militia",
label: "Settlement Militia",
skill_focus: ["combat", "observation"],
combat_eligible: true,
behavior_primitives: [
// OnShift
( action: "walks the fence line at a measured, unhurried pace", context: OnShift, modifier_hint: Some("work_pace") ),
( action: "leans on the gate post with rifle slung, watching the road", context: OnShift, modifier_hint: Some("environmental_scan") ),
( action: "waves a familiar face through without checking credentials", context: OnShift, modifier_hint: Some("social_signal") ),
// on-duty quiet time — context is OnShift but posture reads as off-duty
( action: "sits in the shade of the gatehouse reading a local newsline", context: OnShift, modifier_hint: Some("offduty_posture") ),
( action: "stops to talk with a passerby, eyes still scanning the perimeter", context: OnShift, modifier_hint: Some("social_signal") ),
( action: "checks the charge on a handheld scanner and clips it back to the belt", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "props a boot on the lower fence rail and scans the far end of the road", context: OnShift, modifier_hint: Some("environmental_scan") ),
( action: "nods to a passing cart and tracks it until it clears the gate", context: OnShift, modifier_hint: Some("environmental_scan") ),
( action: "marks a log entry on a handheld at the end of a perimeter pass", context: OnShift, modifier_hint: Some("task_completion") ),
( action: "steps out of the gatehouse at the sound of an approaching engine", context: OnShift, modifier_hint: Some("environmental_scan") ),
( action: "reports a situation to the settlement head without editorializing", context: OnShift, modifier_hint: Some("authority_response") ),
( action: "straightens slightly when the relief officer arrives for handover", context: OnShift, modifier_hint: Some("authority_response") ),
// OffDuty
( action: "sits at the end of the bar still in kit, drink in hand, not really off yet", context: OffDuty, modifier_hint: Some("offduty_posture") ),
( action: "catches up with a neighbor over a drink without mentioning work", context: Social, modifier_hint: Some("social_signal") ),
],
),
],
// Valid social site types for this zone type.
// Location specs declare which appear, with their own label, min_npcs, max_npcs.
social_site_types: [
( site_type: "tavern", eligible_roles: ["farmer", "mechanic", "trader", "militia"] ),
( site_type: "workshop", eligible_roles: ["mechanic", "farmer"] ),
( site_type: "market_stall", eligible_roles: ["trader", "farmer"] ),
],
)