Skip to content

fix: align NPC public lore and dialog exit#110

Merged
JOY (JOY) merged 1 commit into
devfrom
codex/npc-dialogue-public-boundary
May 21, 2026
Merged

fix: align NPC public lore and dialog exit#110
JOY (JOY) merged 1 commit into
devfrom
codex/npc-dialogue-public-boundary

Conversation

@JOY
Copy link
Copy Markdown
Contributor

Summary

  • Align NPC public speech with the lore boundary so ordinary NPCs use body, TIME, SECOND, BodyTime, permits, and clinic rumor language instead of overexposing Frame or transfer mechanics.
  • Add a public speech sanitizer and regression coverage for model output that leaks restricted Frame, reincarnation, or neural imprint wording.
  • Snap dialog and talking animation state back to idle or movement when chat mode exits or movement starts.

Local code review

  • Verdict: APPROVED WITH SUGGESTIONS.
  • No blocking findings.
  • Suggestion tracked for later: the public speech sanitizer is an MVP guardrail. A production unlock path should make restricted terms role, trust, quest, and scene aware instead of globally replacing them.

Verification

  • npm run build in backend/nakama
  • npm test in backend/nakama
  • git diff --cached --check
  • Em dash scan on changed code, docs, and data files
  • Local Nakama runtime restart and healthcheck passed before packaging

@JOY JOY (JOY) merged commit 9eb0d16 into dev May 21, 2026
2 checks passed
@JOY JOY (JOY) deleted the codex/npc-dialogue-public-boundary branch May 21, 2026 04:19
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 39d09ef384

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "Codex (@codex) review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "Codex (@codex) address that feedback".

Comment on lines 5727 to +5730
if (targetId && !isNearbyActor(world, targetId)) {
decision.target_id = "";
}
decision.say = sanitizePublicNpcSpeech(decision.say);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Respect specialist unlocks before sanitizing NPC speech

The new sanitizer is applied to every say decision unconditionally, so even lore that is intentionally unlocked for specialist NPCs or quest scenes is rewritten to public-safe euphemisms. In those contexts the agent can no longer deliver required explanations (for example, explicit reincarnation or transfer details), which conflicts with the same commit's prompt rule that these terms are allowed when context explicitly unlocks them.

Useful? React with 👍 / 👎.

Comment on lines +5756 to +5757
text = text.replace(/\bReincarnation\b/g, "A clinic rumor");
text = text.replace(/\breincarnation\b/g, "clinic rumor");
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Make restricted-term replacements case-insensitive

Several restricted-term rewrites are case-sensitive (/g), so model output like FRAME, FRAMES, or REINCARNATION bypasses the boundary filter and can still leak the exact terms this guardrail is meant to suppress. This is reproducible with emphasized or adversarially prompted uppercase responses, and it undermines the reliability of the new public-speech boundary.

Useful? React with 👍 / 👎.

Comment on lines +5756 to +5757
text = text.replace(/\bReincarnation\b/g, "A clinic rumor");
text = text.replace(/\breincarnation\b/g, "clinic rumor");
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve proper nouns when sanitizing restricted lore terms

The blanket reincarnation replacement also rewrites literal names and titles, so lines that should reference concrete places or factions (for example, Reincarnation Ward) are transformed into malformed text like A clinic rumor Ward. This can corrupt navigation or quest guidance whenever NPC speech needs to cite canonical proper nouns instead of discussing mechanics.

Useful? React with 👍 / 👎.

Comment on lines +113 to +116
CharacterWeaponStyle.TwoHandSword => new CharacterAnimationCommand(CharacterAnimationCommandKind.State, "2Handed - Idle - Idle"),
CharacterWeaponStyle.TwoHandSpear => new CharacterAnimationCommand(CharacterAnimationCommandKind.State, "Spearman - Idle - Idle"),
CharacterWeaponStyle.TwoHandAxe => new CharacterAnimationCommand(CharacterAnimationCommandKind.State, "Hammer - Idle - Idle"),
CharacterWeaponStyle.TwoHandBow => new CharacterAnimationCommand(CharacterAnimationCommandKind.State, "Archer - Idle - Idle"),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use valid animator state paths for idle snap transitions

The newly added idle mappings use short labels like 2Handed - Idle - Idle, but this animation system resolves state hashes via Animator.HasState and the existing intent registry uses full-path names (for example Base Layer...) for that reason. With short labels, TryPlayStateImmediately will usually fail to find the state, so exiting dialog won't reliably snap back to idle as intended.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant