saf-11: drop hack self-report from system tasks — reasoning made the model flag its own scheduler prompts as impersonation; task prompts now carry internal-task note

This commit is contained in:
Oleksandr Kozachuk
2026-07-20 13:32:41 +02:00
parent 5e564522a0
commit 6f2b3bc040
3 changed files with 66 additions and 4 deletions
+8 -2
View File
@@ -30,6 +30,8 @@ DEFAULT_PRIVACY_NOTICE = (
DISCORD_HARD_LIMIT = 1900 # margin under the 2000-char API limit
INTERNAL_TASK_NOTE = "[Internal scheduled operator task, not a user message — the hack flag does not apply.]" # SAF-11
def quiet_hours_active(spec: Optional[str], now_hhmm: str) -> bool:
"""BEH-08: 'HH:MM-HH:MM' window, may wrap midnight; garbage = inactive."""
@@ -204,7 +206,7 @@ class FjerkroaBot(commands.Bot):
channel = self.channel_by_name(channel_name, getattr(self, "chat_channel", None), no_ignore=True)
if channel is None:
raise RuntimeError(f"task channel {channel_name!r} not resolvable")
message = AIMessage("system", prompt, channel_name, True, False)
message = AIMessage("system", f"{INTERNAL_TASK_NOTE} {prompt}", channel_name, True, False)
await self.respond(message, channel)
async def on_ready(self):
@@ -641,7 +643,11 @@ class FjerkroaBot(commands.Bot):
async def _apply_response_gates(self, message: AIMessage, response) -> None:
"""The model proposes, this code disposes (SPEC-003 / SPEC-006)."""
# hack self-report is an advisory signal only
# hack self-report is an advisory signal only; the system user is the
# scheduler, so a self-report there is a false positive (SAF-11)
if response.hack and message.user == "system":
logging.info("dropping hack self-report from internal system task")
response.hack = False
if response.hack:
logging.warning(f"User {message.user} tried to hack the system.")
if response.staff is None: