fix(prompt): allow ZWJ emoji in context files#18616
Conversation
U+200D (Zero Width Joiner) is the standard Unicode mechanism for gendered and compound emoji sequences. The invisible-char scanner blocked entire context files (SOUL.md, AGENTS.md, etc.) when any ZWJ was present, silently censoring legitimate emoji. Remove U+200D from _CONTEXT_INVISIBLE_CHARS while keeping all other truly suspicious invisible characters (zero-width space, directional overrides, BOM). Add regression tests for both the allowed ZWJ path and the continued blocking of the remaining invisible characters. Closes NousResearch#18581
Community PRs applied: - NousResearch#18596: Enable secret redaction by default (SECURITY) - NousResearch#18650: Sanitize malformed tool messages + auto-recover on API 400 - NousResearch#18607: Emergency compression before max_iterations exhaustion - NousResearch#18603: Compression fallback to main model on 413 rate limit - NousResearch#18638: Pass threshold_percent on model switch - NousResearch#18663: Strip extra_content from tool_calls for strict APIs - NousResearch#18618: Forward explicit_api_key to OpenRouter - NousResearch#18632: Show cache tokens in /insights breakdown - NousResearch#18614: Add idempotency guard for patch duplicate loops - NousResearch#18600: Raise ValueError when HERMES_HOME unset in profile mode - NousResearch#18616: Allow ZWJ emoji in context files - NousResearch#18582: Reload .env on /restart - NousResearch#18547: Stabilize system prompt prefix for KV cache reuse - NousResearch#18692: Strip FTS5 operators from session search truncation terms Fix: Add order_by_last_active=True to list_sessions_rich call (pre-existing commit 142b4bf code sync)
|
Thanks for this, @liuhao1024 — the diagnosis is correct and the regression tests are well thought out. Closing without merging for two reasons: 1. The target has been refactored away. The 2. Blanket removal is the wrong fix — and the right one already landed. Dropping U+200D from the set entirely would also stop blocking ZWJ hidden between plain-text characters, which is a real steganographic injection vector — that's why the isolated ZWJ block is intentional (see the discussion on #18581). The accepted approach is emoji-aware: allow ZWJ when it sits inside an emoji grapheme cluster, still block it in plain text. That's already implemented for cron prompts in Issue #18581 was closed as completed. Appreciate the contribution and the clear repro — credit to you for surfacing the emoji case. |
What does this PR do?
_CONTEXT_INVISIBLE_CHARSso that standard Unicode emoji sequences no longer silently block entire context filesRelated Issue
N/A
Type of Change
Changes Made
How to Test
pytest tests/ -q— all tests should passChecklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests passDocumentation & Housekeeping
docs/, docstrings) — or N/Acli-config.yaml.exampleif I added/changed config keys — or N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture and workflows — or N/A