Files
Masterarbeit/.claude/skills/run-experiment/SKILL.md
T
2026-08-26 07:34:29 +02:00

46 KiB
Raw Blame History

name, description, argument-hint, version
name description argument-hint version
run-experiment Führt einen Versuchs-Prompt aus einer Prompt-Datei als messbaren Headless-Lauf aus (claude -p) und schreibt ein Messprotokoll mit Start-/Endzeit, Modell, Tokenverbrauch und weiteren Metriken. Verwenden bei "/run-experiment <Pfad-zur-Prompt-Datei>" oder wenn der User einen Versuch/ein Experiment ausführen und tracken will. <Pfad zur Prompt-Datei> <Root-Verzeichnis> 3.10.0

RunExperiment – Versuchslauf mit Messprotokoll

Du führst einen wissenschaftlichen Versuchslauf für die Masterarbeit aus. Der Prompt aus der übergebenen Datei wird als separater Headless-Lauf von Claude Code ausgeführt, damit Tokenverbrauch und Modell exakt und maschinenlesbar erfasst werden. Anschließend schreibst du ein Messprotokoll neben die Prompt-Datei.

Parameter

  • Prompt (Pflicht): Pfad zur Prompt-Datei (Markdown). Erstes Argument in $ARGUMENTS.
  • Root (Pflicht): Verzeichnis, das als Root des Versuchslaufs dient. Zweites Argument. Der Headless-Lauf wird mit diesem Verzeichnis als Arbeitsverzeichnis gestartet – es ist die Wurzel der zu analysierenden Codebasis und wird nur GELESEN. Fehlt das Argument: den User danach fragen und NICHT stillschweigend das aktuelle Verzeichnis verwenden. Vor dem Lauf prüfen, dass das Verzeichnis existiert; sonst abbrechen und den User informieren.
  • Modell (Pflicht, kein Default): Wird vor jedem Lauf beim User erfragt – siehe Schritt 4 im Ablauf. Nennt der User das Modell bereits im Aufruf („… mit Opus 5"), diese Angabe übernehmen und nicht erneut fragen. Ohne Angabe niemals stillschweigend ein Modell wählen: Das Modell ist eine unabhängige Variable der Versuchsreihe.
  • Agentenmodus (Pflicht, kein Default): Wird wie das Modell vor jedem Lauf beim User erfragt – siehe Schritt 5 im Ablauf. Bestimmt, ob und welche Subagenten der Lauf einsetzen darf. Drei Modi: solo, builtin, custom (Details in Schritt 5).
  • Effort (Pflicht, kein Default): Denkaufwand des Modells. Wird wie Modell und Agentenmodus vor jedem Lauf beim User erfragt – siehe Schritt 6.

Alle Ausgaben des Laufs (Ergebnisdateien, Messprotokoll, Rohdaten) landen in einem neuen Laufverzeichnis neben der Prompt-Datei, niemals im Root-Verzeichnis:

<Verzeichnis der Prompt-Datei>\
  <NN>_Prompt.md
  <ModellID>\<Agentenmodus>\<Effort>\
    <NN>_Lauf_<yyyy-MM-dd_HHmmss>_v<skillversion>-<id4>\
      Protokoll.md
      RawResult.json
      Stderr.log
      _meta\             (Laufsteuerung: combined_prompt.md, before.txt, after.txt, Zeitstempel,
                          subagenten.md/.json, anforderungen.md/.json)
      Ergebnisse\        (NUR vom Prompt erzeugte Artefakte, z. B. StRS.md, SyRS.md, ...)

Die unabhängigen Variablen bilden die Ordnerebenen, nicht den Dateinamen:

  • <ModellID> – die an --model übergebene ID, z. B. claude-sonnet-5, claude-opus-5, claude-fable-5
  • <Agentenmodus> – solo, builtin oder custom
  • <Effort> – low, medium, high, xhigh oder max

Der Verzeichnisname trägt nur noch, was den einzelnen Lauf identifiziert:

  • <NN> – Nummernpräfix der Prompt-Datei (z. B. 01 bei 01_Prompt.md)
  • <yyyy-MM-dd_HHmmss> – Startzeit sekundengenau
  • <skillversion> – Version dieses Skills zum Startzeitpunkt, z. B. v3.10.0
  • <id4> – 4 Hexstellen Zufall; garantiert Eindeutigkeit auch bei gleichzeitigem Start

Warum Ordnerebenen statt Namensbestandteile: Der Name wuchs mit jeder neuen unabhängigen Variable weiter und war mit fünf Bestandteilen kaum noch lesbar. Als Ordnerebenen sind die Bedingungen navigierbar, je Zelle abzählbar (ls <modell>/<modus>/<effort> | wc -l ergibt unmittelbar die Anzahl der Messpunkte) und beim Hinzufügen einer weiteren Variable erweiterbar, ohne bestehende Namen zu brechen. Die Angaben sind redundant zum Protokoll – bei Widerspruch gilt das Protokoll.

Jeder Lauf ist vollständig selbstenthalten. Sämtliche Steuerdateien liegen in _meta\ innerhalb des Laufverzeichnisses – nicht im gemeinsamen Scratchpad. Das ist Voraussetzung für parallele Läufe (siehe „Parallele Läufe") und archiviert nebenbei den exakt gesendeten Prompt je Lauf. Ergebnisse\ enthält ausschließlich die vom Prompt geforderten Artefakte.

Ablauf

1. Vorbereitung

  1. Prompt-Datei lesen. Existiert sie nicht: abbrechen und den User informieren.

  2. Aus dem Metadaten-Block der Prompt-Datei (falls vorhanden) Versuch/Iteration übernehmen.

  3. CLI-Pfad auflösen. Unter Windows liegt claude in der Regel nicht im PATH. Erst Get-Command claude -ErrorAction SilentlyContinue versuchen; schlägt das fehl, auf die VSCode-Extension zurückfallen und die höchste Versionsnummer wählen:

    $claude = (Get-Command claude -ErrorAction SilentlyContinue).Source
    if (-not $claude) {
      $claude = Get-ChildItem "$env:USERPROFILE\.vscode\extensions\anthropic.claude-code-*-win32-x64\resources\native-binary\claude.exe" |
                Sort-Object FullName | Select-Object -Last 1 -ExpandProperty FullName
    }
    

    Findet sich keine ausführbare Datei: abbrechen und den User informieren. Den aufgelösten Pfad fürs Protokoll festhalten.

  4. Modell beim User erfragen. Hat der User das Modell nicht bereits im Aufruf genannt, immer per AskUserQuestion nachfragen – auch dann, wenn frühere Läufe derselben Versuchsreihe ein bestimmtes Modell verwendet haben. Es gibt bewusst keinen Default.

    Als Optionen die vollen Modell-IDs anbieten, nicht die Kurzformen:

    Modell-ID Einordnung
    claude-opus-5 stärkstes Modell, teuerster Lauf
    claude-sonnet-5 1-Mio.-Kontextfenster, für große Codebasen meist ausreichend
    claude-fable-5 schnell und günstig
    claude-haiku-4-5-20251001 günstigstes Modell

    In der Frage den letzten verwendeten Stand nennen, damit der User bewusst wechseln oder bewusst wiederholen kann (z. B. „Lauf 3 lief mit claude-sonnet-5, 11.516.200 Tokens, 23:40").

    Niemals die Kurzformen opus, sonnet, fable an --model übergeben. Sie lösen auf das jeweils neueste Modell auf und verschieben sich über die Zeit – damit wäre die Versuchsbedingung nicht reproduzierbar. Für ein 1-Mio.-Token-Fenster die Variante mit [1m]-Suffix wählen (z. B. claude-opus-5[1m]).

    Weicht das gewählte Modell vom letzten Lauf ab, im Protokoll unter „Anmerkungen" als geänderte Versuchsbedingung vermerken und in der Änderungshistorie des Skills ergänzen.

  5. Agentenmodus beim User erfragen. Wie beim Modell: kein Default, immer nachfragen, wenn der User den Modus nicht bereits im Aufruf genannt hat. Der Modus ist die zentrale Unterscheidung zwischen den Versuchen der Arbeit.

    Modus Versuch Bedeutung
    solo V1 Ein Thread, ein Kontext. Der Lauf darf keine Subagenten starten.
    builtin V1b Eingebaute Subagenten erlaubt (Explore, general-purpose).
    custom V2 Nur vordefinierte, geprompte Agenten aus --agents.

    Flags je Modus – zusätzlich zur Standardkonfiguration aus Abschnitt 2:

    switch ($modus) {
      'solo'    { $agentFlags = @('--disallowedTools','Task','Agent','Workflow') }
      'builtin' { $agentFlags = @() }
      'custom'  { $agentFlags = @('--agents', (Get-Content $agentDatei -Raw)) }
    }
    

    Warum Task, Agent und Workflow: Welchen Namen das Subagenten-Werkzeug in der jeweiligen CLI-Version trägt, ist nicht dokumentiert – im Binary von 2.1.245 kommen Task und Agent vor; beide zu sperren ist unschädlich, ein nicht existierender Name läuft ins Leere. Workflow orchestriert ebenfalls Subagenten und muss mitgesperrt werden: Im Verifikationstest (2026-08-25, CLI 2.1.245) wich der Agent nach der Sperre von Task/Agent genau darauf aus. Verifiziert wurden spawned: 0, die Antwort „KEINE SUBAGENTEN MOEGLICH" und ein Denial auf Workflow. Kontrolle nach dem Lauf: subagent_stats.spawned muss im Modus solo genau 0 sein – andernfalls hat die Sperre nicht gegriffen und der Lauf ist als Fehlmessung zu kennzeichnen.

    Im Modus solo sind Permission-Denials auf Task/Agent erwartbar, wenn der Agent zu delegieren versucht. Sie sind im Protokoll getrennt von sonstigen Denials auszuweisen und nicht als Einschränkung der Werkzeugkonfiguration zu werten – sie sind die Bedingung selbst.

    Für custom (V2): Die Agentendefinitionen liegen als JSON-Datei neben der Prompt-Datei (z. B. Versuche/Versuch_02/02_Agents.json), nicht im Codebasis-Snapshot. Sie werden wie der Prompt per SHA-256 gehasht und im Protokoll geführt. So bleibt der eingefrorene Snapshot unangetastet und die Agentenkonfiguration ist eine dokumentierte, versionierte Versuchsbedingung. Format siehe claude --help zu --agents.

  6. Effort beim User erfragen. Kein Default, immer nachfragen, wenn der User die Stufe nicht bereits im Aufruf genannt hat. Stufen: low, medium, high, xhigh, max. Übergabe per --effort <stufe>.

    In der Frage den bisherigen Stand nennen. Alle Läufe bis einschließlich Lauf B liefen auf high – geerbt aus der Sitzungseinstellung, nicht bewusst gesetzt; der Wert wurde nachträglich aus den Transkripten belegt. Wer die Stufe wechselt, ändert die Versuchsbedingung und macht den Lauf mit den bisherigen unvergleichbar.

    Wichtig – der Effort ist aus RawResult.json nicht rekonstruierbar. Das Ergebnisobjekt enthält kein effort-Feld. Nur das Session-Transkript hält ihn je Nachricht fest ("effort": "high"). Fehlt er im Protokoll, ist die Bedingung nachträglich allein über das Transkript belegbar – und das nur, solange die Session persistiert ist.

  7. Messgrößen VOR dem Lauf erfassen (PowerShell):

    • Startzeit: Get-Date -Format o
    • SHA-256 der Prompt-Datei: (Get-FileHash <datei> -Algorithm SHA256).Hash
    • Claude-Code-Version: & $claude --version
    • Git-Zustand des Root-Verzeichnisses: git -C <root> rev-parse HEAD und git -C <root> status --porcelain (dirty ja/nein)
    • Git-Commit dieses Repos (Stand der Prompt-Datei): git rev-parse HEAD
  8. Kollisionsfreies Laufverzeichnis anlegen. Sekundengenau, mit Agentenmodus und Zufalls-ID; bei Namenskollision neu würfeln:

    # Bedingungen werden Ordnerebenen, nicht Namensbestandteile
    $zelle = Join-Path (Join-Path $modell $modus) $effort
    $skillVer = 'v3.10.0'   # entspricht version: im Frontmatter dieses Skills
    do {
      $id4  = '{0:x4}' -f (Get-Random -Maximum 65536)
      $lauf = Join-Path "<promptverzeichnis>\$zelle" "<NN>_Lauf_$(Get-Date -Format 'yyyy-MM-dd_HHmmss')_${skillVer}-$id4"
    } while (Test-Path $lauf)
    New-Item -ItemType Directory -Force "$lauf\Ergebnisse" | Out-Null
    New-Item -ItemType Directory -Force "$lauf\_meta"      | Out-Null
    
  9. Dateibestand des Roots vor dem Lauf sichern – das Root soll unverändert bleiben, jede Änderung dort ist eine Auffälligkeit fürs Protokoll. Ziel ist _meta\ im Laufverzeichnis, nicht der gemeinsame Scratchpad:

    # Leerwertsicher: -Value erzwingt das Schreiben auch bei sauberem Root.
    Set-Content -Path "$lauf\_meta\before.txt" -Value (git -C <root> status --porcelain | Out-String)
    

    Nicht git ... | Set-Content <datei> verwenden: Ist die Pipeline leer (sauberes Root), schreibt Set-Content die Datei nicht und lässt einen alten Inhalt stehen. Der Vorher/Nachher-Vergleich meldet dann eine Abweichung, die es nicht gibt. (Kein Git-Repo? Dann rekursive Dateiliste mit LastWriteTime nach _meta\ schreiben.)

Isolation: Die Codebasis ist ein eingefrorener Snapshot ohne KI-Konfigurationen. Der Untersuchungsgegenstand wurde einmalig um alle KI-Assistenz-Konfigurationen bereinigt (.claude/, .agents/, .codex/, .cursor/, .serena/, .opencode/, .memory-mcp/, CLAUDE.md, AGENTS.md, .mcp.json, opencode.json, skills-lock.json, .coderabbit.yaml, .aiignore, .claudeignore, .cursorignore), und das GitHub-Remote ist entkoppelt. Die Bedingung „keine Agentendateien, keine MCP-Server" ist damit eine Eigenschaft des Snapshots und muss nicht pro Lauf hergestellt werden. Damit entfällt jeder destruktive Vorbereitungsschritt.

Vor jedem Lauf den Snapshot prüfen – nicht bereinigen:

$muster = 'CLAUDE\.md|AGENTS\.md|GEMINI\.md|\.mcp\.json|opencode\.json|skills-lock\.json|' +
          '\.coderabbit\.yaml|\.aiignore|\.claudeignore|\.cursorignore|copilot-instructions|' +
          '^\.(claude|agents|codex|cursor|serena|opencode|memory-mcp|continue|gemini|windsurf)/'
$fund = git -C <root> ls-files | Select-String -Pattern $muster
if ($fund) { "WARNUNG: KI-Konfigurationen im Snapshot:"; $fund }

Den Regex nicht „vereinfachen". Die Anker ((^|/), $, führender Punkt) sind notwendig. Select-String arbeitet in PowerShell standardmäßig case-insensitiv; ein gelockertes Muster schlägt deshalb auf echte Produktdateien an. In dieser Codebasis etwa: src/backend/Centron.BL/ArtificialIntelligence/Chat/ClaudeCodeChatModelClient.cs und GoogleGeminiChatModelClient.cs – Bestandteile des KI-Assistenz-Features der ERP-Suite und damit legitimer Untersuchungsgegenstand, keine Werkzeugkonfiguration. Bei einem Treffer immer erst die konkreten Pfade ansehen, bevor Alarm ausgelöst wird.

Findet die Prüfung echte Treffer: abbrechen und den User informieren – nicht eigenmächtig löschen. Der Codebasis-Snapshot ist ein Messinstrument. Eine Änderung daran ist eine Änderung der Versuchsbedingung und macht Läufe untereinander unvergleichbar; sie gehört abgestimmt, committet und im Protokoll dokumentiert.

Das Remote ist entkoppelt. Im Codebasis-Repo wird niemals gepusht, gefetcht oder ein Remote hinzugefügt. Der Snapshot bleibt eingefroren.

2. Ausführung (Headless-Lauf)

Dem Prompt eine Ausgabe-Anweisung anhängen, damit die Ergebnisse im Laufverzeichnis landen und nicht im Root. Dazu den Prompttext um einen Abschnitt ergänzen (Prompt-Datei selbst NICHT verändern – nur den per stdin übergebenen Text):

### Ausgabeverzeichnis (überschreibt anderslautende Pfadangaben oben)
Schreibe ALLE zu erzeugenden Ergebnisdateien in das Verzeichnis
`<absoluter Pfad zum Laufverzeichnis>\Ergebnisse\`.
Verändere keine Dateien im Arbeitsverzeichnis (der analysierten Codebasis).

Dann den kombinierten Prompt per stdin an claude -p übergeben. --add-dir gibt dem Headless-Lauf Schreibrecht auf das Laufverzeichnis außerhalb seines Arbeitsverzeichnisses. Versuchsläufe können lange dauern – immer als Background-Task starten (run_in_background), nicht mit Foreground-Timeout arbeiten:

$lauf   = "<absoluter Pfad zum Laufverzeichnis>"
$prompt = (Get-Content "<prompt-datei>" -Raw) + "`n`n<Ausgabe-Anweisung>"
# Steuerdateien IMMER ins Laufverzeichnis - nie in den gemeinsamen Scratchpad (parallelfaehig)
Set-Content -Path "$lauf\_meta\combined_prompt.md" -Value $prompt -Encoding utf8
Set-Content -Path "$lauf\_meta\startzeit.txt" -Value (Get-Date -Format o)

# Schreibende und bauende Shell-Kommandos sperren – die Codebasis wird nur gelesen.
$denyBash = @(
  'Bash(rm:*)','Bash(rmdir:*)','Bash(mv:*)','Bash(cp:*)','Bash(dd:*)',
  'Bash(truncate:*)','Bash(chmod:*)','Bash(chown:*)','Bash(ln:*)','Bash(tee:*)',
  'Bash(sed -i:*)','Bash(git checkout:*)','Bash(git restore:*)','Bash(git clean:*)',
  'Bash(git reset:*)','Bash(git add:*)','Bash(git commit:*)','Bash(git push:*)',
  'Bash(dotnet:*)','Bash(msbuild:*)','Bash(npm install:*)','Bash(nuget:*)'
)
$denyPs = @(
  'PowerShell(Remove-Item:*)','PowerShell(Move-Item:*)','PowerShell(Copy-Item:*)',
  'PowerShell(New-Item:*)','PowerShell(Set-Content:*)','PowerShell(Add-Content:*)',
  'PowerShell(Clear-Content:*)','PowerShell(Out-File:*)','PowerShell(Set-ItemProperty:*)',
  'PowerShell(dotnet:*)','PowerShell(msbuild:*)'
)

Set-Location "<root>"
Get-Content "$lauf\_meta\combined_prompt.md" -Raw |
  & $claude -p `
    --output-format json `
    --safe-mode `
    --strict-mcp-config `
    --permission-mode acceptEdits `
    --allowedTools "Bash" "PowerShell" `
    --disallowedTools @($denyBash + $denyPs) `
    --model <vom User gewaehlte Modell-ID aus Schritt 4> `
    --effort <vom User gewaehlte Stufe aus Schritt 6> `
    @agentFlags `
    --add-dir "$lauf" `
    2> "$lauf\Stderr.log" | Set-Content "$lauf\RawResult.json"
Set-Content -Path "$lauf\_meta\endzeit.txt" -Value (Get-Date -Format o)

Bedeutung der Flags:

Flag Zweck
--safe-mode Isolation: CLAUDE.md, Skills, Plugins, Hooks, MCP-Server, Custom-Agenten, Commands und Output-Styles aus – ohne Dateieingriff. Auth, Modellwahl, eingebaute Tools und Permissions bleiben normal aktiv.
--strict-mcp-config zweite Absicherung gegen MCP-Server aus Projekt- oder User-Konfiguration
--permission-mode acceptEdits Schreibrechte für die Ergebnisdateien im Laufverzeichnis
--allowedTools "Bash" "PowerShell" Shell-Zugriff ohne Rückfrage – Standard seit Iteration 02
--disallowedTools <Denylist> schreibende und bauende Kommandos gesperrt; Deny hat Vorrang vor Allow
--add-dir "$lauf" Schreibziel außerhalb des Arbeitsverzeichnisses
@agentFlags Agentenmodus aus Schritt 5: solo sperrt Task/Agent, builtin fügt nichts hinzu, custom übergibt --agents
--effort <stufe> Denkaufwand aus Schritt 6; nicht aus RawResult.json rekonstruierbar, daher zwingend ins Protokoll
--model <id> exakte Modellbindung aus Schritt 4; überschreibt die Modellpräferenz der User-Settings. Volle ID, keine Kurzform.

Build-Kommandos (dotnet, msbuild, nuget, npm install) stehen bewusst auf der Denylist: Sie würden bin/- und obj/-Artefakte im Root erzeugen und widersprechen der Methodenvorgabe „statische Analyse, keine Ausführung".

Grenzen der Denylist – ehrlich einordnen. Pattern-Matching auf Shell-Kommandos ist nicht lückenlos; Umleitungen, Pipes und verschachtelte Aufrufe lassen sich nicht vollständig abfangen. Die belastbare Read-only-Garantie bleibt der Vorher/Nachher-Vergleich per git status --porcelain aus Abschnitt 1 bzw. 3. Die Denylist senkt das Risiko, sie ersetzt die Verifikation nicht.

--safe-mode bleibt als zweite Sicherung aktiv. Die primäre Isolation leistet der bereinigte Snapshot (Abschnitt 1); --safe-mode fängt zusätzlich alles ab, was von außerhalb des Roots wirken könnte – User-Level-Settings, global installierte Skills, Plugins, Hooks.

Verifiziert am 2026-08-25 gegen Version 2.1.245, dokumentiert als Begründung für den Snapshot-Ansatz:

  • --safe-mode verhindert zuverlässig das Vorladen von CLAUDE.md/AGENTS.md als Systemanweisung. Kontrolltest ohne Werkzeuge: mit --safe-mode antwortet der Agent „NICHTS VORGELADEN", ohne das Flag zitiert er den Inhalt der CLAUDE.md.
  • --safe-mode verhindert nicht, dass der Agent solche Dateien als gewöhnliche Dateien findet und liest. Im Smoke-Test mit Shell-Zugriff hat er genau das getan und den Inhalt von AGENTS.md und CLAUDE.md wiedergegeben.

Genau deshalb reicht --safe-mode allein bei gewährtem Shell-Zugriff nicht aus, und die KI-Konfigurationen wurden aus dem Snapshot entfernt statt nur deaktiviert.

Trust-Hinweis auf stderr. Liegt im Root eine .claude/settings.json mit permissions.allow-Einträgen, meldet die CLI auf stderr sinngemäß „Ignoring N permissions.allow entries … this workspace has not been trusted". Im bereinigten Snapshot tritt das nicht mehr auf; erscheint die Meldung dennoch, ist der Snapshot nicht sauber – Abschnitt 1 prüfen.

Regeln:

  • Arbeitsverzeichnis des Befehls = Root-Verzeichnis des Versuchs; geschrieben wird ausschließlich ins Laufverzeichnis.
  • Treten unerwartete Permission-Denials auf, die den Lauf behindern: die Denylist prüfen und die Abweichung im Protokoll dokumentieren – nicht pauschal alle Prüfungen per --dangerously-skip-permissions abschalten. Eine Änderung der Werkzeugkonfiguration ist eine Änderung der Versuchsbedingung und gehört mit dem User abgestimmt.
  • Optional --max-budget-usd <betrag> als harte Obergrenze setzen (nur mit -p wirksam) und den Wert im Protokoll notieren. Das Flag arbeitet nur in USD – die berichtete Messgröße bleibt der Tokenverbrauch. Anhaltspunkt: Der bisher aufwendigste Lauf verbrauchte 55.167.397 Tokens.
  • Nach Abschluss des Background-Tasks: Endzeit mit Get-Date -Format o erfassen.

3. Ergebnis auswerten

RawResult.json im Laufverzeichnis lesen und defensiv parsen (Feldnamen können je nach Claude-Code-Version leicht abweichen). Relevante Felder:

Feld Bedeutung
is_error, subtype Lauf erfolgreich oder abgebrochen
duration_ms, duration_api_ms Gesamt- und reine API-Dauer
num_turns Anzahl Agent-Turns (Proxy für Werkzeugaktivität)
total_cost_usd Kosten in USD – wird nicht berichtet, bleibt aber als Rohwert in der Datei
usage.input_tokens, usage.output_tokens Tokens nur des Hauptagenten
usage.cache_creation_input_tokens, usage.cache_read_input_tokens Cache-Tokens (getrennt ausweisen!)
modelUsage bzw. model tatsächlich eingesetzte Modell-ID(s), Verbrauch inklusive aller Subagenten-Ebenen
permission_denials verweigerte Werkzeugaufrufe – Anzahl und Aufschlüsselung nach tool_name
subagent_stats gestartete Subagenten: spawned, by_type, completed, failed, max_depth
session_id für spätere Transcript-Analyse (claude --resume <id>)
result Abschlusstext des Agenten

modelUsage erfasst alle Verschachtelungsebenen – empirisch verifiziert. Kontrolltest am 2026-08-25 gegen CLI 2.1.245: Eine erzwungene Kaskade (max_depth: 2, spawned: 2, spawned_by_subagents: 1), bei der ausschließlich der Enkel-Agent auf Tiefe 2 arbeitete – er las 15 große Quelldateien, der mittlere Agent reichte nur durch, der Hauptagent las nichts:

Tokens
usage (nur Hauptagent, 1 Turn) 49.103
modelUsage (gesamt) 1.689.288
Differenz = Subagenten 1.640.185 (Faktor 34,4)

Da die gesamte Leseleistung auf Tiefe 2 stattfand, belegt die Differenz, dass auch Sub-Subagenten in modelUsage einfließen. Für die berichtete Aufwandsgröße „Tokens gesamt" ist modelUsage daher die vollständige und einzig richtige Quelle.

Subagenten-Transkripte werden nicht separat persistiert. Im Projektverzeichnis liegt je Lauf genau eine .jsonl-Datei, und Subagenten-Nachrichten erscheinen darin nicht als Sidechain. Ihr Verbrauch ist deshalb ausschließlich über modelUsage sichtbar, nicht über das Transkript – und die Summe der Transkript-Nachrichten ist kein gültiges Verbrauchsmaß (sie zählt Cache-Reads über Turns hinweg mehrfach).

Zwei Auswertungsfallen:

  • usage erfasst ausschließlich den Hauptagenten. Für den abrechnungsrelevanten Gesamtverbrauch ist modelUsage über alle Modell-IDs zu summieren. In Iteration 01 standen 105.959 Output-Tokens in usage gegenüber 249.040 in modelUsage.
  • duration_api_ms kann die Wanduhrzeit übersteigen, wenn Subagenten parallel laufen (Iteration 01: 47:05 API gegenüber 31:31 Wanduhr). Das ist kein Widerspruch, sondern die Summe nebenläufiger Anfragen – im Protokoll entsprechend einordnen.

Pflichtprüfung: tatsächlich eingesetzte Modelle. Nach jedem Lauf die Schlüssel von modelUsage gegen das angeforderte Modell abgleichen. Zulässig sind nur die angeforderte Modell-ID und claude-haiku-4-5-* (interne Hilfsaufrufe, wenige tausend Tokens). Taucht ein weiteres Modell auf, ist die Versuchsbedingung verletzt – der Lauf ist im Protokoll als solcher zu kennzeichnen und für Modellvergleiche unbrauchbar.

--model steuert nur den Hauptagenten, nicht zwingend die Subagenten. Belegt am 2026-08-25 (CLI 2.1.245, Lauf fable5_builtin_ehigh_v3.7.0-15db): Mit --model claude-fable-5 und Modus builtin liefen die 13 Subagenten auf claude-opus-5[1m] – dem Standardmodell aus ~/.claude/settings.json. Auf sie entfielen 136,7 von 150,3 Mio. Tokens (91 %).

Kombination Läufe Modelle in modelUsage
Sonnet / Opus / Fable + solo 12 nur das angeforderte Modell (+ Haiku)
Sonnet + builtin 11 nur claude-sonnet-5 (+ Haiku)
Fable + builtin 1 Fable + claude-opus-5[1m]

Sonnet und Opus werden an die Subagenten durchgereicht, Fable nicht; Claude Code fällt dann auf die Sitzungsvorgabe zurück. --safe-mode verhindert das nicht – es deaktiviert Customizations, nicht die Modellwahl. Im Modus solo tritt das Problem nicht auf, weil es keine Subagenten gibt.

Bei Modus builtin oder custom daher nie den Flag-Wert allein ins Protokoll schreiben, sondern die Modelle aus modelUsage mit ihrem jeweiligen Anteil ausweisen.

permission_denials ist eine reguläre Messgröße und immer auszuweisen, auch bei 0. Ein hoher Wert bedeutet, dass die Werkzeugkonfiguration den Lauf eingeschränkt hat, und ist bei der Interpretation der Ergebnisqualität zu berücksichtigen.

Subagenten-Prompts sichern (entfällt nur im Modus solo, dort gibt es keine). Die vollständigen Prompts, mit denen der Hauptagent seine Subagenten beauftragt hat, stehen im persistierten Session-Transkript unter %USERPROFILE%\.claude\projects\<projekt>\<session_id>.jsonl. Das mitgelieferte Skript extrahiert sie:

python "<skillverzeichnis>\extract-subagenten.py" "<laufverzeichnis>"

Es schreibt _meta\subagenten.md (lesbar, mit vollständigem Prompt je Subagent) und _meta\subagenten.json (maschinenlesbar). Erfasst werden Werkzeug (Task/Agent), subagent_type, description, Hintergrund-Flag, Prompt-Länge und Länge des zurückgelieferten Ergebnisses.

Plausibilitätskontrolle: Das Skript vergleicht die gefundene Anzahl mit subagent_stats.spawned minus spawned_by_subagents. Im Haupttranskript stehen nämlich nur die direkt vom Hauptagenten gestarteten Subagenten – von Subagenten gestartete (max_depth > 1) liegen in deren eigenen Transkripten. Bei Abweichung setzt das Skript eine Warnung in subagenten.md; dann ist die Ursache zu klären, bevor die Prompts ausgewertet werden.

Warum das erhoben wird: In V1b bestimmt der Agent selbst, wie er die Analyse zerlegt – über alle bisherigen Läufe schwankte das zwischen 0 und 14 Subagenten mit völlig unterschiedlichen Zuschnitten. Diese selbstgewählte Zerlegung ist die dominierende Störgröße der Versuchsreihe. Erst die protokollierten Prompts machen sie als Datum auswertbar statt nur als Zahl sichtbar. Für V2 (custom) sind sie zusätzlich der Vergleichsmaßstab: Sie zeigen, wie der Agent ohne Vorgabe delegiert – gegenüber den vorformulierten Agenten aus --agents.

Anforderungen auswerten – der inhaltliche Ertrag des Laufs, nicht nur sein Aufwand:

python "<skillverzeichnis>nalyse-anforderungen.py" "<laufverzeichnis>"

Das Skript parst das im Prompt vorgegebene Blockformat (ID:, Typ:, Belege:, Status: …) aus Ergebnisse\StRS.md, SyRS.md und SwRS.md und schreibt _metanforderungen.md (fertiger Protokollabschnitt) sowie _metanforderungen.json (maschinenlesbar). Erhoben werden:

  • Verteilung über die drei Ebenen
  • Anforderungstypen (funktional, Sicherheit, Daten, Schnittstelle …)
  • Belegqualität: Anzahl der Belege, Aufteilung PRIMÄR/SEKUNDÄR/KONTEXT, Median je Anforderung, Anteil mit mindestens einem Primärbeleg
  • Status: belegt, [HYPOTHESE], Workaround, Konsolidierungskandidaten
  • Regelkonformität – geprüft wird gegen die Vorgaben des Prompts selbst: Belegpflicht (jede Anforderung ≥ 1 Beleg), risikobasierte Priorisierung (Sicherheit, Abrechnung, Berechtigungen brauchen PRIMÄR oder [HYPOTHESE]), Verifizierbarkeit (Prüfidee vorhanden), Traceability (Tracelinks gesetzt)

Warum das erhoben wird: Die Anforderungsanzahl allein ist als Qualitätsmaß wertlos – sie streute über Läufe gleicher Bedingung um Faktor 5,9. Belegdichte, Primärbelegquote und Regelverstöße sind dagegen inhaltliche Größen und machen Läufe vergleichbar, deren Mengengerüst weit auseinanderliegt. Die Regelkonformitätsprüfung deckt zudem auf, wo der Agent die eigenen Vorgaben des Prompts verfehlt hat – ein Befund, der sich sonst nur durch Handlektüre ergäbe.

Der erzeugte Abschnitt wird unverändert als ## Gefundene Anforderungen ins Protokoll übernommen, zwischen ## Ergebnis und den Vergleichs- bzw. Anmerkungsabschnitten.

Erzeugte Dateien: Inhalt von <laufverzeichnis>\Ergebnisse\ auflisten. Zusätzlich prüfen, ob das Root unverändert blieb: git -C <root> status --porcelain gegen before.txt vergleichen (Nachher-Stand nach $lauf\_metafter.txt) – Abweichungen als Auffälligkeit ins Protokoll. Beim Vergleich Zeilenenden normalisieren (before.txt entsteht je nach Werkzeug mit CRLF, der Nachher-Stand mit LF), sonst meldet ein naiver diff alle Zeilen als geändert.

4. Messprotokoll schreiben

Als Protokoll.md ins Laufverzeichnis, neben RawResult.json und Stderr.log.

Vorlage:

# Messprotokoll – <Versuch> – Iteration <NN>

## Lauf
- **Prompt-Datei:** <relativer Pfad>
- **SHA-256 (Prompt):** <hash>
- **Startzeit:** <ISO 8601>
- **Endzeit:** <ISO 8601>
- **Dauer gesamt:** <hh:mm:ss> (API: <hh:mm:ss>)
- **Root-Verzeichnis:** <Pfad>
- **Codebasis-Commit:** <hash> (dirty: ja/nein)
- **Snapshot-Zustand:** <bereinigt von KI-Konfigurationen: ja/nein; Remote entkoppelt: ja/nein>
- **Prompt-Repo-Commit:** <hash>

## Werkzeugkonfiguration
- **Skill-Version:** <version aus dem Frontmatter dieses Skills>
- **Claude-Code-Version:** <version>
- **CLI-Pfad:** <aufgelöster Pfad zur claude.exe>
- **Modell (angefordert):** <Wert von `--model`>
- **Modelle (tatsächlich eingesetzt):** <alle Schlüssel aus `modelUsage` mit Tokenanteil>
- **Kontrolle Modell:** <bestanden | **verletzt**: nicht angefordertes Modell <ID> mit <N> Tokens>
- **Effort:** <low | medium | high | xhigh | max> (per `--effort` gesetzt; Gegenprobe im
  Transkript-Feld `effort`)
- **Laufverzeichnis-ID:** `v<skillversion>-<id4>` aus dem Verzeichnisnamen
- **Ablage:** `<ModellID>/<Agentenmodus>/<Effort>/`
- **Parallele Läufe:** <nein | ja: welche Laufverzeichnisse liefen zeitgleich>
- **Agentenmodus:** <solo (V1) | builtin (V1b) | custom (V2)>; bei `custom` zusätzlich
  Pfad und SHA-256 der Agentendefinitionen
- **Permission-Mode:** <acceptEdits | ...>
- **Toolfreigabe:** `--allowedTools <wörtlich>` / `--disallowedTools <wörtlich>`
- **Isolationsmechanismus:** <--safe-mode, --strict-mcp-config, ggf. --setting-sources>
- **MCP-Server / Agentendateien:** <keine – aus dem Snapshot entfernt, zusätzlich --safe-mode | Liste>
- **Subagenten:** <Anzahl und Typ aus `subagent_stats`, z. B. 8 × Explore, 0 fehlgeschlagen>
- **Verschachtelung:** `spawned` = <N>, davon `spawned_by_subagents` = <M>, `max_depth` = <D>.
  Bei `max_depth` > 1 ausdrücklich vermerken – die Tokens der tieferen Ebenen sind in
  „Tokens gesamt" enthalten, ihre Prompts jedoch **nicht** in `_meta\subagenten.md`

## Verbrauch

### Hauptagent (`usage`)
| Messgröße | Wert |
|---|---|
| Input-Tokens | |
| Output-Tokens | <Wert> (davon N Thinking-Tokens aus `usage.output_tokens_details`) |
| Cache-Write-Tokens | |
| Cache-Read-Tokens | |
| Agent-Turns | |

### Gesamtlauf inkl. Subagenten (`modelUsage`, abrechnungsrelevant)
| Messgröße | <Modell-ID> | <weitere Modell-ID> | Summe |
|---|---:|---:|---:|
| Input-Tokens | | | |
| Output-Tokens | | | |
| Cache-Write-Tokens | | | |
| Cache-Read-Tokens | | | |
| **Tokens gesamt** | | | |

**Tokens gesamt: <Summe>** — Input + Output + Cache-Write + Cache-Read über alle Modelle.
Das ist die **berichtete Aufwandsgröße** der Versuchsreihe. `total_cost_usd` bleibt unberührt in
`RawResult.json` erhalten, wird aber nicht ins Protokoll übernommen: Token sind modell- und
preisunabhängig und bleiben damit über Preisänderungen und Modellwechsel hinweg vergleichbar.

## Gefundene Anforderungen

<unverändert aus `_metanforderungen.md` übernehmen – Verteilung, Typen, Belegqualität,
Status, Regelkonformität>

## Ergebnis
- **Status:** <erfolgreich | Fehler: ...>
- **Session-ID:** <id>
- **Permission-Denials:** <Anzahl> (<Aufschlüsselung nach Tool>; bei keinem Denial: 0).
  Im Modus `solo` Denials auf `Task`/`Agent` **getrennt** ausweisen – sie sind die
  Versuchsbedingung, keine Einschränkung.
- **Kontrolle Agentenmodus:** `subagent_stats.spawned` = <Zahl> (bei `solo` muss 0 stehen,
  sonst Fehlmessung)
- **Subagenten-Prompts:** <`_meta\subagenten.md`, N Aufrufe erfasst | entfällt (Modus solo)>
- **Erzeugte Dateien:** <Liste aus Ergebnisse\>
- **Root unverändert:** <ja | nein: welche Abweichungen>
- **Abschlusstext des Agenten:** siehe RawResult.json (`result`)
- **Anmerkungen/Auffälligkeiten:** <Beobachtungen, Abbrüche, manuelle Eingriffe>

5. Abschlussbericht an den User

Kurz zusammenfassen: Status, Dauer, Tokenverbrauch (inkl. Cache), Modell, Pfad des Laufverzeichnisses und welche Dateien der Lauf erzeugt hat. Bei is_error oder leerem Ergebnis: Stderr.log und RawResult.json zitieren, nicht spekulieren.

Randbedingungen

  • Niemals Messwerte schätzen oder erfinden – fehlt ein Feld im JSON, im Protokoll als nicht erfasst eintragen.
  • Prompt-Datei unverändert lassen; das Protokoll ist eine neue Datei.
  • Läuft der Background-Task ungewöhnlich lange, User informieren statt abbrechen.
  • Am Codebasis-Root wird nichts verändert – weder zur Vorbereitung noch zur Isolation noch zur Nachbereitung. Ist das Root vor dem Lauf bereits dirty, den Zustand im Protokoll festhalten und den User informieren, statt ihn stillschweigend zu bereinigen.
  • Der Codebasis-Snapshot ist eingefroren. Kein push, kein fetch, kein Hinzufügen eines Remotes, kein Commit im Codebasis-Repo. Soll der Snapshot geändert werden (etwa weil eine weitere KI-Konfiguration auftaucht), ist das mit dem User abzustimmen, als eigener Commit festzuschreiben und in allen betroffenen Protokollen als geänderte Versuchsbedingung zu vermerken.
  • Werkzeugkonfiguration ist eine unabhängige Variable. Weicht ein Lauf von der hier festgelegten Standardkonfiguration ab (andere Flags, anderer Permission-Mode, zusätzliche Tools), ist das im Protokoll unter „Werkzeugkonfiguration" wörtlich zu dokumentieren – sonst sind die Läufe nicht vergleichbar.

Versionierung

Die aktuelle Version steht im Frontmatter (version:) und muss in jedes Protokoll unter „Werkzeugkonfiguration" als Skill-Version eingetragen werden. Nur so lässt sich später zuordnen, unter welcher Fassung des Versuchsaufbaus eine Messung entstanden ist.

Schema (Semantic Versioning):

Stelle Bedeutung Folge für die Vergleichbarkeit
MAJOR Änderung der Versuchsbedingung – Flags, Toolfreigabe, Isolationsmechanismus, Codebasis-Snapshot Läufe verschiedener MAJOR-Versionen sind nicht direkt vergleichbar
MINOR Neue Pflichtschritte oder Messgrößen ohne Änderung der Versuchsbedingung Läufe bleiben vergleichbar; die Protokolle werden reichhaltiger
PATCH Fehlerkorrekturen am Ablauf, Dokumentation, Klarstellungen Ohne Einfluss auf die Messung

Regel: Wer den Skill ändert, erhöht die Version im Frontmatter und ergänzt eine Zeile in der Historie unten – im selben Arbeitsschritt.

Änderungshistorie

Version Änderung Grund Verwendet in
1.0.0 Ausgangsfassung: --permission-mode acceptEdits, kein Shell-Zugriff; Isolation durch Löschen der KI-Konfigurationsdateien im Root vor dem Lauf und git restore danach Erstaufsetzung des Versuchsaufbaus Lauf 1 (01_Lauf_2026-08-25_1228)
2.0.0 --allowedTools "Bash" "PowerShell" + 33er-Denylist für schreibende und bauende Kommandos. Isolation über eingefrorenen Codebasis-Snapshot ohne KI-Konfigurationen (Commit 79c1142, Parent 89ccfd6, GitHub-Remote entkoppelt), zusätzlich --safe-mode und --strict-mcp-config. Der destruktive Lösch-/Restore-Schritt pro Lauf entfällt. permission_denials und subagent_stats werden reguläre Messgrößen; Verbrauchstabelle trennt Hauptagent und Gesamtlauf. CLI-Pfad-Auflösung als eigener Schritt. Lauf 1 erzeugte 36 Permission-Denials (32 × Bash, 4 × PowerShell); Shell-gestützte Verzeichnisinventuren fehlten dem Agenten. --safe-mode allein genügt nicht: Es unterdrückt das Vorladen von CLAUDE.md/AGENTS.md, verhindert aber nicht, dass der Agent sie mit Shell-Zugriff selbst liest – im Smoke-Test nachgewiesen. Lauf 2 (01_Lauf_2026-08-25_1349, API-Abbruch)
2.0.1 before.txt wird leerwertsicher geschrieben (Set-Content -Value (… | Out-String) statt Pipeline) Bei sauberem Root schreibt Set-Content aus leerer Pipeline die Datei nicht und lässt alten Inhalt stehen; der Vorher/Nachher-Vergleich meldete dadurch eine Abweichung, die es nicht gab Lauf 3 (01_Lauf_2026-08-25_1429)
2.1.0 Modell wird vor jedem Lauf beim User erfragt (Pflichtparameter, kein Default); Kurzformen opus/sonnet/fable untersagt Das Modell ist eine unabhängige Variable und wurde bis dahin ad hoc gewählt. Kurzformen lösen auf das jeweils neueste Modell auf und verschieben die Versuchsbedingung über die Zeit. Lauf 4 (01_Lauf_2026-08-25_1505)
2.1.1 Warnung zur Snapshot-Prüfung: Regex nicht vereinfachen, Select-String ist case-insensitiv; Beispiel-Falschtreffer dokumentiert Ein verkürztes Muster sprach auf echte Produktdateien an (ClaudeCodeChatModelClient.cs, GoogleGeminiChatModelClient.cs – KI-Assistenz-Feature der ERP-Suite) und hätte beinahe einen Fehlabbruch ausgelöst –
3.0.0 Agentenmodus als Pflichtparameter (solo / builtin / custom), vor jedem Lauf beim User erfragt. solo sperrt Task/Agent, custom übergibt vordefinierte Agenten per --agents. Neue Protokollfelder: Agentenmodus und Kontrolle subagent_stats.spawned. Der Subagenten-Einsatz schwankte bei identischem Prompt zwischen 0 und 14 und war damit die dominierende Störgröße: Drei Läufe unter sonst identischer Bedingung ergaben 55 / 106 / 325 Anforderungen und 27,6 / 11,5 / 52,7 Mio. Tokens (Faktor 5,9 bzw. 4,6). Ohne Festlegung des Modus ist keine Bedingung sauber messbar. ab Versuch 1 neu
3.1.0 Parallelfähigkeit: Laufverzeichnis sekundengenau plus Modus und 4-stellige Zufalls-ID; alle Steuerdateien nach _meta\ im Laufverzeichnis statt in den gemeinsamen Scratchpad; neue Protokollfelder „Laufverzeichnis-ID" und „Parallele Läufe"; Abschnitt zu den messtechnischen Grenzen des Parallelbetriebs Minutengenaue Namen kollidieren bei zwei Starts in derselben Minute, und geteilte Scratchpad-Dateien (before.txt, combined_prompt.md, Zeitstempel) hätten sich zwischen parallelen Läufen gegenseitig überschrieben. Nebeneffekt: Der exakt gesendete Prompt ist nun je Lauf archiviert. –
3.2.0 Verzeichnisname enthält zusätzlich Modell-Kurzform und Skill-Version: <NN>_Lauf_<yyyy-MM-dd_HHmmss>_<modell>_<modus>_v<skillversion>-<id4>. Solo-Modus sperrt zusätzlich Workflow. Modell, Modus und Skill-Version sind die unabhängigen Variablen der Reihe und waren bisher nur im Protokoll sichtbar – im Namen verhindern sie, dass Läufe verschiedener Bedingungen gemeinsam ausgewertet werden. Die Workflow-Sperre schließt eine im Verifikationstest entdeckte Lücke: Nach der Sperre von Task/Agent versuchte der Agent, über Workflow zu orchestrieren. ab Lauf 7
3.3.0 Subagenten-Prompts werden protokolliert. Neues Skript extract-subagenten.py zieht aus dem Session-Transkript alle Subagenten-Aufrufe samt vollständigem Prompt nach _meta\subagenten.md / .json; neues Protokollfeld „Subagenten-Prompts". Die selbstgewählte Zerlegung der Analyse ist die dominierende Störgröße (0 bis 14 Subagenten bei identischem Prompt) und war bisher nur als Zahl sichtbar. Mit den Prompts wird sie inhaltlich auswertbar und für V2 zum Vergleichsmaßstab gegenüber vorformulierten Agenten. rückwirkend für alle Läufe angewandt
3.4.0 Effort als dritter Pflichtparameter: --effort wird vor jedem Lauf erfragt und im Protokoll geführt; Thinking-Tokens sind in der Verbrauchstabelle vorgesehen. Der Denkaufwand ist eine unabhängige Variable, wurde aber bis dahin nur aus der Sitzung geerbt und nirgends dokumentiert. RawResult.json enthält kein effort-Feld – nachträglich ist er nur aus dem Session-Transkript belegbar. Rekonstruktion ergab: alle Läufe 1 bis B liefen auf high, die Bedingung war also konstant. ab dem nächsten Lauf
3.5.0 Berichtete Aufwandsgröße ist der Tokenverbrauch statt der USD-Kosten. Verbrauchstabelle und alle Vergleiche führen „Tokens gesamt" (Input + Output + Cache-Write + Cache-Read über alle Modelle); total_cost_usd bleibt als Rohwert in RawResult.json, wird aber nicht mehr ins Protokoll übernommen. USD-Beträge hängen an Preisliste und Modellwahl und veralten. Token sind die unmittelbare Verbrauchsgröße, bleiben über Preisänderungen und Modellwechsel hinweg vergleichbar und sind in der Arbeit ohne Währungsbezug zitierbar. rückwirkend auf alle Protokolle angewandt
3.6.0 Verschachtelte Subagenten dokumentiert und verifiziert. Belegt, dass modelUsage auch Sub-Subagenten (Tiefe ≥ 2) erfasst; neues Protokollfeld „Verschachtelung" mit spawned, spawned_by_subagents und max_depth. Festgehalten, dass Subagenten-Transkripte nicht separat persistiert werden. Bis dahin war unbelegt, ob tiefere Ebenen in die berichtete Tokensumme einfließen. Kontrolltest mit erzwungener Kaskade (Arbeit ausschließlich auf Tiefe 2): 49.103 Tokens im Hauptagenten gegenüber 1.689.288 in modelUsage – die Differenz stammt nachweislich vom Enkel-Agenten. ab sofort
3.7.0 Effort im Verzeichnisnamen: <NN>_Lauf_<yyyy-MM-dd_HHmmss>_<modell>_<modus>_e<effort>_v<skillversion>-<id4>, z. B. _sonnet5_solo_ehigh_v3.7.0-a3f1. Das Schema entstand, als der Effort bei allen Läufen konstant high war. Mit dem ersten max-Block (Läufe P, Q) variiert er – gleichnamige Verzeichnisse hätten unterschiedliche Bedingungen bezeichnet und damit den Zweck des Schemas verfehlt. Der Effort ist zudem als möglicherweise stärkste Einflussgröße aufgefallen: Der max-Block erreichte die höchsten Thinking-Token-Werte der gesamten Reihe. rückwirkend auf alle Laufverzeichnisse angewandt
3.8.0 Pflichtprüfung der tatsächlich eingesetzten Modelle. modelUsage ist nach jedem Lauf gegen das angeforderte Modell abzugleichen; neue Protokollfelder „Modell (angefordert)", „Modelle (tatsächlich eingesetzt)" und „Kontrolle Modell". --model steuert nur den Hauptagenten. Im Lauf fable5_builtin_ehigh_v3.7.0-15db liefen die 13 Subagenten auf claude-opus-5[1m] statt auf Fable – 91 % des Verbrauchs entfielen auf ein nicht angefordertes Modell, und der Lauf wurde mit 150,3 Mio. Tokens der teuerste der Reihe. Ohne diese Prüfung bleibt die Bedingungsverletzung unbemerkt. ab sofort; Gegenprüfung der 23 Vorläufe ergab keine weiteren Fälle
3.9.0 Pflichtabschnitt „Gefundene Anforderungen" im Protokoll. Neues Skript analyse-anforderungen.py wertet die erzeugten Anforderungen aus: Verteilung, Typen, Belegqualität (PRIMÄR/SEKUNDÄR/KONTEXT), Status, Konsolidierungskandidaten und Regelkonformität gegen die Vorgaben des Prompts. Die Protokolle maßen bis dahin nur den Aufwand, nicht den Ertrag. Die reine Anforderungsanzahl taugt nicht als Qualitätsmaß (Streuung Faktor 5,9 bei gleicher Bedingung); Belegdichte und Regelverstöße sind inhaltliche Größen. Erste Anwendung deckte sofort Verstöße gegen die risikobasierte Priorisierung auf. rückwirkend auf alle 24 Protokolle angewandt
3.10.0 Bedingungen als Ordnerstruktur statt im Dateinamen. Ablage unter <ModellID>\<Agentenmodus>\<Effort>\; der Verzeichnisname lautet wieder <NN>_Lauf_<yyyy-MM-dd_HHmmss>_v<skillversion>-<id4>. Neues Protokollfeld „Ablage". Der Name wuchs mit jeder unabhängigen Variable und war mit fünf Bestandteilen kaum lesbar. Als Ordnerebenen sind die Bedingungen navigierbar, je Zelle unmittelbar abzählbar und um weitere Variablen erweiterbar, ohne bestehende Namen zu brechen. rückwirkend auf alle 24 Läufe angewandt

Parallele Läufe

Mehrere Läufe dürfen gleichzeitig gestartet werden. Voraussetzung ist, dass kein Zustand geteilt wird:

  • Verzeichnisname ist sekundengenau und trägt Modus plus 4-stellige Zufalls-ID – zwei gleichzeitige Starts können nicht kollidieren (Schritt 7 würfelt bei Kollision neu).
  • Alle Steuerdateien (combined_prompt.md, before.txt, after.txt, Zeitstempel) liegen in _meta\ im jeweiligen Laufverzeichnis. Der gemeinsame Scratchpad wird für Laufdaten nicht verwendet – dort würden parallele Läufe einander überschreiben.
  • Der Codebasis-Snapshot wird nur gelesen. Beliebig viele Läufe dürfen ihn gleichzeitig lesen. Die Vorher/Nachher-Prüfung bleibt gültig, weil kein Lauf schreibt.
  • Endeerkennung je Lauf über das Erscheinen der eigenen RawResult.json, nicht über einen gemeinsamen Marker.

Messtechnische Einschränkung – im Protokoll zwingend vermerken. Gleichzeitig laufende Versuche konkurrieren um CPU, Netzwerk und API-Kontingent. Betroffen sind:

Messgröße Bei Parallelbetrieb
Wanduhrzeit verzerrt – nicht mit seriellen Läufen vergleichbar
duration_ms, duration_api_ms verzerrt
Tokenverbrauch, Anforderungsanzahl, Denials unverzerrt

Für Laufzeitvergleiche daher seriell messen. Parallelbetrieb eignet sich, um schnell mehrere Datenpunkte für Umfang, Tokenverbrauch und Varianz zu sammeln. Das Feld „Parallele Läufe" im Protokoll nennt die zeitgleich laufenden Laufverzeichnisse; steht dort etwas anderes als nein, sind die Zeitangaben des Laufs nicht für Laufzeitvergleiche zu verwenden.

Zuordnung Versuch ↔ Agentenmodus

Versuch Modus Bedeutung
V1 – Baseline (Prompt-only) solo Ein Thread, ein Kontext; keine Subagenten
V1b – Baseline mit internen Agenten builtin Eingebaute Subagenten (Explore, general-purpose)
V2 – Agentengestützt custom Nur vordefinierte, geprompte Agenten aus --agents

Einordnung der bisherigen Läufe: Die Läufe 1–6 in Versuche/Versuch_01/ liefen sämtlich mit eingebauten Subagenten und gehören damit fachlich zu V1b, nicht zu V1. Sie belegen weiterhin die Laufvarianz unter builtin, sind aber keine Baseline-Messung im Sinne der neuen Definition. Bei der Auswertung entsprechend zuordnen.