fix(gateway): a translated intentional-silence sentinel is still silence
A model lane that does not think in English answers the cron instruction
("respond with exactly [SILENT]") by translating the sentinel rather than
dropping it. LIVE_GATEWAY_SILENT_MARKERS is English-only, so the whole control
token is delivered to the user as content. Carry the zh-Hans forms (the only
non-English locale this project documents) and derive the autonomous lane's
bracketed-prefix rule from the set so the two rules cannot drift.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011oAAQ4T859Y8fWNXRoiNEB
This commit is contained in:
@@ -11,8 +11,22 @@ from typing import Any
|
||||
|
||||
# Exact whole-response markers meaning "the agent intentionally chose not to
|
||||
# reply". Keep small and explicit; arbitrary empty output remains an
|
||||
# error/empty-response path, not silence.
|
||||
LIVE_GATEWAY_SILENT_MARKERS = frozenset({"[SILENT]", "SILENT", "NO_REPLY", "NO REPLY"})
|
||||
# error/empty-response path, not silence. A lane that does not think in English
|
||||
# translates the sentinel rather than dropping it, and the whole control token
|
||||
# then reaches the user as content, so the translated forms are carried here
|
||||
# too. zh-Hans is the only non-English locale this project ships documentation
|
||||
# for, which is where the list stops.
|
||||
LIVE_GATEWAY_SILENT_MARKERS = frozenset({
|
||||
"[SILENT]", "SILENT", "NO_REPLY", "NO REPLY",
|
||||
"[静默]", "静默", "[沉默]", "沉默",
|
||||
})
|
||||
|
||||
# Bracketed markers drive the autonomous lane's prefix rule ("[SILENT] nothing
|
||||
# new this tick"). Derived from the set above so a new marker cannot be added to
|
||||
# one rule and forgotten in the other.
|
||||
_BRACKETED_SILENCE_MARKERS = tuple(
|
||||
sorted(m for m in LIVE_GATEWAY_SILENT_MARKERS if m.startswith("["))
|
||||
)
|
||||
|
||||
# The persisted user-row kind of a self-injected MessageEvent(internal=True) turn — the only
|
||||
# machinery kind the gateway produces; only these may vanish on a bare silence marker.
|
||||
@@ -75,7 +89,7 @@ def is_autonomous_silence_response(response: Any) -> bool:
|
||||
return False
|
||||
lines = [ln for ln in stripped.splitlines() if ln.strip()]
|
||||
# Bracketed form only for the prefix rule, so a bare "Silent retry succeeded" is NOT swallowed.
|
||||
return stripped.upper().startswith("[SILENT]") or any(
|
||||
return stripped.upper().startswith(_BRACKETED_SILENCE_MARKERS) or any(
|
||||
_canonical_silence_candidate(c) in LIVE_GATEWAY_SILENT_MARKERS for c in (stripped, lines[0], lines[-1])
|
||||
)
|
||||
|
||||
|
||||
@@ -19,3 +19,26 @@ def test_autonomous_silence_accepts_marker_with_own_line_note():
|
||||
assert is_autonomous_silence_response("[SILENT] No changes detected")
|
||||
|
||||
|
||||
def test_translated_sentinel_suppresses_delivery():
|
||||
"""Regression: a non-English lane answers the silence instruction in its own language.
|
||||
|
||||
2026-09-14 — a deepseek cron lane had nothing to report and answered the cron
|
||||
instruction ("respond with exactly [SILENT]") with "[静默]". The control token
|
||||
was not a known marker, so the whole token was delivered to the user's DM as
|
||||
content.
|
||||
"""
|
||||
assert is_intentional_silence_response("[静默]")
|
||||
assert is_autonomous_silence_response("[静默]")
|
||||
|
||||
|
||||
def test_translated_sentinel_takes_the_same_forms_as_the_english_one():
|
||||
"""Same loose rule: own-line note, reordered lines, bracketless; the exact rule strips punctuation."""
|
||||
assert is_autonomous_silence_response("[静默]\n\nNothing new this tick.")
|
||||
assert is_autonomous_silence_response("2 deals filtered\n\n[沉默]")
|
||||
assert is_autonomous_silence_response("静默")
|
||||
assert is_intentional_silence_response("**沉默**")
|
||||
|
||||
|
||||
def test_prose_mentioning_the_translated_sentinel_is_delivered():
|
||||
assert not is_intentional_silence_response("status: 静默 means the lane is quiet")
|
||||
assert not is_autonomous_silence_response("the lane said 静默 mid-sentence and kept talking")
|
||||
|
||||
Reference in New Issue
Block a user