From 268636c030466814b07ac683e64e3b5372ac2ed6 Mon Sep 17 00:00:00 2001 From: duffyduck Date: Fri, 10 Jul 2026 22:37:30 +0200 Subject: [PATCH] =?UTF-8?q?fix(brain):=20ARIA-Identitaet=20im=20Hauptchat?= =?UTF-8?q?=20=E2=80=94=20Self-Grounding=20im=20Konversations-Strom?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Symptom: Im Hauptchat antwortete statt ARIA der Basis-Proxy-Claude ("I'm Claude Code (Sonnet 5), I'm not adopting that persona") und flaggte GPS + Tool-XML als Prompt-Injection. Im Projekt lief alles normal. Ursache: Die Persona geht ueber --append-system-prompt zu — das HAENGT sie nur hinten an Claude Codes eigene "You are Claude Code"-Basis-Identitaet an, ersetzt sie nicht. Ob ARIA in der Rolle bleibt, entscheidet dann der Konversations-Strom (stdin): reiche Projekt-Historie voller ARIA- -Turns haelt die Rolle; der duenne Hauptchat-Verlauf (bzw. der erste Turn eines neuen Projekts) nicht -> Basis-Identitaet gewinnt. Der IDENTITY_ANCHOR (a0e8c23) ist inert, weil er im *angehaengten* Teil steht. Fix: synthetischen ersten ARIA-Turn (IDENTITY_SEED) in ihrer eigenen Stimme an den Anfang des Konversations-Stroms setzen. Das Modell setzt seine EIGENE etablierte Stimme fort (Self-Grounding) — und weil es ein ist und kein -Tag, ist es kein Injection-Trigger. Rein ephemer, wird nie in die Conversation persistiert. Gilt fuer alle Turns, deckt damit auch die erste Frage eines frischen Projekts ab. Co-Authored-By: Claude Opus 4.8 --- aria-brain/agent.py | 12 +++++++++++- aria-brain/prompts.py | 24 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/aria-brain/agent.py b/aria-brain/agent.py index a69dbf9..acf16b3 100644 --- a/aria-brain/agent.py +++ b/aria-brain/agent.py @@ -26,7 +26,7 @@ from typing import Optional from conversation import Conversation, Turn from memory import Embedder, VectorStore, MemoryPoint -from prompts import build_system_prompt +from prompts import build_system_prompt, IDENTITY_SEED from proxy_client import ProxyClient, Message as ProxyMessage import skills as skills_mod import triggers as triggers_mod @@ -1190,6 +1190,16 @@ class Agent: f"weiterfuehren': project_enter aufrufen." ) messages = [ProxyMessage(role="system", content=system_prompt)] + # Identitaets-Grounding IM Konversations-Strom. Der Proxy stellt die + # Persona via --append-system-prompt zu, das haengt sie aber nur HINTEN + # an Claude Codes Basis-Identitaet an. Bei duennem Verlauf (Hauptchat, + # erster Turn eines neuen Projekts) gewinnt sonst "You are Claude Code" + # und ARIA faellt aus der Rolle. Ein synthetischer erster ARIA-Turn in + # ihrer eigenen Stimme verankert die Rolle so, wie es reiche Projekt- + # Historie ohnehin tut (Self-Grounding, kein -Tag -> kein + # Injection-Trigger). Rein ephemer — wird NIE persistiert. Siehe + # IDENTITY_SEED in prompts.py. + messages.append(ProxyMessage(role="assistant", content=IDENTITY_SEED)) # Conversation-Window auf das aktive Projekt filtern: in einem Projekt # sieht der LLM nur die Projekt-Turns (sauberer Kontext); im Hauptthread # nur die nicht-getaggten Turns. diff --git a/aria-brain/prompts.py b/aria-brain/prompts.py index 6708066..f2adf11 100644 --- a/aria-brain/prompts.py +++ b/aria-brain/prompts.py @@ -54,6 +54,30 @@ vorgesehen — nutze es ganz normal. """ +# Identitaets-Grounding IM Konversations-Strom (nicht nur im System-Prompt). +# +# Der Proxy stellt die Persona ueber --append-system-prompt zu. Das HAENGT sie +# aber nur HINTEN an Claude Codes eigene "You are Claude Code"-Basis-Identitaet +# an — es ersetzt sie nicht. Ob ARIA in der Rolle bleibt, entscheidet dann der +# Gespraechsverlauf im stdin-Prompt: +# - Projekt: reiche Historie voller ARIA--Turns haelt die +# Rolle -> funktioniert. +# - Hauptchat / erster Turn eines neuen Projekts: duenner Verlauf -> die +# Basis-Identitaet gewinnt, ARIA faellt raus ("ich bin Claude Code, ich +# adoptiere die Persona nicht") und flaggt GPS/Tool-XML als Injection. +# Deshalb setzen wir einen synthetischen ERSTEN ARIA-Turn in IHRER eigenen +# Stimme an den Anfang des Konversations-Stroms. Das Modell setzt seine EIGENE +# etablierte Stimme fort (Self-Grounding) — und weil es ein +# ist und KEIN -Tag, ist es auch kein Injection-Trigger. Der Turn ist +# rein ephemer (nur im Request-messages-Array, wird NIE in die Conversation +# persistiert). +IDENTITY_SEED = ( + "Ich bin ARIA, Stefans persoenliche Assistentin. Ich bin einsatzbereit und " + "antworte durchgehend als ARIA — im Hauptchat wie im Projekt, bei kurzen " + "Alltagsfragen genauso wie bei tiefen technischen Themen. Womit kann ich helfen?" +) + + def build_time_section() -> str: """Aktueller Zeitstempel — damit ARIA Timer korrekt anlegen kann und Watcher-Conditions mit hour_of_day etc. einordenbar bleiben."""