Beobachtung 30.05.2026 02:51-02:53: zwei verkettete Antipatterns
beim Spotify-Test.
1. ARIA bekam 403 vom /pause-Endpoint, vermutete 'der 204-Bug ist
zurueck' und patchte den Skill — zweimal hintereinander. Der
204-Fix war aber laengst im Code (haette sie durch skill_get in
5s gesehen). Symptome != Diagnose.
2. Bei den 403s antwortete sie 'war schon pausiert, daher der 403'
und 'schon aktiv, daher der 403'. Beides war geraten basierend
auf is_playing-Check, nicht aus den Daten gelesen. 403 'Restriction
violated' kann viele Ursachen haben (NO_ACTIVE_DEVICE,
ALREADY_PAUSED, PREMIUM_REQUIRED, MARKET_RESTRICTED, ...) — die
wahre steht als error.reason im JSON-Body. Sie hat das verschluckt
und plausibel-aber-geraten geantwortet.
Eine Regel deckt beide Patterns ab, generisch fuer alle Skills:
- Vor jedem skill_update: erst skill_get lesen, dann beurteilen
- Bei HTTP-Errors: Body / error.reason zitieren, nicht raten
- Wenn der Skill die wahre Ursache verschluckt: skill_update mit
besserer Error-Extraktion (NACH skill_get, nicht davor)
Wirkt fuer alle aktuellen + zukuenftigen API-Skills.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mut zur Luecke: -595 Zeilen Auto-Magie-Code raus, weil sie heute Abend
4 Bugs verursacht und 0 echten Mehrwert geliefert hat. Plus Stefan
hat zu Recht erkannt dass das System mit Pentest/Audit-Workflows
kollidieren wuerde (Whitelist-Pflege noetig).
Weg:
- aria-brain/api_heuristic.py geloescht (282 Zeilen Cross-Session-
Tracking, Hint-Generation, Bypass-Detection)
- aria-brain/agent.py: Auto-Scaffold-Block, Bypass-Detection-Block,
_upsert_bypass_lesson-Methode (-146 Zeilen)
- aria-brain/main.py: /skills/can-bash-host Endpoint
- aria-brain/prompts.py: api_heuristic_section-Parameter
- docker-compose.yml: managed-settings-Copy aus proxy-Command
- proxy-patches/pre-tool-bash-block.js (PreToolUse-Hook)
- proxy-patches/managed-settings.json (claude-CLI Hook-Config)
Bleibt (kostet nichts, hilft):
- Alle 18 seed_rules (sind in DB, machen keine Last)
- skill_scaffold Tool (ARIA kann es manuell nutzen)
- Anti-Friedhof + snake_case + Safe-Name-Mapping (passive Validierung)
- Versionierung + Rollback (P4, hat sich bei PATH-Bug bewaehrt)
- 50k stdout Truncate-Fix
scaffold-reflex seed_rule umgeschrieben: kein 'SOFORT scaffold'-
Reflex mehr, stattdessen 4-Punkte-Heuristik (parametrisierbar?
wiederkehrend? exploratory? im Zweifel: Stefan fragen). Pentest-
Workflows bleiben damit ad-hoc Bash ohne false-positive
Skill-Vorschlaege.
Existierende auto-feedback-Memories in der DB bleiben — sind nuetzliche
Lehren, werden nicht mehr automatisch erweitert. Stefan kann sie via
Diagnostic-Gehirn-Tab loeschen wenn sie nerven.
Dank git ist alles rueckholbar. Wenn doch wieder Auto-Magie gewuenscht:
git revert auf 8d5991f.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Beobachtung 30.05.2026 02:22: Stefan bat 'vorheriges lied'. ARIA hat
POST /previous gemacht — Spotify gab 204 No Content zurueck (Erfolgs-
Antwort ohne Body), aber der alte Skill-Code warf JSON-Parse-Error
weil kein Body zum Parsen. ARIA interpretierte das als 'Skill kaputt',
patchte ihn UND fuehrte previous nochmal aus.
Folge: Stefan landete ZWEI Lieder zurueck statt eins. Aergerlich weil
unerwartete Zustandsaenderung.
Neue Regel adressiert das:
- Side-Effect-Tools (POST/PUT/DELETE, next/previous/play/pause, send-
message etc.) sind NICHT idempotent — Retry verdoppelt den Effekt.
- Bei unklarem Result IMMER zuerst State pruefen (currently-playing,
list-Endpoint etc.), dann beurteilen ob Wiederholung noetig.
- HTTP 204 No Content ist KEIN Fehler bei POST/PUT — typische Spotify-
Antwort. Skill darf 204 NICHT als Parse-Error werten.
- GET-Calls / Search sind retry-safe, hier keine Sorge.
ARIAs zweiter Skill-Patch ist uebrigens technisch korrekt (ARG_-
Konvention zurueck, 204 handled, strukturierte Ausgabe fuer
currently-playing). Nur das doppelte Side-Effect war das Problem.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Beobachtung 30.05.2026: ARIA hat beim skill_update des spotify-Skills
die ARG_-Konvention verloren. Statt os.environ.get('ARG_PATH', '')
hat sie os.environ.get('PATH', '') geschrieben. PATH ist aber die
reservierte Linux-Environment-Variable fuer den Executable-Suchpfad
(/usr/local/sbin:/usr/local/bin:...).
Folge: Skill las den System-PATH als URL-Pfad, rief
https://api.spotify.com/usr/local/sbin:/usr/local/bin:... → 404
zurueck. Stefan dachte Spotify sei kaputt. Rollback noetig
(Auto-Archive hat geholfen — alte Version war gluecklicherweise
noch da).
Neue Regel macht das explizit:
- ARG_<UPPER_NAME> ENV ist Pflicht-Konvention vom Skill-Runner
- Liste reservierter ENV-Namen die NICHT genommen werden duerfen:
PATH, HOME, USER, SHELL, LANG, TERM, PWD, OLDPWD,
BRAIN_INTERNAL_URL, SKILL_DIR, SHARED_UPLOADS, CFG_*
- Mit Praefix ARG_ keine Kollision moeglich
Plus skill_create Tool-Description um den gleichen Hinweis
ergaenzt: 'Args lesen via os.environ['ARG_<UPPER_NAME>'] — der
Praefix ARG_ ist Pflicht. NIEMALS direkt PATH/METHOD/BODY etc.
abrufen — das sind reservierte System-ENV (PATH = Executable-
Suchpfad, nicht Dein arg!).'
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Beobachtung 30.05.2026: Stefan bittet ARIA via skill_update den
spotify-Skill so anzupassen dass currently-playing strukturiert
ausgegeben wird (Track/Artist/Album/Device/Zeit). ARIA antwortet
mit Defensiv-Reflex: 'Der Skill ist nur ein OAuth2-Wrapper, ich
kann das nicht im Wrapper bauen — ich schlage einen zweiten Skill
spotify_now_playing vor'.
Quatsch. Skills sind beliebiger Python-Code. Ein
`if path.endswith('currently-playing'): pretty_output()` waere
trivial im Skill drin gewesen. Stefan haette das nicht selbst
erkennen muessen — genau dafuer ist ARIA da.
Neue Regel macht das explizit:
- skill_get + skill_update ist der Standard-Workflow fuer
Skill-Anpassungen
- Skills duerfen if-Verzweigungen, json-Parsing, Output-Filterung,
mehrere Endpoints in einem Skill etc.
- 'Kann ich nicht in den Wrapper bauen' ist Antipattern
- 'Ich schlage einen zweiten Skill vor' ohne erst skill_update
zu pruefen ist Antipattern
- Stefan ist KEIN Python-Entwickler — er nennt das ZIEL, ARIA
baut das WIE.
Plus skill_update Tool-Description um den gleichen Gedanken
ergaenzt: 'Skills sind ganz normaler Python-Code, du kannst sie
beliebig erweitern.'
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Beobachtung beim Hook-Deploy-Test (30.05.2026, 01:51-52): ARIA versucht
run_spotify zuerst als nativen Tool-Use → 'No such tool available'
weil claude-CLI nur seine eigenen Tools (Bash/Read/Write/etc.) kennt;
Brain-Tools sind als Prompt-Instruction injiziert.
Erst nach dem 'No such tool'-Fehler wechselt ARIA aufs XML-Tag-Format
<tool_call name="...">{...}</tool_call>, das der proxy parsed und ans
Brain weiterleitet. Dieser Lernzyklus pro Anfrage kostet ~30s.
Die Regel erklaert die Architektur (claude-CLI vs Proxy vs Brain) und
gibt das richtige Format vor — direkt XML-Tag, nicht native Tool-Use.
Beilaeufige Bestaetigung an Stefan: seed_rules.py ist System-Code, wird
bei jedem Brain-Lifespan-Start aufgespielt — frische DB nach Wipe wird
beim ersten Boot mit den 15 Regeln gesetzt, idempotent ueber
migration_key. Im Gegensatz zu brain-import/ (gitignored, manuelle
Migration via Diagnostic-Klick).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Live-Beobachtung am 30.05.2026: ARIA spawnte `Agent` (Sub-Agent) mit
Anweisung 'Call run_spotify...' statt das Tool direkt aufzurufen. Der
Sub-Agent ist eine isolierte Claude-CLI-Session ohne Brain-Tools, hat
also 'No such tool: run_spotify' gemeldet. ARIA hat dann halluzinierte
Track-Namen ausgegeben ('Set You Free – N-Trance', 'Tomcraft –
Loneliness'), als waeren das echte Spotify-Daten.
Drei distinkte Probleme, zwei neue Regeln:
13. seed/skill-rule/no-subagent-for-skills:
Brain-Tools (run_*, oauth_*, memory_* …) NIEMALS via Agent-Subagent
aufrufen — die sind isoliert und sehen die Brain-Tools nicht.
Direkt in der Haupt-Session aufrufen. Subagent nur fuer Code-Search
/ Web-Recherche / parallele unabhaengige Aufgaben.
14. seed/rule/no-hallucinated-results (Kategorie 'ehrlichkeit'):
Bei Tool-Fail / abgeschnittenem Response / fehlendem Tool: ehrlich
sagen, NICHT raten. Anti-Antipattern: 'Stefan vertraut Deinen
Antworten — wenn Du raetst und es als Fakt verkaufst, bricht das
Vertrauen'. Mit konkreten Formulierungs-Beispielen.
Beide Regeln sind erfahrungsbasiert (mit Datum + konkretem Vorfall) —
ARIA sieht im Hot-Memory was sie selbst falsch gemacht hat.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Stefan-Frage: 'weiss sie in zukunft unterstriche statt bindestriche?'
Antwort vorher: nein — Tool-Description sagte 'kebab-case'. Genau das
hat die Bindestrich-Skills produziert die gestern die Tool-Liste kippten.
Drei Aenderungen:
- skill_create Tool-Description: 'kurz, kebab-case' → 'snake_case (NUR
a-z 0-9 _). KEINE Bindestriche — die brechen das Tool-Schema beim
claude-max-api-proxy. Statt yt-dlp-download → yt_dlp_download.'
- skill_scaffold Tool-Description: gleiche Klarstellung.
- 12. seed_rule snake-case-names: erklaert das Verbot mit Begruendung
(proxy-Limitierung), Beispielen RICHTIG/FALSCH und Hinweis dass
historische Skills mit Bindestrich ueber das Safe-Name-Mapping laufen
(nicht umbenennen).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Variante C: ARIA hat selbst mit Heuristik-Block + 11 seed_rules den
expliziten skill_scaffold-Befehl ignoriert (32x Spotify-Bash-Calls in
24h, kein einziger scaffold-Aufruf). Verhaltens-Traegheit ist staerker
als jeder Prompt-Hint.
Loesung: Brain wartet nicht mehr. Bei jedem chat()-Aufruf wird die
Heuristik berechnet. Findet sie einen Host mit bekannter Suggestion
(Spotify, GitHub, OpenAI, OpenWeather, Telegram, Microsoft, Discord,
Notion, Reddit) der noch keinen Skill hat → Brain ruft selbst
`scaffold_skill(name, template, params)` mit author='aria-auto'.
Der frische Skill ist sofort im Prompt sichtbar (Skill-Liste wird nach
Scaffold refreshed, Heuristik-Cache invalidiert, Hints neu gerechnet).
Side-Channel-Event 'skill_created' mit Flag 'auto_scaffolded' geht an
die UI — Stefan sieht im Chat dass Brain einen Skill angelegt hat.
ARIA findet beim Tool-Use-Loop einen passenden `run_<name>`-Skill vor
und nutzt ihn idealerweise statt wieder Bash. Macht sie's nicht und
curlt trotzdem weiter, ist der Counter beim naechsten Mal wieder hoch
und Brain scaffolded weiter — aber dann ist der Skill ja schon da, also
nur ein Pfad.
Toggle: BRAIN_AUTO_SCAFFOLD=false zum Abschalten.
scaffold-reflex Regel angepasst: ARIA wird informiert dass Brain
manchmal selbst scaffolded (author=aria-auto) und sie den Skill via
run_<name> nutzen soll statt zu curlen. Bei Hinweisen OHNE Suggestion
(unbekannter Host) soll sie selbst skill_scaffold rufen.
Stefan-Zitat aus der Diskussion ("ARIA lernt es so nicht"): stimmt
inhaltlich, aber pragmatisch wichtiger ist dass Stefans Wartezeit von
20s auf 3s sinkt. Lernen kann sie spaeter — der Skill ist da, sie sieht
den Pfad jedes Mal beim Tool-Listing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Variante B: scaffold-reflex Regel allein reicht nicht weil jede Chat-
Anfrage eine eigene claude-CLI-Session ist. ARIA sieht in der aktuellen
Session nicht dass sie gestern auch schon 10x dieselbe API gecurled hat.
Beobachtung: 5+ Spotify-Bash-Calls hintereinander, kein Skill angelegt.
Loesung: Brain trackt server-side aus dem persistierten agent_stream.jsonl.
Bei jedem chat() wird der Log gescanned (cache 5min), Bash-curl-Calls
nach Hostname aggregiert. Hosts mit >=3 Calls in 24h ohne passenden
Skill landen als '## API-Heuristik'-Block im System-Prompt mit konkretem
skill_scaffold-Vorschlag.
Neue Module:
- aria-brain/api_heuristic.py:
- compute_hints(existing_skills, force): Aggregiert + filtert
- build_section(hints): formatiert als kompakten Markdown-Block
- Smart suggestions mapping (api.spotify.com → oauth-api template etc.)
- Ignoriert interne Hosts (aria-brain, localhost, docker-bridge)
- 5-min Cache damit nicht jeder Turn die JSONL parst
- aria-brain/prompts.py: build_system_prompt nimmt api_heuristic_section
als optionalen Block direkt nach Skills-Section.
- aria-brain/agent.py: vor build_system_prompt Heuristik berechnen mit
aktueller Skill-Liste, Block durchreichen.
- 11. seed_rule scaffold-reflex umgeschrieben: kein 'in einer Session'
mehr (das ergab keinen Sinn — jeder Turn neue Session). Stattdessen:
'## API-Heuristik'-Block ist Dein Cross-Session-Gedaechtnis. Wenn da
was steht: scaffolden BEVOR Du Bash machst.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Variante C: niedrigere Huerde zum Skill-Bau. Statt einen kompletten
Python-Skill via skill_create zu generieren (~100 Zeilen Code, teuer in
Tokens und fehleranfaellig), waehlt ARIA ein Template + minimale params,
Brain expandiert das Skelett in ~1s zu fertigem Skill.
Beobachtung: ARIA driftet bei Spotify, PDF etc. zu Bash-curl statt
einen Skill zu bauen, weil die Skill-Bau-Huerde zu hoch ist (Code,
README, args, pip_packages, config_schema). Mit Templates ist die
Huerde minimal.
Neue Module:
- aria-brain/skill_templates.py: drei mitgelieferte Templates
- oauth-api: OAuth2-API (Spotify, GitHub, Reddit, Google, Discord, ...).
Token via BRAIN_INTERNAL_URL/oauth/<s>/token mit Auto-Refresh.
Args: method/path/body/base_url
- apikey-api: API mit statischem Key (OpenWeather, OpenAI, Twilio).
Key liegt im config_schema -> CFG_<NAME> ENV, KEIN hardcoden.
Konfigurierbar: auth_header (Authorization|X-Api-Key), auth_prefix.
- file-process: Skelett fuer File-In/File-Out (PDF, Bild, JSON).
process()-Funktion ist Stub, ARIA fuellt sie via skill_update.
Templates nutzen Token-Replacement statt f-Strings (sonst Konflikt
mit dem skill-internen Python-Code).
- aria-brain/skills.py: scaffold_skill(name, template, params, author)
wrappt create_skill mit den expandierten Feldern.
- aria-brain/agent.py: neues Brain-Tool skill_scaffold mit detaillierter
Description (Template-Liste + params-Schema). Dispatcher-Handler
schickt skill_created Side-Channel-Event analog zu skill_create.
- aria-brain/main.py: POST /skills/scaffold + GET /skills/templates
(letzteres listet alle Templates fuer UI/Diagnostic).
- 11. seed_rule scaffold-reflex: bei 2x derselben API per Bash-curl
SOFORT skill_scaffold rufen. Belohnung explizit benannt
("welches lied" von 20s auf 3s).
README mit Skills-Scaffold-Tabelle ergaenzt.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Beobachtung beim "ueberspringe Lied"-Test (29.05.2026): 47 Sekunden mit
12 fehlgeschlagenen Bash-Versuchen weil ARIA glaubte sie sei im
aria-brain Container. Sie hat probiert:
- python3/python/jq (Alpine — alle nicht installiert)
- cd /data/skills/spotify-control (existiert nur im Brain)
- curl localhost:8080/oauth/... (localhost = aria-proxy, nicht Brain)
- 8s Timeout auf localhost (kein TCP Reset)
Erst nach 9 Versuchen brain:8080 erraten und dann den Token-Wert
hardcoded in den naechsten curl gepackt.
Die neue Regel beschreibt die echte Topologie explizit:
- Du bist die claude-CLI als Subprocess IM aria-proxy (node:22-alpine)
- KEIN python3/python/jq verfuegbar
- /data/skills/ existiert NUR im aria-brain
- localhost in Deinem Bash heisst aria-proxy; Brain ist aria-brain:8080
- BRAIN_INTERNAL_URL ist NUR in laufenden Skills gesetzt
- Brain-Resources via Brain-Tools (oauth_get_token, memory_search,
run_<skill_name>), NICHT via Bash
- SSH zur VM-Host: `ssh aria@host` (ed25519-Key liegt im Proxy)
- Externe APIs direkt per curl mit Token aus oauth_get_token
Plus das Anti-Pattern dokumentiert ("47 Sekunden Stefan-Lebenszeit") —
ARIA soll bei jedem Bash-Reflex gegen "lokale" Brain-Resources erst
denken oder die Brain-Tool-Ebene nehmen.
README in Skills-Architektur-Sektion entsprechend ergaenzt (10 Regeln).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Befund aus chat_backup.jsonl-Analyse heute: ARIA ist 3x auf oauth_authorize
gefallen statt oauth_get_token (Stefan musste manuell einloggen), und beim
PDF-Skill ist sie nach Stefans "Variante bitte" zu Ad-hoc-Bash-Befehlen
auf der VM gedriftet ("ich lass den Code direkt laufen") — Skill wurde
unbrauchbar. Beides genau die Antipattern die wir mit den seed_rules
abdecken wollten, nur waren die zu schwach formuliert.
seed_rules (jetzt 9 statt 7):
- oauth-reauth-reflex: bei 401 ZUERST oauth_get_token, NUR bei dessen
Fehler oauth_authorize. Stefan zu Re-Login schicken ist das aergerlichste
Antipattern (er sitzt im Auto, muss Handy rauskramen).
- no-skill-drift: kaputter Skill -> skill_logs + skill_update, NIEMALS
zu Ad-hoc-Bash wechseln (Skill wird Karteileiche). Plus: "ich baue
dir einen Skill" SAGEN ohne skill_create zu rufen ist verboten —
Stefan checkt die Liste und verliert das Vertrauen.
agent_stream-Persistenz:
- diagnostic/server.js schreibt jeden agent_stream-Event parallel zum
Broadcast in /shared/logs/agent_stream.jsonl (soft-cap 50 MB mit
half-truncate beim Ueberlauf).
- Live-View laedt beim Page-Load + Sub-Tab-Switch die letzten 200
Eintraege via /api/agent-stream. Browser-Reload / Standby verliert
damit den Verlauf nicht mehr.
Debug-API ohne SSH:
- GET /api/chat-backup?lines=N (Default 200, Max 5000) — geparstes JSON
der letzten N Zeilen aus chat_backup.jsonl
- GET /api/agent-stream?lines=N — gleiches fuer den persistierten Stream
README:
- Neuer Abschnitt "## Skills — Architektur" mit Skill-Layout,
Drei-Stufen-Daten-Modell (OAuth / config_schema / Brain-Daten),
Versionierung, Anti-Friedhof, seed_rules (alle 9 aufgelistet).
- Diagnostic-Sektion um agent_stream-Persistenz + neue Debug-Endpoints
ergaenzt.
- Roadmap: Phase B "Skill-Architektur P0-P4" abgehakt.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ARIA wusste bisher nichts von BRAIN_INTERNAL_URL — sie hatte den Endpoint
zwar, aber keinen Grund ihn zu nutzen. Zwei neue rule-Memories:
- "BRAIN_INTERNAL_URL ist deine Brain-Schnittstelle" — listet die
wichtigsten Endpoints (oauth/<service>/token, memory/search,
memory/pinned, skills/list) und macht klar dass auch Daten wie
Stefans Standort, Memories oder andere Skills aus dem Skill heraus
abrufbar sind.
- "Auth-Strategie fuer externe APIs" — zwingt ARIA bei jedem API-Skill
in eine Checkliste: erst OAuth2 pruefen (Spotify, Google, GitHub,
Reddit, …), sonst statischer Key per config_schema, NIEMALS hardcoden.
Damit kommt sie eigenstaendig auf "Spotify = OAuth2 = Brain-Endpoint"
ohne dass Stefan das jedes Mal sagen muss. Insgesamt jetzt 7 seed_rules
statt 5.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Stefans Skill-Friedhof (9 Spotify-Skills, hardcoded Credentials) hatte
keine systemische Ursache im Code, sondern im fehlenden Leitplanken-
Memory. Lösung: System-Seed-Regeln als pinned Hot Memory, mit jedem
Deploy ausgerollt.
- aria-brain/seed_rules.py: 5 rule-type Memories (skill_list-vor-create,
no-version-suffix, update-not-recreate, no-hardcoded-credentials,
config-schema-for-settings), source="seed", pinned=true
- Lifespan ruft seed_rules.apply() beim Brain-Start — idempotent via
migration_key (alte Versionen werden vor dem Schreiben gelöscht)
- skill_create Tool-Description um PFLICHT-VORHER-Block ergänzt:
skill_list-check, kein Versionssuffix, oauth_get_token bei OAuth,
config_schema statt hardcoded Werte
Editieren = SEED_RULES-Liste anpassen, Brain neu starten. Im Gegensatz
zu brain-import/ (User-Saatgut, gitignored, manueller Diagnostic-Klick)
gehört das hier zum Brain-Code und rollt mit jedem Deploy aus.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>