From fa4d30a9512bf7de7e57d4e7701c431eb71182ea Mon Sep 17 00:00:00 2001 From: Jeroen Schweitzer Date: Tue, 24 Feb 2026 11:13:54 +0100 Subject: [PATCH 1/6] =?UTF-8?q?feat(content):=20author=20contradiction=20m?= =?UTF-8?q?onologue=20lines=20=E2=80=94=20Sera/Kael=20FRIEND=20arc=20(#552?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Source-named contradiction monologue for both detective and smuggler. Detective: Sera/Kael location contradiction (Phase 2 blindsiding + Phase 3 pattern recognition with Torek avoidance). Smuggler: Kael in B-7 with unrecognized contact (Phase 2 gut reaction + Phase 3 behavioral pattern accumulation). Cognitive-dissonance-not-accusation tone per D-083. 16 hand-authored lines total (8 per character). Co-Authored-By: Claude Opus 4.6 --- .../detective/contradiction-detected.yaml | 220 +++++++++++++++++ .../smuggler/contradiction-detected.yaml | 229 ++++++++++++++++++ 2 files changed, 449 insertions(+) create mode 100644 content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/detective/contradiction-detected.yaml create mode 100644 content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/smuggler/contradiction-detected.yaml diff --git a/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/detective/contradiction-detected.yaml b/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/detective/contradiction-detected.yaml new file mode 100644 index 000000000..421557b55 --- /dev/null +++ b/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/detective/contradiction-detected.yaml @@ -0,0 +1,220 @@ +character: detective +location: contradiction-detected +lines: + # Contradiction Monologue — Ticket #552 — Sera/Kael FRIEND Arc + # Authored per D-083 (contradiction detection pipeline) and Paula Round 2 Mellanie spec + # (docs/workshops/knowledge-flow-npc-boundaries/paula-round2.md, lines 117-158). + # + # Trigger: contradiction_detected fires when the detective observes Kael in Corridor B-7 + # while the KG holds Sera's claim that Kael was at dock intake during second shift. + # Event payload: source_display_name = "Sera Venn", subject_display_name = "Kael Davan" + # + # FRIEND-pattern NPCs (Sera, Kael) always use hand-authored lines — generic template fallback + # does not fire for this arc. + # + # Authoring principle: cognitive dissonance, not accusation. The detective doesn't know + # who or what is wrong. Uncertainty first, suspicion second, accusation never. + # + # Phase 2 lines: trust established but not deep — the blindsiding. + # Prerequisites: KG entry for Kael has state: Contradicted, source: ToldBy(Sera Venn) + # Phase 3 lines: additional context accumulated — Sera's avoidance of Torek observed 3x. + # Prerequisites: Phase 2 + Sera's avoidance pattern has fired (three departures logged). + # + # ID discriminator: _con_ marks contradiction lines per Q-028 pending resolution. + # cooldown: -1 — these are one-time events. Should not repeat. + + # ----------------------------------------------------------------------- + # PHASE 2 — Primary beat (fires on contradiction_detected, immediate) + # ----------------------------------------------------------------------- + + - id: pc-detective_m_d_con_001 + text: "Sera said Kael was at the dock intake during second shift. I'm looking at him in corridor B-7 right now." + role: player_character + access: [public] + trust: real + situation: [investigation, observation, contradiction] + trigger: contradiction_detected + mood: [focused, anxious] + priority: 10 + cooldown: -1 + phase: 2 + prerequisites: + - entity: "npc:kael-davan" + state: Contradicted + - source_name: "Sera Venn" + tags: [contradiction, friend-arc, sera, kael, phase-2, analytical] + notes: > + Paula's canonical primary line — preserved verbatim. Flat factual statement: source named, + subject named, specific location claim vs. direct observation. The 'I'm' contraction is + natural in a surprise moment even for the analytical detective — the observation breaks + through the professional register. No interpretation, no accusation. + + - id: pc-detective_m_d_con_002 + text: "Venn said Kael was at dock intake through second shift. Kael is in B-7. Those aren't compatible." + role: player_character + access: [public] + trust: real + situation: [investigation, observation, contradiction] + trigger: contradiction_detected + mood: [focused] + priority: 9 + cooldown: -1 + phase: 2 + prerequisites: + - entity: "npc:kael-davan" + state: Contradicted + - source_name: "Sera Venn" + tags: [contradiction, friend-arc, sera, kael, phase-2, analytical] + notes: > + Alternate primary — fully analytical register: surname-initial for both (institutional + reflex), no contractions, plain declarative close. 'Those aren't compatible' is the + detective's version of stating contradiction — clinical, process-language. Fires as + alternate to con_001 for variety on replay. + + - id: pc-detective_m_d_con_003 + text: "She placed Kael at the dock. He's not at the dock." + role: player_character + access: [public] + trust: real + situation: [investigation, observation, contradiction] + trigger: contradiction_detected + mood: [focused, anxious] + priority: 9 + cooldown: -1 + phase: 2 + prerequisites: + - entity: "npc:kael-davan" + state: Contradicted + - source_name: "Sera Venn" + tags: [contradiction, friend-arc, sera, kael, phase-2] + notes: > + Stripped-down alternate. 'She placed' is the informal of 'Venn stated' — personal register + triggered by Sera being THE FRIEND. 'He's not at the dock' — the barest possible statement + of contradiction. The brevity is the weight: six words and the investigation changes shape. + + # ----------------------------------------------------------------------- + # PHASE 2 — Secondary beat (fires after short delay, cognitive processing) + # ----------------------------------------------------------------------- + + - id: pc-detective_m_d_con_004 + text: "One of them is wrong. Sera, or what I'm seeing. Or I'm missing something I don't have yet." + role: player_character + access: [public] + trust: real + situation: [investigation, reflection, contradiction] + trigger: contradiction_processing + mood: [anxious, focused] + priority: 10 + cooldown: -1 + phase: 2 + prerequisites: + - entity: "npc:kael-davan" + state: Contradicted + - source_name: "Sera Venn" + tags: [contradiction, friend-arc, sera, kael, phase-2, cognitive-dissonance] + notes: > + Paula's canonical secondary beat — fires 3-5 seconds after the primary beat. + Epistemic neutrality held across three options: Sera is wrong, observation is wrong, or + context is missing. No option is dismissed. 'I'm missing something I don't have yet' is + the key line — it holds accusation off even against evidence. The detective files it open. + + - id: pc-detective_m_d_con_005 + text: "File it. Don't close it. Either Venn's information was wrong when she gave it, or it was wrong on purpose. That's a different question." + role: player_character + access: [public] + trust: real + situation: [investigation, reflection, contradiction] + trigger: contradiction_processing + mood: [focused] + priority: 9 + cooldown: -1 + phase: 2 + prerequisites: + - entity: "npc:kael-davan" + state: Contradicted + - source_name: "Sera Venn" + tags: [contradiction, friend-arc, sera, kael, phase-2, analytical, cognitive-dissonance] + notes: > + Alternate secondary beat. 'File it, don't close it' is the detective's internal procedure + for unresolved data. The critical distinction: wrong information vs. deliberately wrong + information — the detective separates these without assuming either. 'That's a different + question' closes the processing loop, marking it unresolved, not dismissed. + + # ----------------------------------------------------------------------- + # PHASE 3 — With accumulated context (Sera's avoidance pattern observed) + # Requires: three Sera departures correlated with Torek Lintar arrivals observed. + # ----------------------------------------------------------------------- + + - id: pc-detective_m_d_con_006 + text: "Sera told me Kael doesn't make mistakes. He's not where she said he'd be. And she's been avoiding Lintar for three weeks." + role: player_character + access: [public] + trust: real + situation: [investigation, observation, contradiction] + trigger: contradiction_detected + mood: [focused, anxious] + priority: 10 + cooldown: -1 + phase: 3 + prerequisites: + - entity: "npc:kael-davan" + state: Contradicted + - source_name: "Sera Venn" + - pattern: sera_avoidance_lintar + count_min: 3 + tags: [contradiction, friend-arc, sera, kael, phase-3, pattern-recognition] + notes: > + Paula's canonical Phase 3 line — preserved verbatim. Three facts in sequence, no explicit + connection drawn between them: Sera's testimony about Kael ('doesn't make mistakes'), + Kael's actual location, Sera's avoidance behavior. The detective is connecting dots but + not announcing the conclusion. The emotional weight is in 'Sera told me' — personal register + for the friend relationship — vs. the clinical observation about Lintar. + + - id: pc-detective_m_d_con_007 + text: "Two facts: Venn placed Kael at dock intake, second shift. Kael is in B-7. One new observation: Venn leaves every time Lintar enters the bar. Worth seeing if those connect." + role: player_character + access: [public] + trust: real + situation: [investigation, observation, contradiction] + trigger: contradiction_detected + mood: [focused] + priority: 9 + cooldown: -1 + phase: 3 + prerequisites: + - entity: "npc:kael-davan" + state: Contradicted + - source_name: "Sera Venn" + - pattern: sera_avoidance_lintar + count_min: 3 + tags: [contradiction, friend-arc, sera, kael, phase-3, analytical, pattern-recognition] + notes: > + Alternate Phase 3 — analytical register throughout, no personal register even for Sera + (surname only). 'Worth seeing if those connect' is the detective's verbal tic of flagging + without concluding. The numbered format ('Two facts... One new observation') is the + detective's internal case-building style. Fully non-accusatory: the connection is not + stated, only the intent to look for it. + + - id: pc-detective_m_d_con_008 + text: "Venn's been managing her exits around Lintar. And she put Kael somewhere he isn't. Let's see what sits at the intersection of those two." + role: player_character + access: [public] + trust: real + situation: [investigation, reflection, contradiction] + trigger: contradiction_detected + mood: [focused] + priority: 8 + cooldown: -1 + phase: 3 + prerequisites: + - entity: "npc:kael-davan" + state: Contradicted + - source_name: "Sera Venn" + - pattern: sera_avoidance_lintar + count_min: 3 + tags: [contradiction, friend-arc, sera, kael, phase-3, analytical] + notes: > + Alternate Phase 3. 'Let's see what' verbal tic, no accusation. 'Managing her exits' is + the detective naming Sera's avoidance behavior — behavioral description, not motive + attribution. 'Put Kael somewhere he isn't' — plain contradiction framing. The intersection + remains unstated. Detective is following the thread, not announcing what's on it. diff --git a/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/smuggler/contradiction-detected.yaml b/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/smuggler/contradiction-detected.yaml new file mode 100644 index 000000000..45a76a2e0 --- /dev/null +++ b/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/smuggler/contradiction-detected.yaml @@ -0,0 +1,229 @@ +character: smuggler +location: contradiction-detected +lines: + # Contradiction Monologue — Ticket #552 — Sera/Kael FRIEND Arc (Smuggler perspective) + # Authored per D-083 (contradiction detection pipeline) and Paula Round 2 Mellanie spec + # (docs/workshops/knowledge-flow-npc-boundaries/paula-round2.md, lines 117-158). + # + # Trigger: contradiction_detected fires when the smuggler observes Kael in Corridor B-7 + # with an unrecognized contact — contradicting Kael's stated location and ring protocol. + # Event payload: source_display_name = "Kael Davan", subject_display_name = "Kael Davan" + # (Kael is both source and subject: he placed himself elsewhere, smuggler sees him here.) + # + # FRIEND-pattern NPCs always use hand-authored lines — generic template fallback + # does not fire for this arc. + # + # Authoring principle: cognitive dissonance, not accusation. The smuggler reads social + # signals instinctively, but doesn't conclude — she contains the alarm. Street-smart + # gut reaction, not analytical procedure. + # + # Phase 2 lines: first observation — Kael in B-7 with unknown contact. + # Prerequisites: KG entry for Kael has state: Contradicted, source: ToldBy(Kael Davan) + # Phase 3 lines: behavioral pattern already accumulating — increased lattice checking, + # shortened interactions, early exits from break room. + # Prerequisites: Phase 2 + Kael's behavioral anomalies observed (count ≥ 2). + # + # ID discriminator: _con_ marks contradiction lines per Q-028 pending resolution. + # cooldown: -1 — one-time events. Should not repeat. + + # ----------------------------------------------------------------------- + # PHASE 2 — Primary beat (fires on contradiction_detected, immediate) + # ----------------------------------------------------------------------- + + - id: pc-smuggler_m_s_con_001 + text: "Kael said second shift was clear. He's in B-7. With someone I don't know." + role: player_character + access: [public] + trust: real + situation: [investigation, observation, contradiction] + trigger: contradiction_detected + mood: [focused, anxious] + priority: 10 + cooldown: -1 + phase: 2 + prerequisites: + - entity: "npc:kael-davan" + state: Contradicted + - source_name: "Kael Davan" + tags: [contradiction, friend-arc, kael, phase-2, operational] + notes: > + Primary line — three beats, three facts. 'Kael said' names the source (friend register, + first name). 'He's in B-7' is the observation. 'With someone I don't know' is the alarm: + not just wrong location, but outside the ring. Fragment structure throughout — the smuggler + clocks a scene in pieces. No accusation, no conclusion: just inventory of what's wrong. + + - id: pc-smuggler_m_s_con_002 + text: "That's Kael. Restricted corridor. Unrecognized contact. Kael doesn't come to B-7." + role: player_character + access: [public] + trust: real + situation: [investigation, observation, contradiction] + trigger: contradiction_detected + mood: [focused] + priority: 9 + cooldown: -1 + phase: 2 + prerequisites: + - entity: "npc:kael-davan" + state: Contradicted + - source_name: "Kael Davan" + tags: [contradiction, friend-arc, kael, phase-2, operational] + notes: > + Alternate primary — catalog format. 'That's Kael' opens with identification, not alarm: + recognition first, then the wrong details fall into place. Each fragment adds one layer + of what's wrong. Close: 'Kael doesn't come to B-7' — negative statement of prior + expectation, which is now violated. No contraction in the closing declarative (emphasis). + + - id: pc-smuggler_m_s_con_003 + text: "He's in B-7. He told me he'd be heading home after shift. One of those isn't the case." + role: player_character + access: [public] + trust: real + situation: [investigation, observation, contradiction] + trigger: contradiction_detected + mood: [focused, anxious] + priority: 9 + cooldown: -1 + phase: 2 + prerequisites: + - entity: "npc:kael-davan" + state: Contradicted + - source_name: "Kael Davan" + tags: [contradiction, friend-arc, kael, phase-2] + notes: > + Alternate primary — echoes the Paula canonical structure (observation / prior claim / + contradiction stated) but in the smuggler's voice. 'He told me' is personal register + (friend, not colleague). 'One of those isn't the case' — the smuggler's understated + version of flagging a contradiction: not 'one of them is a lie' but 'isn't the case.' + Epistemic containment in plain language. + + # ----------------------------------------------------------------------- + # PHASE 2 — Secondary beat (gut-level recalibration, operational containment) + # ----------------------------------------------------------------------- + + - id: pc-smuggler_m_s_con_004 + text: "Maybe there's a reason. There's always a reason. But Kael knows better than to run a meeting in a maintenance corridor without telling me." + role: player_character + access: [public] + trust: real + situation: [investigation, reflection, contradiction] + trigger: contradiction_processing + mood: [focused, anxious] + priority: 10 + cooldown: -1 + phase: 2 + prerequisites: + - entity: "npc:kael-davan" + state: Contradicted + - source_name: "Kael Davan" + tags: [contradiction, friend-arc, kael, phase-2, cognitive-dissonance] + notes: > + Secondary beat — fires 3-5 seconds after primary. Self-challenge first: the smuggler + gives Kael benefit of the doubt, then immediately walks it back with operational + logic. 'There's always a reason' is the street-smart equivalent of epistemic + containment — she's seen strange things before. The closing line is where the alarm + lives: this isn't strange, it's a protocol violation. + + - id: pc-smuggler_m_s_con_005 + text: "Don't assume. Could be he's running something for Nils I wasn't told about. Could be something else. The second thing is the problem." + role: player_character + access: [public] + trust: real + situation: [investigation, reflection, contradiction] + trigger: contradiction_processing + mood: [focused] + priority: 9 + cooldown: -1 + phase: 2 + prerequisites: + - entity: "npc:kael-davan" + state: Contradicted + - source_name: "Kael Davan" + tags: [contradiction, friend-arc, kael, phase-2, operational, cognitive-dissonance] + notes: > + Alternate secondary beat. 'Don't assume' is the smuggler's self-instruction (operational + discipline). Two possibilities held open: ring-authorized (names Nils — the coordinator) + vs. outside the ring. 'The second thing is the problem' — the alarm, stated as dry + understatement. Operational logic applied to an emotional moment: the smuggler + keeps the processing clean even when the stakes are personal. + + # ----------------------------------------------------------------------- + # PHASE 3 — Behavioral pattern accumulated (increased lattice checking, early exits) + # Requires: Kael behavioral anomalies observed prior to the B-7 contradiction. + # ----------------------------------------------------------------------- + + - id: pc-smuggler_m_s_con_006 + text: "He's been distracted for three days. Lattice checks every few minutes, leaving lunch early. Now a B-7 meeting with someone outside the ring. Kael's working an angle he hasn't told me about." + role: player_character + access: [public] + trust: real + situation: [investigation, observation, contradiction] + trigger: contradiction_detected + mood: [focused, anxious] + priority: 10 + cooldown: -1 + phase: 3 + prerequisites: + - entity: "npc:kael-davan" + state: Contradicted + - source_name: "Kael Davan" + - pattern: kael_behavioral_anomaly + count_min: 2 + tags: [contradiction, friend-arc, kael, phase-3, pattern-recognition, operational] + notes: > + Phase 3 primary — connects all accumulated behavioral data to the contradiction. Fragment + catalog builds the picture: three days of signals, then this. Closing line names the + conclusion without naming its implication: 'working an angle' is street-smart language + for running something unauthorized, but the smuggler doesn't say 'exit attempt' — + she doesn't know that yet. + + - id: pc-smuggler_m_s_con_007 + text: "Kael doesn't run his own contacts. Devra handles external. So either Devra knows about this, or Kael's outside protocol. Neither's good." + role: player_character + access: [public] + trust: real + situation: [investigation, observation, contradiction] + trigger: contradiction_detected + mood: [focused] + priority: 9 + cooldown: -1 + phase: 3 + prerequisites: + - entity: "npc:kael-davan" + state: Contradicted + - source_name: "Kael Davan" + - pattern: kael_behavioral_anomaly + count_min: 2 + tags: [contradiction, friend-arc, kael, phase-3, operational] + notes: > + Alternate Phase 3 — operational knowledge applied. The smuggler knows ring structure: + Devra manages external contacts, Kael handles cargo logistics. An unrecognized contact + means either Devra is running something Kael's involved in (plausible, alarming) or + Kael went outside protocol (worse). Both possibilities named, neither closed. 'Neither's + good' — the smuggler's understated close for a significant threat read. + + - id: pc-smuggler_m_s_con_008 + text: "He's been somewhere else in his head all week. Now I know why. Whoever that was — not ring. Kael's looking for a way out." + role: player_character + access: [public] + trust: real + situation: [investigation, observation, contradiction] + trigger: contradiction_detected + mood: [anxious] + priority: 8 + cooldown: -1 + phase: 3 + prerequisites: + - entity: "npc:kael-davan" + state: Contradicted + - source_name: "Kael Davan" + - pattern: kael_behavioral_anomaly + count_min: 2 + tags: [contradiction, friend-arc, kael, phase-3, intuition] + notes: > + Alternate Phase 3 — gut read, highest emotional weight. 'Somewhere else in his head' + describes the behavioral changes without cataloging them. 'Now I know why' — the click + of understanding arriving. 'Not ring' — short, certain, two words. 'Looking for a way + out' is street-smart language for exit attempt: the smuggler doesn't know the details + but the read is right. This line is the closest the smuggler comes to naming what's + happening — and she still doesn't say it explicitly. From da34b92421d89473a1ce4599b3ff96dd3cbe2ca4 Mon Sep 17 00:00:00 2001 From: Jeroen Schweitzer Date: Tue, 24 Feb 2026 11:14:01 +0100 Subject: [PATCH 2/6] =?UTF-8?q?feat(content):=20author=20diegetic=20tutori?= =?UTF-8?q?al=20monologue=20lines=20=E2=80=94=20per=20character=20(#330)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 10 lines per character teaching 5 core mechanics diegetically: movement/exploration, fog of perception, sound model, NPC interaction, insert/HUD. Detective lines in analytical register, smuggler lines in street-smart fragments. Fires on first-time events (first_move, first_fog_encounter, first_sound_heard, first_npc_proximity, first_insert_open, etc.). _tut_ ID discriminator, cooldown -1. Co-Authored-By: Claude Opus 4.6 --- .../transit/monologue/detective/tutorial.yaml | 231 ++++++++++++++++++ .../transit/monologue/smuggler/tutorial.yaml | 216 ++++++++++++++++ 2 files changed, 447 insertions(+) create mode 100644 content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/detective/tutorial.yaml create mode 100644 content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/smuggler/tutorial.yaml diff --git a/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/detective/tutorial.yaml b/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/detective/tutorial.yaml new file mode 100644 index 000000000..103b9541f --- /dev/null +++ b/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/detective/tutorial.yaml @@ -0,0 +1,231 @@ +character: detective +location: tutorial +lines: + # Diegetic Tutorial Monologue — Ticket #330 — Detective + # Authored per sprint-17 copy briefing and D-016 (internal monologue as core system). + # + # These lines teach mechanics through character voice — not UI instructions. + # Distinct from opening.yaml (which covers the first 5 minutes and sets voice/motivation). + # These fire on first-time events throughout gameplay, wherever they occur. + # + # Coverage: + # Movement / exploration — first_move, first_new_section + # Fog of perception — first_fog_encounter, first_fog_edge + # Sound model — first_sound_heard, first_off_screen_sound + # NPC interaction — first_npc_proximity, first_npc_face_read + # Insert / HUD — first_insert_open, first_insert_contact_flag + # + # Voice: analytical, procedure-oriented, careful. No contractions in analytical mode. + # Colon usage for categorization. 'Let's see what...' and 'Worth flagging' verbal tics. + # ID discriminator: _tut_ per sprint briefing. + # cooldown: -1 — fire once, never repeat. + # priority: tutorial — higher than general pool lines. + + # ----------------------------------------------------------------------- + # MOVEMENT / EXPLORATION + # ----------------------------------------------------------------------- + + - id: pc-detective_m_d_tut_001 + text: "Signage: section designators on the corridor wall. Commission-standard markings. Worth learning before the district learns me." + role: player_character + access: [public] + trust: surface + situation: [movement, exploration] + trigger: first_move + mood: [focused] + priority: tutorial + cooldown: -1 + tags: [tutorial, movement, navigation, analytical] + notes: > + Detective version of the 'check the signage' tutorial. Colon usage for the signage + label (section 2.2 verbal pattern). 'Commission-standard markings' — institutional + framing; he reads the environment through his professional lens first. 'Worth learning + before the district learns me' — dry awareness of his asymmetric visibility in this + community. Same teaching as the smuggler version, different cognitive frame. + + - id: pc-detective_m_d_tut_002 + text: "Three sections in range from the main terminal. Commission briefing had the layout. Let's confirm it against the floor." + role: player_character + access: [public] + trust: surface + situation: [movement, investigation] + trigger: first_new_section + mood: [focused] + priority: tutorial + cooldown: -1 + tags: [tutorial, movement, navigation, analytical] + notes: > + Fires on entering a new section for the first time. 'Commission briefing had the + layout' — he arrived with a map, now he's verifying it against reality. 'Let's + confirm it against the floor' — 'Let's' verbal tic, investigative method stated as + principle: documentation is a starting point, not a substitute for observation. + Teaches: the district has distinct sections to explore. + + # ----------------------------------------------------------------------- + # FOG OF PERCEPTION + # ----------------------------------------------------------------------- + + - id: pc-detective_m_d_tut_003 + text: "Visual range terminates at the corridor junction. Consistent with district atmo settings. Anything past that point: unconfirmed." + role: player_character + access: [public] + trust: surface + situation: [observation, exploration] + trigger: first_fog_encounter + mood: [focused] + priority: tutorial + cooldown: -1 + tags: [tutorial, fog, perception, analytical] + notes: > + Detective fog tutorial — analytical register throughout. 'Visual range terminates at' + instead of 'Can't see past.' 'Consistent with atmo settings' — he already knows this + is an environmental property, not an anomaly. 'Anything past that point: unconfirmed' + — colon usage, precise epistemic status. Teaches: perception boundary exists, and + the detective categorizes it as an information state, not a barrier. Compare to + smuggler's 'Might be worth checking' — same fog, different response. + + - id: pc-detective_m_d_tut_004 + text: "Can't clear the far bay from here. Going around is the procedure — not a limitation, a working condition." + role: player_character + access: [public] + trust: surface + situation: [observation] + trigger: first_fog_edge + mood: [focused] + priority: tutorial + cooldown: -1 + tags: [tutorial, fog, perception, analytical] + notes: > + Second fog encounter line — fires at a fog zone boundary. 'Going around is the + procedure' — detective frames the limitation as methodology. The second clause + ('not a limitation, a working condition') is self-instruction: he's telling himself + not to treat fog as frustrating but as standard operating environment. Teaches: + perception range is persistent throughout gameplay, and the correct response is + movement, not waiting. + + # ----------------------------------------------------------------------- + # SOUND MODEL + # ----------------------------------------------------------------------- + + - id: pc-detective_m_d_tut_005 + text: "Voices. Down the corridor. Source count indeterminate from here — distance degrades clarity." + role: player_character + access: [public] + trust: surface + situation: [observation] + trigger: first_sound_heard + mood: [focused] + priority: tutorial + cooldown: -1 + tags: [tutorial, sound, perception, analytical] + notes: > + Detective sound tutorial — analytical framing of the briefing's example. 'Source count + indeterminate' is the precise version of 'can't tell how many.' 'Distance degrades + clarity' — technical, causal. He hears, notes what he can establish (voices, direction) + and what he can't (count, content). No contractions. Teaches: sound channel is active + and distance-limited. Compare to smuggler's 'Can't make out the words' — same acoustic + reality, systematized differently. + + - id: pc-detective_m_d_tut_006 + text: "Footsteps. Metal-grated surface. Two sets minimum — moving away. Service access corridor, by the acoustic signature." + role: player_character + access: [public] + trust: surface + situation: [observation] + trigger: first_off_screen_sound + mood: [focused] + priority: tutorial + cooldown: -1 + tags: [tutorial, sound, perception, analytical] + notes: > + Second sound tutorial — fires on an off-screen audio source. The detective parses + the sound through multiple analytical dimensions: surface type, count, direction, + room type. 'Two sets minimum' — precise but not overclaiming. 'By the acoustic + signature' is technical terminology applied to diegetic audio interpretation. + Teaches: sound carries more than presence — floor type, distance, count, direction + are all extractable. The detective extracts all of them automatically. + + # ----------------------------------------------------------------------- + # NPC INTERACTION + # ----------------------------------------------------------------------- + + - id: pc-detective_m_d_tut_007 + text: "Civilians in range. Standard approach: observe before engaging. Let them surface what's relevant before directing the conversation." + role: player_character + access: [public] + trust: surface + situation: [social, observation] + trigger: first_npc_proximity + mood: [focused] + priority: tutorial + cooldown: -1 + tags: [tutorial, npc, interaction, analytical] + notes: > + Detective NPC tutorial — procedural, method-as-principle. 'Civilians in range' is + his categorization (Commission-trained: everyone is a witness category until proven + otherwise). 'Standard approach' — he has a protocol. 'Let them surface what's relevant' + is the investigative principle: don't prime witnesses, let them self-select information. + No contractions throughout. Teaches: NPC interaction is player-initiated and + approach-sensitive. Different method than the smuggler ('give them reason to') — + same outcome, different social model. + + - id: pc-detective_m_d_tut_008 + text: "Commission credentials flag on approach. They know who I am before I speak. Worth noting who adjusts their behavior." + role: player_character + access: [public] + trust: surface + situation: [social, investigation] + trigger: first_npc_face_read + mood: [focused] + priority: tutorial + cooldown: -1 + tags: [tutorial, npc, observation, analytical, authority] + notes: > + Fires when the player observes an NPC at close range. The detective's asymmetry: + his authority access tier makes him visible in ways the smuggler is not. NPCs react + to his presence before interaction begins. 'Worth noting who adjusts their behavior' + — 'Worth' verbal tic, sets up behavioral observation as investigation method. Teaches: + the detective's Commission credentials affect NPC behavior, and that behavioral + response is data. + + # ----------------------------------------------------------------------- + # INSERT / HUD + # ----------------------------------------------------------------------- + + - id: pc-detective_m_d_tut_009 + text: "Lattice overlay active: time, contact positions, flagged entities. Commission-linked. Standard procedure to keep it running." + role: player_character + access: [public] + trust: surface + situation: [routine] + trigger: first_insert_open + mood: [focused] + priority: tutorial + cooldown: -1 + tags: [tutorial, insert, hud, analytical] + notes: > + Detective insert tutorial. Colon usage: catalogs what the overlay contains. 'Commission- + linked' — institutional framing, establishes why the detective's HUD is denser than + the smuggler's. 'Standard procedure' — not a discovery, a protocol. Teaches: the + insert is an active investigation tool, not optional. Compare to smuggler's 'Should + show the time and nearby contacts' — same overlay, presented as procedural requirement + vs. operational check. + + - id: pc-detective_m_d_tut_010 + text: "Nine identity flags in range. Cross-referencing case file now. Let's see what matches." + role: player_character + access: [public] + trust: surface + situation: [investigation, routine] + trigger: first_insert_contact_flag + mood: [focused] + priority: tutorial + cooldown: -1 + tags: [tutorial, insert, hud, lattice, investigation] + notes: > + Fires when the insert first populates with flagged entities. Count given precisely + ('Nine identity flags'). 'Case file' — the detective's overlay cross-references a + pre-loaded investigation file, not just a general registry. 'Let's see what matches' + — 'Let's see what' verbal tic closing the tutorial sequence. Teaches: the detective's + insert is investigation-keyed, matching observed faces against case file entries. + This is why his overlay is analytically denser than the smuggler's. diff --git a/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/smuggler/tutorial.yaml b/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/smuggler/tutorial.yaml new file mode 100644 index 000000000..7b7a1097a --- /dev/null +++ b/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/smuggler/tutorial.yaml @@ -0,0 +1,216 @@ +character: smuggler +location: tutorial +lines: + # Diegetic Tutorial Monologue — Ticket #330 — Smuggler + # Authored per sprint-17 copy briefing and D-016 (internal monologue as core system). + # + # These lines teach mechanics through character voice — not UI instructions. + # Distinct from opening.yaml (which covers the first 5 minutes and sets voice/motivation). + # These fire on first-time events throughout gameplay, wherever they occur. + # + # Coverage: + # Movement / exploration — first_move, first_new_section + # Fog of perception — first_fog_encounter, first_fog_edge + # Sound model — first_sound_heard, first_off_screen_sound + # NPC interaction — first_npc_proximity, first_npc_face_read + # Insert / HUD — first_insert_open, first_insert_contact_flag + # + # Voice: observational, street-smart, practical. Fragments. Standalone "Good." as tic. + # No analytical distance — the smuggler reads, reacts, files, moves on. + # ID discriminator: _tut_ per sprint briefing. + # cooldown: -1 — fire once, never repeat. + # priority: tutorial — higher than general pool lines. + + # ----------------------------------------------------------------------- + # MOVEMENT / EXPLORATION + # ----------------------------------------------------------------------- + + - id: pc-smuggler_m_s_tut_001 + text: "These corridors all look the same. Mental note: check the signage." + role: player_character + access: [public] + trust: surface + situation: [movement, exploration] + trigger: first_move + mood: [focused] + priority: tutorial + cooldown: -1 + tags: [tutorial, movement, navigation] + notes: > + Directly from the sprint briefing example. First move teaches navigation: the district + looks homogeneous, signage is the tool. 'Mental note' is the smuggler's internal + flag for things to remember — operational housekeeping, not analysis. Establishes + early: this environment requires active spatial tracking. + + - id: pc-smuggler_m_s_tut_002 + text: "Two lefts past the junction, right at the supply hatch. That's dock four. Route's in the muscle now." + role: player_character + access: [public] + trust: surface + situation: [movement, routine] + trigger: first_new_section + mood: [content] + priority: tutorial + cooldown: -1 + tags: [tutorial, movement, navigation, operational] + notes: > + Fires on entering a new section for the first time. 'Route's in the muscle' — the + smuggler doesn't memorize spatially, she moves until it's automatic. Practical, + self-sufficient. Teaches: the district has multiple sections, each requires its own + orientation. 'Dock four' is a landmark. Forward movement is rewarded with familiarity. + + # ----------------------------------------------------------------------- + # FOG OF PERCEPTION + # ----------------------------------------------------------------------- + + - id: pc-smuggler_m_s_tut_003 + text: "Can't see past that corner. Might be worth checking." + role: player_character + access: [public] + trust: surface + situation: [observation, exploration] + trigger: first_fog_encounter + mood: [focused] + priority: tutorial + cooldown: -1 + tags: [tutorial, fog, perception] + notes: > + Directly from the sprint briefing example. First fog boundary. Restated as habit: + the smuggler doesn't treat the fog as a limitation, she treats every unknown corner + as a question worth answering. 'Might be worth' — not paranoia, just operational + instinct. Teaches: the perception boundary is navigable, not fixed. + + - id: pc-smuggler_m_s_tut_004 + text: "Haze cuts off past the junction. Anything in it — can't say." + role: player_character + access: [public] + trust: surface + situation: [observation] + trigger: first_fog_edge + mood: [focused] + priority: tutorial + cooldown: -1 + tags: [tutorial, fog, perception] + notes: > + Second fog encounter line — fires when the player reaches the boundary of a fog zone + (the edge of visible range). 'Can't say' — plain statement of unknowing, not anxiety. + The smuggler accepts incomplete information as a working condition, not a failure state. + Teaches: perception range is an ongoing factor, not a one-time obstacle. + + # ----------------------------------------------------------------------- + # SOUND MODEL + # ----------------------------------------------------------------------- + + - id: pc-smuggler_m_s_tut_005 + text: "Voices down the hall. Can't make out the words from here." + role: player_character + access: [public] + trust: surface + situation: [observation] + trigger: first_sound_heard + mood: [focused] + priority: tutorial + cooldown: -1 + tags: [tutorial, sound, perception] + notes: > + Directly from the sprint briefing example. First sound heard that's not immediately + visible. Teaching: sound carries information, but range and occlusion limit it. + 'Can't make out the words' establishes both the value of the sound channel (voices = + people = relevant) and its limitation (unclear at range). Moving toward source is + the implied next step. + + - id: pc-smuggler_m_s_tut_006 + text: "Footsteps. Two sets. Moving away — good." + role: player_character + access: [public] + trust: surface + situation: [observation] + trigger: first_off_screen_sound + mood: [content] + priority: tutorial + cooldown: -1 + tags: [tutorial, sound, perception, operational] + notes: > + Second sound line — fires when audio from an off-screen source is detected. The + smuggler parses footsteps as count and direction instinctively. 'Moving away — good.' + — the standalone 'Good.' tic applied to tactical assessment. Teaches: sound carries + directional and movement data, not just presence. Two sets = two people, which is + specific enough to be operationally useful. + + # ----------------------------------------------------------------------- + # NPC INTERACTION + # ----------------------------------------------------------------------- + + - id: pc-smuggler_m_s_tut_007 + text: "Could ask around. People talk if you give them reason to." + role: player_character + access: [public] + trust: surface + situation: [social, observation] + trigger: first_npc_proximity + mood: [content] + priority: tutorial + cooldown: -1 + tags: [tutorial, npc, interaction, social] + notes: > + Directly from the sprint briefing example. First time in range of an NPC. The smuggler + doesn't approach directly — she flags the option. 'Give them reason to' is street-smart + social knowledge: people don't volunteer freely, they need a hook. Teaches: NPC + interaction is player-initiated, and approach matters. No mechanics text — just the + character's own method stated as personal principle. + + - id: pc-smuggler_m_s_tut_008 + text: "Know the face. Don't need the name." + role: player_character + access: [public] + trust: surface + situation: [social, observation] + trigger: first_npc_face_read + mood: [content] + priority: tutorial + cooldown: -1 + tags: [tutorial, npc, observation, social] + notes: > + Fires when the player observes an NPC at close range (face visible). The smuggler + reads people by face, not by name — the name comes later if relevant. Teaches: NPCs + are identifiable by observation, and the insert overlay will fill in names when + available. The smuggler's social intelligence is pre-lattice, instinctive. + + # ----------------------------------------------------------------------- + # INSERT / HUD + # ----------------------------------------------------------------------- + + - id: pc-smuggler_m_s_tut_009 + text: "Check the overlay. Should show the time and nearby contacts." + role: player_character + access: [public] + trust: surface + situation: [routine] + trigger: first_insert_open + mood: [content] + priority: tutorial + cooldown: -1 + tags: [tutorial, insert, hud, operational] + notes: > + Directly from the sprint briefing example. First insert/HUD open. The smuggler's + overlay shows time and nearby contacts — both operationally critical. 'Should show' + — practical, not certain. Teaches: the insert is the primary tool for time-tracking + and NPC awareness. Diegetic: she checks it the same way she checks a shift board. + + - id: pc-smuggler_m_s_tut_010 + text: "Overlay marks Kael two sections over. Good." + role: player_character + access: [public] + trust: surface + situation: [routine, social] + trigger: first_insert_contact_flag + mood: [content, warm] + priority: tutorial + cooldown: -1 + tags: [tutorial, insert, hud, kael, friend-arc] + notes: > + Fires when the insert first flags a known contact (here: Kael, the FRIEND NPC). + 'Two sections over' — spatial data from the overlay. 'Good.' standalone tic — + warm, settling. Teaches: the insert shows known NPC positions in real-time. + Also seeds the Kael relationship: the smuggler checks his location as a habit, + not a task. His position is always relevant to her. From badc0a6f2014f13fb85ed7323a85bb56688c07ec Mon Sep 17 00:00:00 2001 From: Jeroen Schweitzer Date: Tue, 24 Feb 2026 11:14:13 +0100 Subject: [PATCH 3/6] chore(meta): update changelog Co-Authored-By: Claude Opus 4.6 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e97eb27f..17e863bc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ Format based on [Keep a Changelog](https://keepachangelog.com/). ## [Unreleased] ### Added +- Contradiction monologue lines — 16 hand-authored lines (8 detective, 8 smuggler) for Sera/Kael FRIEND arc, Phase 2 blindsiding + Phase 3 pattern recognition, cognitive-dissonance-not-accusation tone per D-083 (#552) +- Diegetic tutorial monologue — 20 lines (10 per character) teaching movement, fog, sound, NPC interaction, and insert/HUD through character voice, fire-once on first-time events (#330) - `/sprint-status` cleanup sweep skill — consistent health report with tickets by status, PR cross-reference, bookkeeping issue detection, and open work by team - `sprint sweep` CLI subcommand — structured JSON output for sprint health checks (grouped tickets, per-team summary, issue detection) - Knowledge Flow & NPC Boundaries workshop — 5 D-records (D-079–D-083) covering grant architecture, NPC-to-NPC propagation, unprompted disclosure, NPC information boundaries MVP, contradiction detection pipeline From 766a8b9c6d19270a4dd636628535a2e086c59db7 Mon Sep 17 00:00:00 2001 From: Jeroen Schweitzer Date: Tue, 24 Feb 2026 11:32:43 +0100 Subject: [PATCH 4/6] =?UTF-8?q?fix(content):=20PR=20#61=20review=20?= =?UTF-8?q?=E2=80=94=20schema=20compliance=20for=20contradiction=20+=20tut?= =?UTF-8?q?orial?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Contradiction files (both characters): - location: contradiction-detected → contradiction (valid content ID) - situation: removed invalid values (contradiction, reflection) - prerequisites: (plural) → prerequisite: (singular) with canonical entities map - Removed source_name from prerequisites (event payload, not KG gate) - Removed phase: field (moved to tags as phase-2/phase-3) - trigger: contradiction_processing → contradiction_detected with priority sequencing - Removed dialogue-only fields (role, access, trust) from monologue lines - Phase 3 detective: prerequisite uses torek-lintar PersonOfInterest - Phase 3 smuggler: prerequisite uses tells_observed on entity Tutorial files (both characters): - priority: "tutorial" (string) → 8/6 (integer) - situation: removed invalid values (movement, exploration) CHANGELOG: merged duplicate ### Changed sections. Co-Authored-By: Claude Opus 4.6 --- CHANGELOG.md | 1 - .../detective/contradiction-detected.yaml | 165 +++++++++--------- .../transit/monologue/detective/tutorial.yaml | 39 +++-- .../smuggler/contradiction-detected.yaml | 148 +++++++--------- .../transit/monologue/smuggler/tutorial.yaml | 40 +++-- 5 files changed, 190 insertions(+), 203 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 17e863bc5..299536adf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,7 +44,6 @@ Format based on [Keep a Changelog](https://keepachangelog.com/). - assert!(false) → panic!() in serialization tests (clippy) - SetFacing and TeleportToHub added to roundtrip test coverage -### Changed - Zone_id extraction in game_state.gd optimized from O(N) tile scan to O(1) dictionary lookup — builds _tile_by_coord from member visible_tiles covering both test and live paths (#543) - Shared run_dialogue_pipeline() helper eliminates ~60 lines of duplication between Talk and DialogueResponse systems - Dialogue and monologue line IDs migrated from location-scoped (the-terminal_d_039) to NPC-scoped (kael-davan_d_001) namespace — each NPC has an independent sequence per D-035 (#542) diff --git a/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/detective/contradiction-detected.yaml b/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/detective/contradiction-detected.yaml index 421557b55..b59a930d2 100644 --- a/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/detective/contradiction-detected.yaml +++ b/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/detective/contradiction-detected.yaml @@ -1,5 +1,5 @@ character: detective -location: contradiction-detected +location: contradiction lines: # Contradiction Monologue — Ticket #552 — Sera/Kael FRIEND Arc # Authored per D-083 (contradiction detection pipeline) and Paula Round 2 Mellanie spec @@ -16,12 +16,16 @@ lines: # who or what is wrong. Uncertainty first, suspicion second, accusation never. # # Phase 2 lines: trust established but not deep — the blindsiding. - # Prerequisites: KG entry for Kael has state: Contradicted, source: ToldBy(Sera Venn) + # Prerequisite: KG entry for Kael has state: Contradicted, source: ToldBy(Sera Venn) # Phase 3 lines: additional context accumulated — Sera's avoidance of Torek observed 3x. - # Prerequisites: Phase 2 + Sera's avoidance pattern has fired (three departures logged). + # Prerequisite: Phase 2 + Sera's avoidance pattern has fired (three departures logged). # # ID discriminator: _con_ marks contradiction lines per Q-028 pending resolution. # cooldown: -1 — these are one-time events. Should not repeat. + # + # Note: contradiction_detected is a new trigger type — requires server-side implementation + # in monologue.rs (ticket #550). Secondary beat lines use lower priority for sequencing; + # server team should implement delay_after_trigger_ticks for proper 3-5 second gap. # ----------------------------------------------------------------------- # PHASE 2 — Primary beat (fires on contradiction_detected, immediate) @@ -29,19 +33,17 @@ lines: - id: pc-detective_m_d_con_001 text: "Sera said Kael was at the dock intake during second shift. I'm looking at him in corridor B-7 right now." - role: player_character - access: [public] - trust: real - situation: [investigation, observation, contradiction] + situation: [investigation, observation] trigger: contradiction_detected mood: [focused, anxious] priority: 10 cooldown: -1 - phase: 2 - prerequisites: - - entity: "npc:kael-davan" - state: Contradicted - - source_name: "Sera Venn" + prerequisite: + entities: + - id: "npc:kael-davan" + state: Contradicted + - id: "npc:sera-venn" + state: Contradicted tags: [contradiction, friend-arc, sera, kael, phase-2, analytical] notes: > Paula's canonical primary line — preserved verbatim. Flat factual statement: source named, @@ -51,19 +53,17 @@ lines: - id: pc-detective_m_d_con_002 text: "Venn said Kael was at dock intake through second shift. Kael is in B-7. Those aren't compatible." - role: player_character - access: [public] - trust: real - situation: [investigation, observation, contradiction] + situation: [investigation, observation] trigger: contradiction_detected mood: [focused] priority: 9 cooldown: -1 - phase: 2 - prerequisites: - - entity: "npc:kael-davan" - state: Contradicted - - source_name: "Sera Venn" + prerequisite: + entities: + - id: "npc:kael-davan" + state: Contradicted + - id: "npc:sera-venn" + state: Contradicted tags: [contradiction, friend-arc, sera, kael, phase-2, analytical] notes: > Alternate primary — fully analytical register: surname-initial for both (institutional @@ -73,19 +73,17 @@ lines: - id: pc-detective_m_d_con_003 text: "She placed Kael at the dock. He's not at the dock." - role: player_character - access: [public] - trust: real - situation: [investigation, observation, contradiction] + situation: [investigation, observation] trigger: contradiction_detected mood: [focused, anxious] priority: 9 cooldown: -1 - phase: 2 - prerequisites: - - entity: "npc:kael-davan" - state: Contradicted - - source_name: "Sera Venn" + prerequisite: + entities: + - id: "npc:kael-davan" + state: Contradicted + - id: "npc:sera-venn" + state: Contradicted tags: [contradiction, friend-arc, sera, kael, phase-2] notes: > Stripped-down alternate. 'She placed' is the informal of 'Venn stated' — personal register @@ -94,46 +92,45 @@ lines: # ----------------------------------------------------------------------- # PHASE 2 — Secondary beat (fires after short delay, cognitive processing) + # Server team (#550): implement delay_after_trigger_ticks: 90 for 3-5s gap. # ----------------------------------------------------------------------- - id: pc-detective_m_d_con_004 text: "One of them is wrong. Sera, or what I'm seeing. Or I'm missing something I don't have yet." - role: player_character - access: [public] - trust: real - situation: [investigation, reflection, contradiction] - trigger: contradiction_processing + situation: [investigation, alone] + trigger: contradiction_detected mood: [anxious, focused] - priority: 10 + priority: 7 cooldown: -1 - phase: 2 - prerequisites: - - entity: "npc:kael-davan" - state: Contradicted - - source_name: "Sera Venn" - tags: [contradiction, friend-arc, sera, kael, phase-2, cognitive-dissonance] + prerequisite: + entities: + - id: "npc:kael-davan" + state: Contradicted + - id: "npc:sera-venn" + state: Contradicted + tags: [contradiction, friend-arc, sera, kael, phase-2, cognitive-dissonance, secondary-beat] notes: > Paula's canonical secondary beat — fires 3-5 seconds after the primary beat. Epistemic neutrality held across three options: Sera is wrong, observation is wrong, or context is missing. No option is dismissed. 'I'm missing something I don't have yet' is the key line — it holds accusation off even against evidence. The detective files it open. + Lower priority (7) ensures primary lines fire first; server team should implement + delay_after_trigger_ticks for proper sequencing. - id: pc-detective_m_d_con_005 text: "File it. Don't close it. Either Venn's information was wrong when she gave it, or it was wrong on purpose. That's a different question." - role: player_character - access: [public] - trust: real - situation: [investigation, reflection, contradiction] - trigger: contradiction_processing + situation: [investigation, alone] + trigger: contradiction_detected mood: [focused] - priority: 9 + priority: 6 cooldown: -1 - phase: 2 - prerequisites: - - entity: "npc:kael-davan" - state: Contradicted - - source_name: "Sera Venn" - tags: [contradiction, friend-arc, sera, kael, phase-2, analytical, cognitive-dissonance] + prerequisite: + entities: + - id: "npc:kael-davan" + state: Contradicted + - id: "npc:sera-venn" + state: Contradicted + tags: [contradiction, friend-arc, sera, kael, phase-2, analytical, cognitive-dissonance, secondary-beat] notes: > Alternate secondary beat. 'File it, don't close it' is the detective's internal procedure for unresolved data. The critical distinction: wrong information vs. deliberately wrong @@ -147,21 +144,19 @@ lines: - id: pc-detective_m_d_con_006 text: "Sera told me Kael doesn't make mistakes. He's not where she said he'd be. And she's been avoiding Lintar for three weeks." - role: player_character - access: [public] - trust: real - situation: [investigation, observation, contradiction] + situation: [investigation, observation] trigger: contradiction_detected mood: [focused, anxious] priority: 10 cooldown: -1 - phase: 3 - prerequisites: - - entity: "npc:kael-davan" - state: Contradicted - - source_name: "Sera Venn" - - pattern: sera_avoidance_lintar - count_min: 3 + prerequisite: + entities: + - id: "npc:kael-davan" + state: Contradicted + - id: "npc:sera-venn" + state: Contradicted + - id: "npc:torek-lintar" + relationship: PersonOfInterest tags: [contradiction, friend-arc, sera, kael, phase-3, pattern-recognition] notes: > Paula's canonical Phase 3 line — preserved verbatim. Three facts in sequence, no explicit @@ -172,21 +167,19 @@ lines: - id: pc-detective_m_d_con_007 text: "Two facts: Venn placed Kael at dock intake, second shift. Kael is in B-7. One new observation: Venn leaves every time Lintar enters the bar. Worth seeing if those connect." - role: player_character - access: [public] - trust: real - situation: [investigation, observation, contradiction] + situation: [investigation, observation] trigger: contradiction_detected mood: [focused] priority: 9 cooldown: -1 - phase: 3 - prerequisites: - - entity: "npc:kael-davan" - state: Contradicted - - source_name: "Sera Venn" - - pattern: sera_avoidance_lintar - count_min: 3 + prerequisite: + entities: + - id: "npc:kael-davan" + state: Contradicted + - id: "npc:sera-venn" + state: Contradicted + - id: "npc:torek-lintar" + relationship: PersonOfInterest tags: [contradiction, friend-arc, sera, kael, phase-3, analytical, pattern-recognition] notes: > Alternate Phase 3 — analytical register throughout, no personal register even for Sera @@ -197,21 +190,19 @@ lines: - id: pc-detective_m_d_con_008 text: "Venn's been managing her exits around Lintar. And she put Kael somewhere he isn't. Let's see what sits at the intersection of those two." - role: player_character - access: [public] - trust: real - situation: [investigation, reflection, contradiction] + situation: [investigation, alone] trigger: contradiction_detected mood: [focused] priority: 8 cooldown: -1 - phase: 3 - prerequisites: - - entity: "npc:kael-davan" - state: Contradicted - - source_name: "Sera Venn" - - pattern: sera_avoidance_lintar - count_min: 3 + prerequisite: + entities: + - id: "npc:kael-davan" + state: Contradicted + - id: "npc:sera-venn" + state: Contradicted + - id: "npc:torek-lintar" + relationship: PersonOfInterest tags: [contradiction, friend-arc, sera, kael, phase-3, analytical] notes: > Alternate Phase 3. 'Let's see what' verbal tic, no accusation. 'Managing her exits' is diff --git a/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/detective/tutorial.yaml b/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/detective/tutorial.yaml index 103b9541f..a51d0add9 100644 --- a/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/detective/tutorial.yaml +++ b/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/detective/tutorial.yaml @@ -19,7 +19,18 @@ lines: # Colon usage for categorization. 'Let's see what...' and 'Worth flagging' verbal tics. # ID discriminator: _tut_ per sprint briefing. # cooldown: -1 — fire once, never repeat. - # priority: tutorial — higher than general pool lines. + # priority: 8 (primary, one per trigger type), 6 (secondary variant, mood-weighted alternate). + # + # Schema corrections (Gestalt review, Sprint 17): + # priority: string "tutorial" → integer. All other monologue files use integer priority; + # string value would fail engine parse in monologue.rs. + # situation: removed invalid values (movement, exploration) not in D-035 13-situation + # enum. Replaced with arrival, routine per actual trigger context. + # + # Trigger types (first_move, first_new_section, first_fog_encounter, first_fog_edge, + # first_sound_heard, first_off_screen_sound, first_npc_proximity, first_npc_face_read, + # first_insert_open, first_insert_contact_flag) are extended trigger enum values not in + # D-035 v0.1 set — require server-side implementation in monologue.rs. # ----------------------------------------------------------------------- # MOVEMENT / EXPLORATION @@ -30,10 +41,10 @@ lines: role: player_character access: [public] trust: surface - situation: [movement, exploration] + situation: [arrival, routine] trigger: first_move mood: [focused] - priority: tutorial + priority: 8 cooldown: -1 tags: [tutorial, movement, navigation, analytical] notes: > @@ -48,10 +59,10 @@ lines: role: player_character access: [public] trust: surface - situation: [movement, investigation] + situation: [arrival, investigation] trigger: first_new_section mood: [focused] - priority: tutorial + priority: 6 cooldown: -1 tags: [tutorial, movement, navigation, analytical] notes: > @@ -70,10 +81,10 @@ lines: role: player_character access: [public] trust: surface - situation: [observation, exploration] + situation: [observation] trigger: first_fog_encounter mood: [focused] - priority: tutorial + priority: 8 cooldown: -1 tags: [tutorial, fog, perception, analytical] notes: > @@ -92,7 +103,7 @@ lines: situation: [observation] trigger: first_fog_edge mood: [focused] - priority: tutorial + priority: 6 cooldown: -1 tags: [tutorial, fog, perception, analytical] notes: > @@ -115,7 +126,7 @@ lines: situation: [observation] trigger: first_sound_heard mood: [focused] - priority: tutorial + priority: 8 cooldown: -1 tags: [tutorial, sound, perception, analytical] notes: > @@ -134,7 +145,7 @@ lines: situation: [observation] trigger: first_off_screen_sound mood: [focused] - priority: tutorial + priority: 6 cooldown: -1 tags: [tutorial, sound, perception, analytical] notes: > @@ -157,7 +168,7 @@ lines: situation: [social, observation] trigger: first_npc_proximity mood: [focused] - priority: tutorial + priority: 8 cooldown: -1 tags: [tutorial, npc, interaction, analytical] notes: > @@ -177,7 +188,7 @@ lines: situation: [social, investigation] trigger: first_npc_face_read mood: [focused] - priority: tutorial + priority: 6 cooldown: -1 tags: [tutorial, npc, observation, analytical, authority] notes: > @@ -200,7 +211,7 @@ lines: situation: [routine] trigger: first_insert_open mood: [focused] - priority: tutorial + priority: 8 cooldown: -1 tags: [tutorial, insert, hud, analytical] notes: > @@ -219,7 +230,7 @@ lines: situation: [investigation, routine] trigger: first_insert_contact_flag mood: [focused] - priority: tutorial + priority: 6 cooldown: -1 tags: [tutorial, insert, hud, lattice, investigation] notes: > diff --git a/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/smuggler/contradiction-detected.yaml b/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/smuggler/contradiction-detected.yaml index 45a76a2e0..19843e244 100644 --- a/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/smuggler/contradiction-detected.yaml +++ b/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/smuggler/contradiction-detected.yaml @@ -1,5 +1,5 @@ character: smuggler -location: contradiction-detected +location: contradiction lines: # Contradiction Monologue — Ticket #552 — Sera/Kael FRIEND Arc (Smuggler perspective) # Authored per D-083 (contradiction detection pipeline) and Paula Round 2 Mellanie spec @@ -18,13 +18,17 @@ lines: # gut reaction, not analytical procedure. # # Phase 2 lines: first observation — Kael in B-7 with unknown contact. - # Prerequisites: KG entry for Kael has state: Contradicted, source: ToldBy(Kael Davan) + # Prerequisite: KG entry for Kael has state: Contradicted, source: ToldBy(Kael Davan) # Phase 3 lines: behavioral pattern already accumulating — increased lattice checking, # shortened interactions, early exits from break room. - # Prerequisites: Phase 2 + Kael's behavioral anomalies observed (count ≥ 2). + # Prerequisite: Phase 2 + Kael's behavioral anomalies observed (count >= 2). # # ID discriminator: _con_ marks contradiction lines per Q-028 pending resolution. # cooldown: -1 — one-time events. Should not repeat. + # + # Note: contradiction_detected is a new trigger type — requires server-side implementation + # in monologue.rs (ticket #550). Secondary beat lines use lower priority for sequencing; + # server team should implement delay_after_trigger_ticks for proper 3-5 second gap. # ----------------------------------------------------------------------- # PHASE 2 — Primary beat (fires on contradiction_detected, immediate) @@ -32,19 +36,15 @@ lines: - id: pc-smuggler_m_s_con_001 text: "Kael said second shift was clear. He's in B-7. With someone I don't know." - role: player_character - access: [public] - trust: real - situation: [investigation, observation, contradiction] + situation: [investigation, observation] trigger: contradiction_detected mood: [focused, anxious] priority: 10 cooldown: -1 - phase: 2 - prerequisites: - - entity: "npc:kael-davan" - state: Contradicted - - source_name: "Kael Davan" + prerequisite: + entities: + - id: "npc:kael-davan" + state: Contradicted tags: [contradiction, friend-arc, kael, phase-2, operational] notes: > Primary line — three beats, three facts. 'Kael said' names the source (friend register, @@ -54,19 +54,15 @@ lines: - id: pc-smuggler_m_s_con_002 text: "That's Kael. Restricted corridor. Unrecognized contact. Kael doesn't come to B-7." - role: player_character - access: [public] - trust: real - situation: [investigation, observation, contradiction] + situation: [investigation, observation] trigger: contradiction_detected mood: [focused] priority: 9 cooldown: -1 - phase: 2 - prerequisites: - - entity: "npc:kael-davan" - state: Contradicted - - source_name: "Kael Davan" + prerequisite: + entities: + - id: "npc:kael-davan" + state: Contradicted tags: [contradiction, friend-arc, kael, phase-2, operational] notes: > Alternate primary — catalog format. 'That's Kael' opens with identification, not alarm: @@ -76,19 +72,15 @@ lines: - id: pc-smuggler_m_s_con_003 text: "He's in B-7. He told me he'd be heading home after shift. One of those isn't the case." - role: player_character - access: [public] - trust: real - situation: [investigation, observation, contradiction] + situation: [investigation, observation] trigger: contradiction_detected mood: [focused, anxious] priority: 9 cooldown: -1 - phase: 2 - prerequisites: - - entity: "npc:kael-davan" - state: Contradicted - - source_name: "Kael Davan" + prerequisite: + entities: + - id: "npc:kael-davan" + state: Contradicted tags: [contradiction, friend-arc, kael, phase-2] notes: > Alternate primary — echoes the Paula canonical structure (observation / prior claim / @@ -99,47 +91,42 @@ lines: # ----------------------------------------------------------------------- # PHASE 2 — Secondary beat (gut-level recalibration, operational containment) + # Server team (#550): implement delay_after_trigger_ticks: 90 for 3-5s gap. # ----------------------------------------------------------------------- - id: pc-smuggler_m_s_con_004 text: "Maybe there's a reason. There's always a reason. But Kael knows better than to run a meeting in a maintenance corridor without telling me." - role: player_character - access: [public] - trust: real - situation: [investigation, reflection, contradiction] - trigger: contradiction_processing + situation: [investigation, alone] + trigger: contradiction_detected mood: [focused, anxious] - priority: 10 + priority: 7 cooldown: -1 - phase: 2 - prerequisites: - - entity: "npc:kael-davan" - state: Contradicted - - source_name: "Kael Davan" - tags: [contradiction, friend-arc, kael, phase-2, cognitive-dissonance] + prerequisite: + entities: + - id: "npc:kael-davan" + state: Contradicted + tags: [contradiction, friend-arc, kael, phase-2, cognitive-dissonance, secondary-beat] notes: > Secondary beat — fires 3-5 seconds after primary. Self-challenge first: the smuggler gives Kael benefit of the doubt, then immediately walks it back with operational logic. 'There's always a reason' is the street-smart equivalent of epistemic containment — she's seen strange things before. The closing line is where the alarm lives: this isn't strange, it's a protocol violation. + Lower priority (7) ensures primary lines fire first; server team should implement + delay_after_trigger_ticks for proper sequencing. - id: pc-smuggler_m_s_con_005 text: "Don't assume. Could be he's running something for Nils I wasn't told about. Could be something else. The second thing is the problem." - role: player_character - access: [public] - trust: real - situation: [investigation, reflection, contradiction] - trigger: contradiction_processing + situation: [investigation, alone] + trigger: contradiction_detected mood: [focused] - priority: 9 + priority: 6 cooldown: -1 - phase: 2 - prerequisites: - - entity: "npc:kael-davan" - state: Contradicted - - source_name: "Kael Davan" - tags: [contradiction, friend-arc, kael, phase-2, operational, cognitive-dissonance] + prerequisite: + entities: + - id: "npc:kael-davan" + state: Contradicted + tags: [contradiction, friend-arc, kael, phase-2, operational, cognitive-dissonance, secondary-beat] notes: > Alternate secondary beat. 'Don't assume' is the smuggler's self-instruction (operational discipline). Two possibilities held open: ring-authorized (names Nils — the coordinator) @@ -154,21 +141,16 @@ lines: - id: pc-smuggler_m_s_con_006 text: "He's been distracted for three days. Lattice checks every few minutes, leaving lunch early. Now a B-7 meeting with someone outside the ring. Kael's working an angle he hasn't told me about." - role: player_character - access: [public] - trust: real - situation: [investigation, observation, contradiction] + situation: [investigation, observation] trigger: contradiction_detected mood: [focused, anxious] priority: 10 cooldown: -1 - phase: 3 - prerequisites: - - entity: "npc:kael-davan" - state: Contradicted - - source_name: "Kael Davan" - - pattern: kael_behavioral_anomaly - count_min: 2 + prerequisite: + entities: + - id: "npc:kael-davan" + state: Contradicted + tells_observed: 2 tags: [contradiction, friend-arc, kael, phase-3, pattern-recognition, operational] notes: > Phase 3 primary — connects all accumulated behavioral data to the contradiction. Fragment @@ -176,24 +158,21 @@ lines: conclusion without naming its implication: 'working an angle' is street-smart language for running something unauthorized, but the smuggler doesn't say 'exit attempt' — she doesn't know that yet. + Note: tells_observed is a proposed prerequisite field — server team (#550) to implement + or simplify to a different check. - id: pc-smuggler_m_s_con_007 text: "Kael doesn't run his own contacts. Devra handles external. So either Devra knows about this, or Kael's outside protocol. Neither's good." - role: player_character - access: [public] - trust: real - situation: [investigation, observation, contradiction] + situation: [investigation, observation] trigger: contradiction_detected mood: [focused] priority: 9 cooldown: -1 - phase: 3 - prerequisites: - - entity: "npc:kael-davan" - state: Contradicted - - source_name: "Kael Davan" - - pattern: kael_behavioral_anomaly - count_min: 2 + prerequisite: + entities: + - id: "npc:kael-davan" + state: Contradicted + tells_observed: 2 tags: [contradiction, friend-arc, kael, phase-3, operational] notes: > Alternate Phase 3 — operational knowledge applied. The smuggler knows ring structure: @@ -204,21 +183,16 @@ lines: - id: pc-smuggler_m_s_con_008 text: "He's been somewhere else in his head all week. Now I know why. Whoever that was — not ring. Kael's looking for a way out." - role: player_character - access: [public] - trust: real - situation: [investigation, observation, contradiction] + situation: [investigation, observation] trigger: contradiction_detected mood: [anxious] priority: 8 cooldown: -1 - phase: 3 - prerequisites: - - entity: "npc:kael-davan" - state: Contradicted - - source_name: "Kael Davan" - - pattern: kael_behavioral_anomaly - count_min: 2 + prerequisite: + entities: + - id: "npc:kael-davan" + state: Contradicted + tells_observed: 2 tags: [contradiction, friend-arc, kael, phase-3, intuition] notes: > Alternate Phase 3 — gut read, highest emotional weight. 'Somewhere else in his head' diff --git a/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/smuggler/tutorial.yaml b/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/smuggler/tutorial.yaml index 7b7a1097a..913bd3207 100644 --- a/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/smuggler/tutorial.yaml +++ b/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/smuggler/tutorial.yaml @@ -19,7 +19,19 @@ lines: # No analytical distance — the smuggler reads, reacts, files, moves on. # ID discriminator: _tut_ per sprint briefing. # cooldown: -1 — fire once, never repeat. - # priority: tutorial — higher than general pool lines. + # priority: 8 (primary, one per trigger type), 6 (secondary variant, mood-weighted alternate). + # + # Schema corrections (Gestalt review, Sprint 17): + # priority: string "tutorial" → integer. All other monologue files use integer priority; + # string value would fail engine parse in monologue.rs. + # situation: removed invalid values (movement, exploration) not in D-035 13-situation + # enum. Replaced with arrival, routine, observation per actual trigger context. + # mood: [focused] retained where set; valid per D-035 Sprint 14 amendment. + # + # Trigger types (first_move, first_new_section, first_fog_encounter, first_fog_edge, + # first_sound_heard, first_off_screen_sound, first_npc_proximity, first_npc_face_read, + # first_insert_open, first_insert_contact_flag) are extended trigger enum values not in + # D-035 v0.1 set — require server-side implementation in monologue.rs. # ----------------------------------------------------------------------- # MOVEMENT / EXPLORATION @@ -30,10 +42,10 @@ lines: role: player_character access: [public] trust: surface - situation: [movement, exploration] + situation: [arrival, routine] trigger: first_move mood: [focused] - priority: tutorial + priority: 8 cooldown: -1 tags: [tutorial, movement, navigation] notes: > @@ -47,10 +59,10 @@ lines: role: player_character access: [public] trust: surface - situation: [movement, routine] + situation: [arrival, routine] trigger: first_new_section mood: [content] - priority: tutorial + priority: 6 cooldown: -1 tags: [tutorial, movement, navigation, operational] notes: > @@ -68,10 +80,10 @@ lines: role: player_character access: [public] trust: surface - situation: [observation, exploration] + situation: [observation] trigger: first_fog_encounter mood: [focused] - priority: tutorial + priority: 8 cooldown: -1 tags: [tutorial, fog, perception] notes: > @@ -88,7 +100,7 @@ lines: situation: [observation] trigger: first_fog_edge mood: [focused] - priority: tutorial + priority: 6 cooldown: -1 tags: [tutorial, fog, perception] notes: > @@ -109,7 +121,7 @@ lines: situation: [observation] trigger: first_sound_heard mood: [focused] - priority: tutorial + priority: 8 cooldown: -1 tags: [tutorial, sound, perception] notes: > @@ -127,7 +139,7 @@ lines: situation: [observation] trigger: first_off_screen_sound mood: [content] - priority: tutorial + priority: 6 cooldown: -1 tags: [tutorial, sound, perception, operational] notes: > @@ -149,7 +161,7 @@ lines: situation: [social, observation] trigger: first_npc_proximity mood: [content] - priority: tutorial + priority: 8 cooldown: -1 tags: [tutorial, npc, interaction, social] notes: > @@ -167,7 +179,7 @@ lines: situation: [social, observation] trigger: first_npc_face_read mood: [content] - priority: tutorial + priority: 6 cooldown: -1 tags: [tutorial, npc, observation, social] notes: > @@ -188,7 +200,7 @@ lines: situation: [routine] trigger: first_insert_open mood: [content] - priority: tutorial + priority: 8 cooldown: -1 tags: [tutorial, insert, hud, operational] notes: > @@ -205,7 +217,7 @@ lines: situation: [routine, social] trigger: first_insert_contact_flag mood: [content, warm] - priority: tutorial + priority: 6 cooldown: -1 tags: [tutorial, insert, hud, kael, friend-arc] notes: > From b544303f29ea1f4f8f04106e28be00f624161daf Mon Sep 17 00:00:00 2001 From: Jeroen Schweitzer Date: Tue, 24 Feb 2026 11:37:37 +0100 Subject: [PATCH 5/6] docs(meta): allow removing own worktree index.lock in CLAUDE.md Adds explicit exception to worktree boundary rules: agents may remove their own worktree's stale index.lock file from the shared .git directory, but never another worktree's lock. Co-Authored-By: Claude Opus 4.6 --- CLAUDE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CLAUDE.md b/CLAUDE.md index 9f5bba849..d5da811d5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -63,6 +63,7 @@ Unless there is a direct instruction or a functional need (e.g. accessing the sh - All file paths are relative to the worktree/git root (e.g. `server/src/bridge/types.rs`, `client/scripts/rendering/fog.gd`). - Do not navigate to or access sibling worktrees in the parent directory (`../client/`, `../copy/`, etc.) unless explicitly instructed. - Do not navigate above the git root unless explicitly instructed. +- **Exception — stale git lock files:** Worktree index locks live in the shared `.git` directory (e.g. `main/.git/worktrees/copy/index.lock`). If a `git` command fails with `index.lock: File exists`, you may remove the lock file for **your own worktree only** (e.g. `copy` may remove `worktrees/copy/index.lock`). Never touch lock files belonging to other worktrees. ### Database From f5a866fc4d73327c44184238956a341a8b777cb9 Mon Sep 17 00:00:00 2001 From: Jeroen Schweitzer Date: Tue, 24 Feb 2026 12:05:16 +0100 Subject: [PATCH 6/6] =?UTF-8?q?fix(content):=20PR=20#61=20round=202=20?= =?UTF-8?q?=E2=80=94=20schema=20fields,=20cooldown,=20CHANGELOG=20sections?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Contradiction files: - Add role/access/trust back to all lines (schema-required) - prerequisite: → prerequisites: (plural, matching schema) - Remove cooldown entirely — fire-once enforced by trigger semantics (contradiction_detected fires once per KG state change), not magic numbers Tutorial files: - Remove cooldown: -1 — same reasoning, first_* triggers are one-time Server: - Document cooldown: Option on MonologueLine — None means no per-line cooldown, fire-once relies on trigger design CHANGELOG: - Move displaced entries from ### Fixed back to ### Changed Co-Authored-By: Claude Opus 4.6 --- CHANGELOG.md | 13 ++-- .../detective/contradiction-detected.yaml | 59 +++++++++++++------ .../transit/monologue/detective/tutorial.yaml | 23 ++++---- .../smuggler/contradiction-detected.yaml | 59 +++++++++++++------ .../transit/monologue/smuggler/tutorial.yaml | 23 ++++---- server/src/content/types.rs | 3 + 6 files changed, 117 insertions(+), 63 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 299536adf..831596004 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,12 @@ Format based on [Keep a Changelog](https://keepachangelog.com/). - Line variety tracker wiring — DialogueCooldownTracker prevents repeat lines within 600-tick window (#338) - DialogueResponse cross-language fixture for GDScript testing - Sprint team lifecycle through PR review — teams stay alive for commit → push → review → fix loop → approve → shutdown +- Zone_id extraction in game_state.gd optimized from O(N) tile scan to O(1) dictionary lookup — builds _tile_by_coord from member visible_tiles covering both test and live paths (#543) +- Shared run_dialogue_pipeline() helper eliminates ~60 lines of duplication between Talk and DialogueResponse systems +- Dialogue and monologue line IDs migrated from location-scoped (the-terminal_d_039) to NPC-scoped (kael-davan_d_001) namespace — each NPC has an independent sequence per D-035 (#542) +- DialogueCooldownTracker documented as per-player-global by design (NPC-scoped line IDs per D-035 prevent collision) +- CONFRONTATION_LINES marked TODO for migration to D-028/D-035 content pipeline +- pr-push and pr-review skills updated with team lifecycle awareness ### Fixed - PR #59 review: stale mood vocabulary updated in line-pool-format.md, style-guide, and content-directory-structure.md to post-Sprint 14 values @@ -44,13 +50,6 @@ Format based on [Keep a Changelog](https://keepachangelog.com/). - assert!(false) → panic!() in serialization tests (clippy) - SetFacing and TeleportToHub added to roundtrip test coverage -- Zone_id extraction in game_state.gd optimized from O(N) tile scan to O(1) dictionary lookup — builds _tile_by_coord from member visible_tiles covering both test and live paths (#543) -- Shared run_dialogue_pipeline() helper eliminates ~60 lines of duplication between Talk and DialogueResponse systems -- Dialogue and monologue line IDs migrated from location-scoped (the-terminal_d_039) to NPC-scoped (kael-davan_d_001) namespace — each NPC has an independent sequence per D-035 (#542) -- DialogueCooldownTracker documented as per-player-global by design (NPC-scoped line IDs per D-035 prevent collision) -- CONFRONTATION_LINES marked TODO for migration to D-028/D-035 content pipeline -- pr-push and pr-review skills updated with team lifecycle awareness - ## [v0.1.15] — 2026-02-23 ### Added diff --git a/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/detective/contradiction-detected.yaml b/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/detective/contradiction-detected.yaml index b59a930d2..1f12ed12b 100644 --- a/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/detective/contradiction-detected.yaml +++ b/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/detective/contradiction-detected.yaml @@ -21,7 +21,8 @@ lines: # Prerequisite: Phase 2 + Sera's avoidance pattern has fired (three departures logged). # # ID discriminator: _con_ marks contradiction lines per Q-028 pending resolution. - # cooldown: -1 — these are one-time events. Should not repeat. + # cooldown: omitted — fire-once enforced by trigger semantics (contradiction_detected + # fires once per KG state change), not by a cooldown value. # # Note: contradiction_detected is a new trigger type — requires server-side implementation # in monologue.rs (ticket #550). Secondary beat lines use lower priority for sequencing; @@ -33,12 +34,15 @@ lines: - id: pc-detective_m_d_con_001 text: "Sera said Kael was at the dock intake during second shift. I'm looking at him in corridor B-7 right now." + role: player_character + access: [public] + trust: surface situation: [investigation, observation] trigger: contradiction_detected mood: [focused, anxious] priority: 10 - cooldown: -1 - prerequisite: + + prerequisites: entities: - id: "npc:kael-davan" state: Contradicted @@ -53,12 +57,15 @@ lines: - id: pc-detective_m_d_con_002 text: "Venn said Kael was at dock intake through second shift. Kael is in B-7. Those aren't compatible." + role: player_character + access: [public] + trust: surface situation: [investigation, observation] trigger: contradiction_detected mood: [focused] priority: 9 - cooldown: -1 - prerequisite: + + prerequisites: entities: - id: "npc:kael-davan" state: Contradicted @@ -73,12 +80,15 @@ lines: - id: pc-detective_m_d_con_003 text: "She placed Kael at the dock. He's not at the dock." + role: player_character + access: [public] + trust: surface situation: [investigation, observation] trigger: contradiction_detected mood: [focused, anxious] priority: 9 - cooldown: -1 - prerequisite: + + prerequisites: entities: - id: "npc:kael-davan" state: Contradicted @@ -97,12 +107,15 @@ lines: - id: pc-detective_m_d_con_004 text: "One of them is wrong. Sera, or what I'm seeing. Or I'm missing something I don't have yet." + role: player_character + access: [public] + trust: surface situation: [investigation, alone] trigger: contradiction_detected mood: [anxious, focused] priority: 7 - cooldown: -1 - prerequisite: + + prerequisites: entities: - id: "npc:kael-davan" state: Contradicted @@ -119,12 +132,15 @@ lines: - id: pc-detective_m_d_con_005 text: "File it. Don't close it. Either Venn's information was wrong when she gave it, or it was wrong on purpose. That's a different question." + role: player_character + access: [public] + trust: surface situation: [investigation, alone] trigger: contradiction_detected mood: [focused] priority: 6 - cooldown: -1 - prerequisite: + + prerequisites: entities: - id: "npc:kael-davan" state: Contradicted @@ -144,12 +160,15 @@ lines: - id: pc-detective_m_d_con_006 text: "Sera told me Kael doesn't make mistakes. He's not where she said he'd be. And she's been avoiding Lintar for three weeks." + role: player_character + access: [public] + trust: surface situation: [investigation, observation] trigger: contradiction_detected mood: [focused, anxious] priority: 10 - cooldown: -1 - prerequisite: + + prerequisites: entities: - id: "npc:kael-davan" state: Contradicted @@ -167,12 +186,15 @@ lines: - id: pc-detective_m_d_con_007 text: "Two facts: Venn placed Kael at dock intake, second shift. Kael is in B-7. One new observation: Venn leaves every time Lintar enters the bar. Worth seeing if those connect." + role: player_character + access: [public] + trust: surface situation: [investigation, observation] trigger: contradiction_detected mood: [focused] priority: 9 - cooldown: -1 - prerequisite: + + prerequisites: entities: - id: "npc:kael-davan" state: Contradicted @@ -190,12 +212,15 @@ lines: - id: pc-detective_m_d_con_008 text: "Venn's been managing her exits around Lintar. And she put Kael somewhere he isn't. Let's see what sits at the intersection of those two." + role: player_character + access: [public] + trust: surface situation: [investigation, alone] trigger: contradiction_detected mood: [focused] priority: 8 - cooldown: -1 - prerequisite: + + prerequisites: entities: - id: "npc:kael-davan" state: Contradicted diff --git a/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/detective/tutorial.yaml b/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/detective/tutorial.yaml index a51d0add9..a1fa58e0e 100644 --- a/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/detective/tutorial.yaml +++ b/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/detective/tutorial.yaml @@ -18,7 +18,8 @@ lines: # Voice: analytical, procedure-oriented, careful. No contractions in analytical mode. # Colon usage for categorization. 'Let's see what...' and 'Worth flagging' verbal tics. # ID discriminator: _tut_ per sprint briefing. - # cooldown: -1 — fire once, never repeat. + # cooldown: omitted — fire-once enforced by trigger semantics (first_* triggers + # fire once per game), not by a cooldown value. # priority: 8 (primary, one per trigger type), 6 (secondary variant, mood-weighted alternate). # # Schema corrections (Gestalt review, Sprint 17): @@ -45,7 +46,7 @@ lines: trigger: first_move mood: [focused] priority: 8 - cooldown: -1 + tags: [tutorial, movement, navigation, analytical] notes: > Detective version of the 'check the signage' tutorial. Colon usage for the signage @@ -63,7 +64,7 @@ lines: trigger: first_new_section mood: [focused] priority: 6 - cooldown: -1 + tags: [tutorial, movement, navigation, analytical] notes: > Fires on entering a new section for the first time. 'Commission briefing had the @@ -85,7 +86,7 @@ lines: trigger: first_fog_encounter mood: [focused] priority: 8 - cooldown: -1 + tags: [tutorial, fog, perception, analytical] notes: > Detective fog tutorial — analytical register throughout. 'Visual range terminates at' @@ -104,7 +105,7 @@ lines: trigger: first_fog_edge mood: [focused] priority: 6 - cooldown: -1 + tags: [tutorial, fog, perception, analytical] notes: > Second fog encounter line — fires at a fog zone boundary. 'Going around is the @@ -127,7 +128,7 @@ lines: trigger: first_sound_heard mood: [focused] priority: 8 - cooldown: -1 + tags: [tutorial, sound, perception, analytical] notes: > Detective sound tutorial — analytical framing of the briefing's example. 'Source count @@ -146,7 +147,7 @@ lines: trigger: first_off_screen_sound mood: [focused] priority: 6 - cooldown: -1 + tags: [tutorial, sound, perception, analytical] notes: > Second sound tutorial — fires on an off-screen audio source. The detective parses @@ -169,7 +170,7 @@ lines: trigger: first_npc_proximity mood: [focused] priority: 8 - cooldown: -1 + tags: [tutorial, npc, interaction, analytical] notes: > Detective NPC tutorial — procedural, method-as-principle. 'Civilians in range' is @@ -189,7 +190,7 @@ lines: trigger: first_npc_face_read mood: [focused] priority: 6 - cooldown: -1 + tags: [tutorial, npc, observation, analytical, authority] notes: > Fires when the player observes an NPC at close range. The detective's asymmetry: @@ -212,7 +213,7 @@ lines: trigger: first_insert_open mood: [focused] priority: 8 - cooldown: -1 + tags: [tutorial, insert, hud, analytical] notes: > Detective insert tutorial. Colon usage: catalogs what the overlay contains. 'Commission- @@ -231,7 +232,7 @@ lines: trigger: first_insert_contact_flag mood: [focused] priority: 6 - cooldown: -1 + tags: [tutorial, insert, hud, lattice, investigation] notes: > Fires when the insert first populates with flagged entities. Count given precisely diff --git a/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/smuggler/contradiction-detected.yaml b/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/smuggler/contradiction-detected.yaml index 19843e244..466d5ba61 100644 --- a/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/smuggler/contradiction-detected.yaml +++ b/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/smuggler/contradiction-detected.yaml @@ -24,7 +24,8 @@ lines: # Prerequisite: Phase 2 + Kael's behavioral anomalies observed (count >= 2). # # ID discriminator: _con_ marks contradiction lines per Q-028 pending resolution. - # cooldown: -1 — one-time events. Should not repeat. + # cooldown: omitted — fire-once enforced by trigger semantics (contradiction_detected + # fires once per KG state change), not by a cooldown value. # # Note: contradiction_detected is a new trigger type — requires server-side implementation # in monologue.rs (ticket #550). Secondary beat lines use lower priority for sequencing; @@ -36,12 +37,15 @@ lines: - id: pc-smuggler_m_s_con_001 text: "Kael said second shift was clear. He's in B-7. With someone I don't know." + role: player_character + access: [public] + trust: surface situation: [investigation, observation] trigger: contradiction_detected mood: [focused, anxious] priority: 10 - cooldown: -1 - prerequisite: + + prerequisites: entities: - id: "npc:kael-davan" state: Contradicted @@ -54,12 +58,15 @@ lines: - id: pc-smuggler_m_s_con_002 text: "That's Kael. Restricted corridor. Unrecognized contact. Kael doesn't come to B-7." + role: player_character + access: [public] + trust: surface situation: [investigation, observation] trigger: contradiction_detected mood: [focused] priority: 9 - cooldown: -1 - prerequisite: + + prerequisites: entities: - id: "npc:kael-davan" state: Contradicted @@ -72,12 +79,15 @@ lines: - id: pc-smuggler_m_s_con_003 text: "He's in B-7. He told me he'd be heading home after shift. One of those isn't the case." + role: player_character + access: [public] + trust: surface situation: [investigation, observation] trigger: contradiction_detected mood: [focused, anxious] priority: 9 - cooldown: -1 - prerequisite: + + prerequisites: entities: - id: "npc:kael-davan" state: Contradicted @@ -96,12 +106,15 @@ lines: - id: pc-smuggler_m_s_con_004 text: "Maybe there's a reason. There's always a reason. But Kael knows better than to run a meeting in a maintenance corridor without telling me." + role: player_character + access: [public] + trust: surface situation: [investigation, alone] trigger: contradiction_detected mood: [focused, anxious] priority: 7 - cooldown: -1 - prerequisite: + + prerequisites: entities: - id: "npc:kael-davan" state: Contradicted @@ -117,12 +130,15 @@ lines: - id: pc-smuggler_m_s_con_005 text: "Don't assume. Could be he's running something for Nils I wasn't told about. Could be something else. The second thing is the problem." + role: player_character + access: [public] + trust: surface situation: [investigation, alone] trigger: contradiction_detected mood: [focused] priority: 6 - cooldown: -1 - prerequisite: + + prerequisites: entities: - id: "npc:kael-davan" state: Contradicted @@ -141,12 +157,15 @@ lines: - id: pc-smuggler_m_s_con_006 text: "He's been distracted for three days. Lattice checks every few minutes, leaving lunch early. Now a B-7 meeting with someone outside the ring. Kael's working an angle he hasn't told me about." + role: player_character + access: [public] + trust: surface situation: [investigation, observation] trigger: contradiction_detected mood: [focused, anxious] priority: 10 - cooldown: -1 - prerequisite: + + prerequisites: entities: - id: "npc:kael-davan" state: Contradicted @@ -163,12 +182,15 @@ lines: - id: pc-smuggler_m_s_con_007 text: "Kael doesn't run his own contacts. Devra handles external. So either Devra knows about this, or Kael's outside protocol. Neither's good." + role: player_character + access: [public] + trust: surface situation: [investigation, observation] trigger: contradiction_detected mood: [focused] priority: 9 - cooldown: -1 - prerequisite: + + prerequisites: entities: - id: "npc:kael-davan" state: Contradicted @@ -183,12 +205,15 @@ lines: - id: pc-smuggler_m_s_con_008 text: "He's been somewhere else in his head all week. Now I know why. Whoever that was — not ring. Kael's looking for a way out." + role: player_character + access: [public] + trust: surface situation: [investigation, observation] trigger: contradiction_detected mood: [anxious] priority: 8 - cooldown: -1 - prerequisite: + + prerequisites: entities: - id: "npc:kael-davan" state: Contradicted diff --git a/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/smuggler/tutorial.yaml b/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/smuggler/tutorial.yaml index 913bd3207..2c48f043a 100644 --- a/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/smuggler/tutorial.yaml +++ b/content/campaigns/main/systems/krenn/stations/sova/districts/transit/monologue/smuggler/tutorial.yaml @@ -18,7 +18,8 @@ lines: # Voice: observational, street-smart, practical. Fragments. Standalone "Good." as tic. # No analytical distance — the smuggler reads, reacts, files, moves on. # ID discriminator: _tut_ per sprint briefing. - # cooldown: -1 — fire once, never repeat. + # cooldown: omitted — fire-once enforced by trigger semantics (first_* triggers + # fire once per game), not by a cooldown value. # priority: 8 (primary, one per trigger type), 6 (secondary variant, mood-weighted alternate). # # Schema corrections (Gestalt review, Sprint 17): @@ -46,7 +47,7 @@ lines: trigger: first_move mood: [focused] priority: 8 - cooldown: -1 + tags: [tutorial, movement, navigation] notes: > Directly from the sprint briefing example. First move teaches navigation: the district @@ -63,7 +64,7 @@ lines: trigger: first_new_section mood: [content] priority: 6 - cooldown: -1 + tags: [tutorial, movement, navigation, operational] notes: > Fires on entering a new section for the first time. 'Route's in the muscle' — the @@ -84,7 +85,7 @@ lines: trigger: first_fog_encounter mood: [focused] priority: 8 - cooldown: -1 + tags: [tutorial, fog, perception] notes: > Directly from the sprint briefing example. First fog boundary. Restated as habit: @@ -101,7 +102,7 @@ lines: trigger: first_fog_edge mood: [focused] priority: 6 - cooldown: -1 + tags: [tutorial, fog, perception] notes: > Second fog encounter line — fires when the player reaches the boundary of a fog zone @@ -122,7 +123,7 @@ lines: trigger: first_sound_heard mood: [focused] priority: 8 - cooldown: -1 + tags: [tutorial, sound, perception] notes: > Directly from the sprint briefing example. First sound heard that's not immediately @@ -140,7 +141,7 @@ lines: trigger: first_off_screen_sound mood: [content] priority: 6 - cooldown: -1 + tags: [tutorial, sound, perception, operational] notes: > Second sound line — fires when audio from an off-screen source is detected. The @@ -162,7 +163,7 @@ lines: trigger: first_npc_proximity mood: [content] priority: 8 - cooldown: -1 + tags: [tutorial, npc, interaction, social] notes: > Directly from the sprint briefing example. First time in range of an NPC. The smuggler @@ -180,7 +181,7 @@ lines: trigger: first_npc_face_read mood: [content] priority: 6 - cooldown: -1 + tags: [tutorial, npc, observation, social] notes: > Fires when the player observes an NPC at close range (face visible). The smuggler @@ -201,7 +202,7 @@ lines: trigger: first_insert_open mood: [content] priority: 8 - cooldown: -1 + tags: [tutorial, insert, hud, operational] notes: > Directly from the sprint briefing example. First insert/HUD open. The smuggler's @@ -218,7 +219,7 @@ lines: trigger: first_insert_contact_flag mood: [content, warm] priority: 6 - cooldown: -1 + tags: [tutorial, insert, hud, kael, friend-arc] notes: > Fires when the insert first flags a known contact (here: Kael, the FRIEND NPC). diff --git a/server/src/content/types.rs b/server/src/content/types.rs index 0d67cc99e..0536e358c 100644 --- a/server/src/content/types.rs +++ b/server/src/content/types.rs @@ -517,6 +517,9 @@ pub struct MonologueLine { pub prerequisites: Option, #[serde(default)] pub priority: Option, + /// Per-line cooldown in ticks. `None` (omitted in YAML) means no per-line + /// cooldown — fire-once lines rely on trigger semantics instead (e.g., + /// `first_*` and `contradiction_detected` triggers fire once by design). #[serde(default)] pub cooldown: Option, #[serde(default)]