Lokaler LM-Studio-Adapter fuer Gemma und Qwen (Skill 10.1.0)

Der TensorX-Wrapper wird providerneutral: opencode-tensorx-adapter.py heisst
jetzt opencode-adapter.py und waehlt ueber --provider {tensorx,lmstudio}
Gateway und Modellvorlage. Der TensorX-Pfad bleibt unveraendert; die vier
bestehenden Regressionstests laufen durch.

Neu fuer den lokalen Betrieb:
- opencode-lmstudio.json fuer google/gemma-4-e4b und qwen/qwen3.8-27b
- Preflight ueber /api/v0/models: Servererreichbarkeit, Modellverfuegbarkeit,
  tool_use-Faehigkeit, geladenes Kontextfenster (--min-context, Standard 32768)
  und genau eine geladene Instanz; --lmstudio-autoload stellt das selbst her
- local_runtime in RawResult.json (Quantisierung, Architektur, Runtime,
  lms-Version, Instanzbezeichner, Kontextfenster) fuer Kap. 4.3
- effort_applied, da der lokale Endpunkt keinen Thinking-Level annimmt

Drei Befunde aus der Inbetriebnahme, alle im Adapter abgefangen: LM Studio
laedt standardmaessig nur 8192 Kontexttokens; ein erneutes lms load erzeugt
eine zweite Instanz und macht das Routing mehrdeutig; Effort ist lokal
wirkungslos. Dazu zwei Korrekturen am gemeinsamen Pfad (Abbruchgrund nur
einmal in errors, saubere lms-Versionskennung).

Enthaelt ausserdem die bislang nicht committeten Laeufe der Iterationen 8
und 9 sowie Versuch 2 (Iterationen 1 bis 3). Der laufende Lauf unter
Iteration 10 ist bewusst nicht enthalten.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Christoph Schwörer
2026-08-31 20:19:33 +02:00
co-authored by Claude Opus 5
parent b369e6115e
commit 611fd0a80c
132 changed files with 83432 additions and 204 deletions
+381 -25
View File
@@ -1,7 +1,7 @@
# Ablaufprotokoll der Versuchsdurchführung
# Ablaufprotokoll der Versuchsdurchführung
**Zeitraum:** 25.–26. August 2026
**Ablage der Läufe:** `Versuche/Versuch_01/Tag 1/` – alle 24 Läufe entstanden am 25. August
**Zeitraum:** 25.–31. August 2026
**Ablage der Läufe:** `Versuche/Versuch_01/Iteration <N>/<ModellID>/<Modus>/<Effort>/<Laufverzeichnis>/`
**Untersuchungsgegenstand:** c-entron ERP-Suite, eingefrorener Snapshot `79c1142`
**Zweck dieses Dokuments:** Grundlage für den Ergebnisteil der Arbeit (Kapitel 5 und 6).
@@ -762,28 +762,357 @@ Läufe liefen **sukzessive** (nicht parallel), um API-Kontingent-Probleme zu ver
**Lauf 34 (GLM builtin) — DER DURCHBRUCH:** Nach 3 Fehlmessungen in Folge (Iteration 6+7) hat GLM 5.2 im builtin-Modus endlich Ergebnisdateien geschrieben. **132 Anforderungen** (vs. 70 bei solo — fast doppelt so viele durch Subagent-Delegation). 9 Subagenten (Limit 10, nicht voll ausgeschöpft), alle completed, 0 failed. 8 `write_file`-Aufrufe — das Subagent-Limit und die Schreib-Erinnerung haben funktioniert. 7,14 Mio Tokens (3,8× solo).
**Lauf 35 (Kimi solo):** 44 Turns, 3,2 Mio Tokens, aber nur 1 Ergebnisdatei (Analysebericht.md). Die Schreib-Erinnerung wurde nicht ausgelöst, weil das Modell früh einmal `write_file` aufrief (`write_file_count == 0` war nie erfüllt). Kimi schrieb den Analysebericht, dann nie wieder — möglicherweise durch max_turns begrenzt.
---
**Lauf 36 (Kimi builtin):** Wurde durch Stromausfall abgebrochen. 6 Subagenten gestartet, 0 Ergebnisdateien. Keine Auswertung möglich.
### Nachanalyse der Kimi-K3-Läufe und Adapterkorrektur 9.0.0 (29.08.2026)
**Wiederholungsläufe (nach Adapter-Verbesserung):** Die Schreib-Erinnerung wurde erweitert: sie löst jetzt auch bei `write_file_count < 3` nach ⅔ der Turns aus.
Die zunächst notierte Erklärung, Kimi K3 beende seine Arbeit nach einer Beschreibung mit
`finish_reason: stop`, wird durch die Rohdaten widerlegt. In allen fünf `solo`-Läufen mit
Prompt-Version 03 war die letzte erfolgreiche Antwort ein Tool-Aufruf
(`finish_reason: tool_calls`). Der jeweils folgende HTTP-Aufruf an TensorX lieferte 1.800
Sekunden lang keine Antwort und endete mit `Read timed out (read timeout=1800)`.
| # | Zeit | Modell | Modus | Effort | Subagenten | Turns | Tokens | Anforderungen | Status |
|---:|---|---|---|---|---:|---:|---:|---:|---|
| 37 | 16:10 | **kimi-k3** | solo | high | 0 | 27 | 1.473.405 | 0 | ⚠️ nur StRS.md |
| 38 | 17:24 | **kimi-k3** | builtin | high | 10 (Limit) | — | — | 0 | ❌ **abgebrochen** (API-Timeout) |
| Lauf | Iteration | Turns | Tokens | Dateien | Tatsächliches Ende |
|---:|---:|---:|---:|---:|---|
| 31 | 7 | 23 | 628.222 | 0 | API-Read-Timeout in Turn 23 |
| 35 | 8 | 44 | 3.208.550 | 1 | API-Read-Timeout in Turn 44 |
| 37 | 8 | 27 | 1.473.405 | 1 | API-Read-Timeout in Turn 27 |
| 39 | 8 | 25 | 695.248 | 7, davon 6 nur Skelette | API-Read-Timeout in Turn 25 |
| 40 | 8 | 30 | 2.094.726 | 0 | API-Read-Timeout in Turn 30 |
**Lauf 37 (Kimi solo, Wiederholung):** 27 Turns, 1,47 Mio Tokens, aber nur 1 Ergebnisdatei (StRS.md). Das Modell schreibt eine Datei und beendet sich dann mit `finish_reason: stop` — die Schreib-Erinnerung kann nicht greifen, weil das Modell vor Turn 67 (Schwelle für erste Erinnerung) stoppt. Dies ist ein Kimi-K3-spezifisches Verhaltensmuster: das Modell beendet den Lauf nach einer Teilleistung.
Der Timeout war im Adapter trotz der CLI-Beschreibung `--timeout 0` fest auf 1.800 Sekunden
gesetzt. Zusätzlich lautete die Fehlerbedingung
`len(errors) > 0 and not final_content`: Sobald irgendeine frühere Modellantwort Freitext
enthielt, wurden der Timeout, `subtype` und der Prozess-Exitcode als Erfolg ausgewiesen. Der
Fehler stand nur im Feld `errors` der `RawResult.json`, nicht in `Stderr.log`. Dadurch konnte die
vorgeschriebene Stderr-Prüfung ihn nicht erkennen.
**Lauf 38 (Kimi builtin, Wiederholung):** Subagent-Limit erreicht (10/10), danach 4 weitere `spawn_subagent`-Aufrufe verweigert. Aber das Modell schrieb keine Ergebnisdateien — es blockierte nach den Verweigerungen auf einem API-Aufruf (CPU eingefroren bei 465s für 25+ Min). Nach ~100 Min manuell abgebrochen.
Die Kausalität ist daher zweistufig: Der unmittelbare Stillstand liegt auf dem nicht
gestreamten Kimi-/TensorX-API-Aufruf; dass daraus eine stille oder falsch als erfolgreich
markierte Fehlmessung wurde, liegt am Adapter. Ein grundsätzlich ungeeignetes Modell ist nicht
belegt: Kimi K3 schloss in Iteration 6 unter Prompt-Version 02 sowohl `solo` als auch `builtin`
ohne Hauptagenten-API-Fehler ab. Auch ein fester Kontext- oder Turnschwellenwert erklärt die
Streuung der Abbruchturns 23 bis 44 nicht.
**Erkenntnis aus Iteration 8 (endgültig):**
- **Das Subagent-Limit (10) funktioniert für GLM 5.2** zuverlässig: nach Erreichen des Limits schreibt GLM Ergebnisdateien (132 Anforderungen in Lauf 34).
- **Kimi K3 hat ein anderes Problem als GLM:** Das Subagent-Limit wird korrekt durchgesetzt (10/10, 4 Verweigerungen), aber Kimi K3 kann nicht zur Schreibphase übergehen — es blockiert nach den Verweigerungen.
- **Kimi K3 solo** beendet sich nach 1 Ergebnisdatei mit `finish_reason: stop` — die Schreib-Erinnerung kann nicht greifen, weil das Modell vor der Turn-Schwelle stoppt.
- **Modell-spezifische Unterschiede:** GLM 5.2 ist im builtin-Modus produktiv (mit Limit), Kimi K3 ist es nicht — weder solo (frühzeitiger Abbruch) noch builtin (kein Übergang zur Schreibphase).
- Die TensorX-Matrix hat jetzt 2 von 4 Zellen gültig gefüllt: GLM solo (70 Anf.) und GLM builtin (132 Anf.). Kimi solo und Kimi builtin bleiben problematisch.
Die beiden abgebrochenen `builtin`-Wiederholungen haben zusätzliche, getrennte Ursachen:
- Lauf 36 wurde nach sechs gestarteten Subagenten durch einen Stromausfall beendet.
- Lauf 38 wurde nach zehn gestarteten und vier vom Adapter verweigerten Subagenten manuell
beendet. Der Adapter arbeitete Subagenten synchron ab, obwohl das Modell sie gemeinsam und
damit parallel angefordert hatte.
Das in Iteration 8 eingeführte 10er-Limit ist keine neutrale Schutzmaßnahme. Anzahl, Typ und
Zerlegung der Subagenten sind selbst Untersuchungsgegenstand von V1b. Nach dem zehnten Start
injizierte der Adapter zudem eine Aufforderung, keine weiteren Subagenten zu starten und sofort
Dateien zu schreiben. Auch die turnabhängigen Schreib-Erinnerungen griffen in die autonome
Strategie ein. Lauf 34 belegt daher nur, dass GLM unter dieser erzwungenen Adapterstrategie
Ergebnisdateien erzeugte; er ist nicht mit einem freien `builtin`-Lauf poolbar.
**Adapterkorrektur und neue Versuchsbedingung (Skill 9.0.0, Adapter 2.0.0):**
- Kein Anzahl-Limit für `spawn_subagent`; Typ und Zahl bestimmt ausschließlich das Modell.
- Alle Subagenten-Aufrufe aus demselben Hauptagenten-Turn laufen tatsächlich parallel.
- Haupt- und Subagenten haben standardmäßig kein Turnlimit; laufzeitabhängige
Schreib-Erinnerungen wurden entfernt.
- `--timeout 0` bedeutet tatsächlich kein clientseitiges HTTP-Timeout.
- API-Fehler setzen unabhängig von früherem Freitext `is_error: true`, werden nach
`Stderr.log` geschrieben und führen zu Exitcode 1.
- Ein threadsicheres Lebenszeichen meldet standardmäßig alle 60 Sekunden, welche Operation
beim Hauptagenten und bei jedem Subagenten aktiv ist. Abgeschlossene API-Turns melden ihren
Einzel- und kumulierten Tokenverbrauch.
Ein Lebenszeichen während eines API-Aufrufs bedeutet ausschließlich: Der lokale Python-Prozess
lebt und wartet weiterhin auf TensorX. Da die API nicht gestreamt wird, kann der Adapter während
dieser Wartephase nicht unterscheiden, ob serverseitig noch inferiert wird oder der Request
hängt. Der Logtext weist auf diese Grenze ausdrücklich hin. Automatische Abbrüche oder Retries
wurden bewusst nicht eingeführt, weil Laufzeit unerheblich ist und ein Retry zusätzlichen,
möglicherweise doppelten Tokenverbrauch verursachen kann.
Die Implementierung wurde ohne echten API-Aufruf geprüft: zwölf in einem Turn angeforderte
Subagenten starteten ohne Ablehnung parallel; `timeout=0` wurde als unbegrenztes Requests-Timeout
weitergereicht; ein API-Fehler nach vorhandenem Freitext blieb ein Fehler; Haupt- und
Subagentenaktivitäten erschienen gemeinsam im Heartbeat. Alle vier Tests liefen erfolgreich.
Da Parallelität, Limits, Laufsteuerung und Fehlersemantik geändert wurden, ist dies eine neue
Versuchsbedingung. Der nächste TensorX-Lauf beginnt **Iteration 9**; Iteration-8-`builtin`-Läufe
werden nicht mit den neuen freien `builtin`-Läufen gepoolt.
### Versuch 2 – erster Lauf im Modus `custom` (31.08.2026)
Erster Lauf mit rollenspezialisierten Agentendateien überhaupt. Er eröffnet `Iteration 1` in
`Versuche/Versuch_02/`.
**Vorgeschaltete Korrekturen am Versuchsaufbau.** Der bis dahin vorbereitete V2-Prompt
(`01_Prompt.md`, Version 02-A) leitete sich von Prompt-Version **02** ab, während Versuch 1 seit
Iteration 8 auf Version **03** lief. Ein Lauf dagegen hätte sich in zwei Größen unterschieden –
Agentenrollen *und* Prompt-Version – und wäre als Wirkungsnachweis der Rollen unbrauchbar
gewesen. `02_Prompt.md` (Version **03-A**) setzt deshalb auf Prompt-Version 03 auf; einzige
Ergänzung bleibt der Abschnitt *Arbeitsteilung*. Dabei fielen zwei Fehlstellen in
`Versuch_01/03_Prompt.md` auf, die in jeden Lauf der Iterationen 8 und 9 eingingen, weil der
Skill die gesamte Datei sendet: eine leere Änderungstabelle im Metadatenblock und zwei
Tabellenzeilen, die hinter dem Abschnitt *Abschluss* stehen.
**Die Rollennutzung wurde gebunden.** Ein Smoke-Test vom 26.08. hatte gezeigt, dass der Agent von
acht beigestellten Rollen nur zwei einsetzt. Ohne Bindung wird die Versuchsbedingung nicht
hergestellt: Der Lauf führt die Rollen mit, ohne sie zu nutzen. Der Prompt verlangt seither, dass
eine Teilaufgabe, für die ein Bearbeiter vorgesehen ist, von ihm ausgeführt wird; die konkrete
Zuordnung `Teilaufgabe → Rolle` steht im Block *Werkzeugkontext* (Skill 9.1.0), nicht im Prompt,
damit dieselbe Prompt-Datei für `solo` und `builtin` gültig bleibt. Gebunden ist **wer** eine
Teilaufgabe ausführt; Zuschnitt, Anzahl, Reihenfolge und Tiefe bleiben frei.
Die Bindung ist statisch deklariert und über den SHA-256 der `--agents`-Datei versioniert. Sie
ist damit von den in Skill 9.0.0 entfernten **laufzeitabhängigen** Adaptereingriffen zu
unterscheiden, die Lauf 34 unpoolbar machten: Jene steuerten den Lauf abhängig von seinem eigenen
Verlauf um, diese steht vor dem Lauf fest.
**Ergebnis des Laufs** (`Iteration 1/claude-sonnet-5/custom/high/…_v9.1.0-0c39`):
| Messgröße | Wert |
|---|---:|
| Wanduhrdauer | 03:07:16 |
| Tokens gesamt | **352.828.287** |
| Anforderungen | 845 (StRS 185 / SyRS 180 / SwRS 480) |
| Subagenten | 86 gestartet, 86 abgeschlossen, 0 fehlgeschlagen |
| Primärbelegquote | 96,0 % der Belege; 95,6 % der Anforderungen |
| Permission-Denials | 3 (alle Bash, Denylist) |
Der Lauf ist gültig: alle sieben geforderten Dateien, keine Ergänzungsdateien, `Stderr.log` leer,
Root unverändert, Modellkontrolle bestanden. Er ist mit **352,8 Mio. Tokens** zugleich der
aufwendigste der gesamten Reihe – 1,8-fach über dem bisherigen Höchstwert (193,4 Mio., ohne
Artefakt) und 2,3-fach über dem teuersten Lauf mit Ergebnis.
**Die Bindung wirkt.** Alle acht Rollen wurden eingesetzt, gegenüber 2 von 8 im ungebundenen
Smoke-Test. Die Zerlegung blieb dabei frei gewählt: acht Inventar-Ausschnitte, 35 Faktenaufträge,
ID-blockweise Autorenaufträge.
| Rolle | Aufrufe | Rolle | Aufrufe |
|---|---:|---|---:|
| `faktenermittler` | 35 | `syrs-autor` | 6 |
| `general-purpose` | 12 | `Explore` | 4 |
| `swrs-autor` | 10 | `belegpruefer` | 1 |
| `modulinventar` | 8 | `iso29148-orchestrator` | 1 |
| `strs-autor` | 8 | `konsistenzpruefer` | 1 |
**Vier Befunde aus dem Lauf:**
1. **Die Bindung hatte eine Lücke.** 12 Aufrufe gingen an den eingebauten Typ `general-purpose`,
sämtlich für die Traceability-Anreicherung (Schritt 6) – für die die Zuordnungstabelle keinen
Bearbeiter vorsah, obwohl `iso29148-orchestrator` laut Rollenprompt dafür zuständig ist. Kein
Verstoß des Agenten, sondern ein Konstruktionsfehler der Tabelle. Wo die Bindung schweigt,
greift der Agent zum eingebauten Typ.
2. **Die Selbstauskunft war an einer Stelle falsch.** Der `Analysebericht.md` vermerkt
*Ausnahmen von der Zuständigkeitsbindung: keine*, obwohl die Traceability von
`general-purpose` stammt. Aufgefallen ist das nur durch den maschinellen Abgleich gegen
`subagent_stats.by_type` – die Dokumentationspflicht allein hätte den Fall verdeckt.
3. **`--agents` ersetzt die Agent-Registry nicht, es ergänzt sie.** `Explore` und
`general-purpose` blieben verfügbar. Ein V2, das ausschließlich die beigestellten Rollen
zulassen soll, bräuchte zusätzlich eine Sperre – eine geänderte Werkzeugkonfiguration und
damit eine neue Bedingung.
4. **Die Rollen delegierten selbst.** `spawned_by_subagents` = 26 von 86, `max_depth` = 3. Die
Rollen erben über `--agents` alle Werkzeuge einschließlich `Task`. Das war nicht beabsichtigt
und ist der wesentliche Kostentreiber (siehe unten).
**Zwei überholte Annahmen des Skills.** Unter CLI 2.1.251 liegt je Lauf ein Verzeichnis
`subagents/` mit einer vollständigen `.jsonl` je Subagent; die Feststellung, Subagenten-Transkripte
würden nicht auswertbar persistiert (Stand 2.1.245), gilt nicht mehr. Damit wären erstmals auch
die Prompts und Verläufe der Ebenen 2 und 3 auswertbar, die `extract-subagenten.py` nicht
erreicht. Zweitens erfasst `duration_ms` (220.847 ms) den Gesamtlauf erkennbar nicht und ist als
Dauer unbrauchbar; berichtet wird die selbst gemessene Wanduhrzeit.
**Nebenbefund zur Zerlegung.** 72 Aufrufe wurden am Nebenläufigkeitslimit (20 gleichzeitig)
abgewiesen – gegenüber 86 gestarteten die höchste Absagequote der Reihe. Die Zerlegung ist damit
nur eingeschränkt selbstgewählt: Sie ist teilweise vom Werkzeuglimit geformt.
### Kostenanalyse und die Option `unverschachtelt` (Skill 9.2.0, 31.08.2026)
Der Lauf verbrauchte 43 % des verfügbaren Modellkontingents. Für die Wiederholung mit
`claude-opus-5` ist das die bindende Grenze, denn Opus kostet **gleichmäßig das 2,5-fache** von
Sonnet 5 – auf Input, Output, Cache-Write und Cache-Read gleichermaßen. Derselbe Lauf mit Opus
entspräche rund **108 %** des Kontingents; das Ergebnis hängt nicht davon ab, wie das Kontingent
denominiert ist, weil der Faktor uniform ist.
Kostenanteile des Laufs:
| Position | Tokens | Anteil an den Kosten |
|---|---:|---:|
| Cache-Read | 335,3 Mio. | 46 % |
| Output | 4,69 Mio. | 32 % |
| Cache-Write | 12,8 Mio. | 22 % |
Cache-Reads dominieren, und sie entstehen **innerhalb** der Subagenten: Jeder Turn liest den bis
dahin gewachsenen Kontext erneut, die Kosten wachsen daher etwa quadratisch mit der Turn-Zahl je
Agent. Bei 86 Agenten entfallen rechnerisch rund 3,9 Mio. Cache-Reads auf jeden.
Daraus folgt die neue Option **Delegationstiefe** (Skill 9.2.0). `unverschachtelt` untersagt jeder
Rolle in ihrem Prompt die Weiterdelegation; `verschachtelt` entspricht dem bisherigen Verhalten.
Bestehende Läufe gelten rückwirkend als `verschachtelt`. Kontrolle nach dem Lauf über
`subagent_stats.max_depth` und `spawned_by_subagents`.
Die strukturellen Korrekturen allein – keine Weiterdelegation, Faktenübergabe per Datei statt
inline – bringen geschätzt 30 bis 40 %. Nötig wären 60 %. Der Opus-Lauf erfordert deshalb
zusätzlich eine bewusste Bedingungsänderung: **Effort `medium` statt `high`**. Der Modellvergleich
Sonnet-`high` gegen Opus-`medium` ist damit konfundiert; aufzulösen ist das durch einen
zusätzlichen, günstigen Lauf `claude-sonnet-5 / custom / medium`, der Modell- und Effort-Effekt
trennt.
**Anzumerken bleibt:** Die Wirkung des Effort-Wechsels auf einen `custom`-Lauf ist nicht gemessen,
sondern geschätzt. Bleibt der Opus-Lauf über 43 %, ist das selbst ein Befund zur Messbarkeit der
Zelle – vergleichbar mit `claude-opus-5 / builtin / high` aus Versuch 1.
---
### Versuch 2 – Opus-Lauf und die Kontingentgrenze (31.08.2026)
Der zweite V2-Lauf sollte prüfen, ob die Zelle `claude-opus-5 / custom` innerhalb der 43 % des
Modellkontingents machbar ist, die der Sonnet-Lauf verbraucht hatte. **Sie ist es nicht.** Er
eröffnet `Iteration 2` in Versuch 02
(`Iteration 2/claude-opus-5/custom/medium/…_v9.2.0-da6a`).
**Drei Größen wurden gleichzeitig gewechselt**, zwei davon erzwungen durch das Kontingent:
| Größe | Iteration 1 | Iteration 2 |
|---|---|---|
| Modell | `claude-sonnet-5` | `claude-opus-5` |
| Effort | `high` | `medium` |
| Delegationstiefe | `verschachtelt` | `unverschachtelt` |
Ein Modellvergleich zwischen beiden Läufen ist damit **nicht zulässig**; die Gegenüberstellung
unten vergleicht zwei Bedingungen, nicht zwei Modelle.
**Ergebnis:**
| Messgröße | Wert |
|---|---:|
| Wanduhrdauer | 03:47:17 |
| Tokens gesamt | **397.199.658** |
| Anforderungen | 606 (StRS 53 / SyRS 149 / SwRS 404) |
| Subagenten | 56 gestartet, 56 abgeschlossen, 0 fehlgeschlagen, **0 abgewiesen** |
| Permission-Denials | 0 |
| Regelverstöße (maschinell) | **0** |
Der Lauf ist gültig – alle sieben Dateien, `Stderr.log` leer, Root unverändert – **mit einer
Einschränkung: die Modellbedingung ist verletzt.**
**Die Kontingentgrenze ist die eigentliche Nachricht.** Zu Listenpreisen kostet der Lauf rund
$433 gegenüber $146 des Sonnet-Laufs, also das **2,97-fache** und damit rund **128 % des
Kontingents**. Der Preisfaktor zwischen Opus 5 und Sonnet 5 beträgt gleichmäßig 2,5 auf allen
Token-Klassen; die restliche Differenz stammt aus einem um 12,6 % **höheren** Tokenverbrauch –
und zwar trotz `medium` statt `high`, trotz unterbundener Weiterdelegation und trotz 56 statt 86
Agenten. Je Subagent wurden rund 13,6 Mio. Transkript-Tokens verbraucht gegenüber 7,0 Mio. beim
Sonnet-Lauf: Opus zerlegt gröber und arbeitet jeden Ausschnitt tiefer aus. Beide strukturellen
Sparmaßnahmen wurden davon vollständig aufgezehrt.
Die vorab getroffene Schätzung von 38 bis 45 % war damit **deutlich zu niedrig**. Auch die
laufende Live-Schätzung aus den Transkripten traf nicht: Sie meldete kurz vor Laufende 96 %,
tatsächlich waren es 128 %. Der dafür verwendete Kalibrierfaktor – Transkriptsumme geteilt durch
den am Sonnet-Lauf gemessenen Wert 2,45 – beträgt für diesen Lauf nur 1,95. Er ist nicht
laufübergreifend stabil, weil er vom Verhältnis Haupt- zu Subagenten-Nachrichten abhängt. Eine
solche Schätzung taugt zur Richtungsanzeige, nicht zur Budgetsteuerung.
**Damit ist `claude-opus-5 / custom` als unter dem verfügbaren Kontingent nicht wiederholbar
messbare Zelle zu führen** – die zweite nach `claude-opus-5 / builtin / high` aus Versuch 1. In
beiden Fällen ist die Grenze das Kontingent und nicht das Verfahren.
**Modellbedingung verletzt – erstmals auftragsscharf lokalisiert.** `modelUsage` weist neben
`claude-opus-5` (365,0 Mio.) das nicht angeforderte `claude-sonnet-5` mit 32,2 Mio. Tokens
(8,1 %) aus. Weil CLI 2.1.251 jedes Subagenten-Transkript einzeln persistiert, ließ sich der Fall
erstmals genau verorten statt nur als Summe zu sehen: 8 der 56 Subagenten liefen auf Sonnet –
sechs `faktenermittler`, ein `swrs-autor`, ein `modulinventar`. Sieben davon betreffen denselben
Gegenstand (docuFORM, offener Punkt 63), für den der `faktenermittler` sechsmal beauftragt wurde.
Ob der Modellwechsel eine Folge der wiederholten Beauftragung derselben Teilaufgabe ist oder eine
davon unabhängige Zuweisung der CLI, ist aus den Daten nicht zu entscheiden. Der Fall ist der
dritte dokumentierte seiner Art und bestätigt: `--model` bindet den Hauptagenten, nicht
zuverlässig die Subagenten.
**Was die neuen Vorgaben geleistet haben.** Die Delegationstiefe `unverschachtelt` hat
vollständig gegriffen: `spawned_by_subagents` = 0, `max_depth` = 1, 56 Aufrufe gegen 56
Transkripte – und das allein über den Rollenprompt, ohne technische Erzwingung. Als Nebeneffekt
entfielen die Absagen am Nebenläufigkeitslimit vollständig (0 gegenüber 72 im ersten V2-Lauf).
Alle acht Rollen wurden eingesetzt, und zwar **ohne einen einzigen Aufruf an einen eingebauten
Typ** – gegenüber 16 von 86 (18,6 %) im ersten V2-Lauf. Die Bindungslücke bei Schritt 6
(Traceability) blieb absichtlich offen, um die Zahl der geänderten Größen zu begrenzen; sie
wirkte sich hier nicht aus. Die `Traceability.md` entstand ohne ungebundenen Agenten. Ein
Modelleffekt ist naheliegend, bei drei gleichzeitig gewechselten Größen aber nicht belegt.
**Gegenüberstellung der beiden V2-Läufe** – zwei Bedingungen, kein Modellvergleich:
| Kenngröße | Iteration 1 (Sonnet/high/verschachtelt) | Iteration 2 (Opus/medium/unverschachtelt) |
|---|---:|---:|
| Anforderungen | 845 | 606 |
| Verteilung StRS/SyRS/SwRS | 185 / 180 / 480 | 53 / 149 / 404 |
| Belege gesamt | 1.086 | **1.927** |
| Belege je Anforderung (Median) | 1,0 | **3,0** |
| Anforderungen mit `PRIMÄR`-Beleg | 95,6 % | **98,5 %** |
| Anforderungen ohne jeden Beleg | 9 | **0** |
| Hypothesenanteil | 8,9 % | 4,8 % |
| Konsolidierungskandidaten | 22,1 % | 38,3 % |
| mit ISO-25010-Merkmal | **65,9 %** | 13,4 % |
| Subagenten | 86 | 56 |
| Tokens gesamt | 352.828.287 | 397.199.658 |
| Wanduhrdauer | 03:07:16 | 03:47:17 |
Weniger Anforderungen, aber erheblich dichter belegt, und kein einziger maschinell feststellbarer
Regelverstoß gegenüber neun Anforderungen ohne Beleg im ersten Lauf. Zwei Verschlechterungen:
Die ISO-25010-Zuordnung bricht von 65,9 % auf 13,4 % ein, und die StRS-Ebene ist mit 53
Anforderungen (8,7 %) sehr dünn – der `strs-autor` wurde nur dreimal beauftragt, der
`swrs-autor` elfmal. Die Ebenenverteilung bleibt damit auch mit getrennten Autorenrollen die
instabilste Größe der Reihe.
---
### Lokaler Betrieb: LM-Studio-Adapter (Skill 10.1.0, 31.08.2026)
Kapitel 4 sieht neben den Cloud-Modellen den lokalen Betrieb als eigene Bedingung vor. Dafür
wurde der bisherige TensorX-Wrapper zu einem providerneutralen Adapter verallgemeinert:
`opencode-tensorx-adapter.py` heißt jetzt `opencode-adapter.py` und wählt über
`--provider {tensorx,lmstudio}` Gateway und Modellvorlage. Beide Provider durchlaufen denselben
Agenten-, Berechtigungs- und Metrikpfad; die vier bestehenden TensorX-Regressionstests laufen
unverändert durch, laufende V2-Läufe bleiben damit vergleichbar.
Lokale Modelle: `google/gemma-4-e4b` (7,5B, Q4_K_M, gguf) und `qwen/qwen3.8-27b` (27B, Q4_K_M,
gguf) über den OpenAI-kompatiblen LM-Studio-Server auf `localhost:1234`.
**Drei Befunde aus der Inbetriebnahme sind direkt in den Adapter eingeflossen.** Alle drei
hätten unbemerkt ungültige Messpunkte erzeugt:
1. **LM Studio lädt Modelle standardmäßig mit 8192 Kontexttokens** – bei `gemma-4-e4b` von
131.072 möglichen. Eine Codebasisanalyse wäre serverseitig abgeschnitten worden, ohne dass
Adapter, Werkzeug oder Protokoll davon etwas gemerkt hätten. Der Preflight fordert deshalb
`--min-context` (Standard 32768) und bricht sonst mit dem exakten `lms load`-Befehl ab.
2. **Ein erneutes `lms load` erzeugt eine zweite Instanz** (`modell:2`) neben der bestehenden.
Beide beantworten dieselbe `model`-Angabe der OpenAI-API; welche Instanz – und damit welches
Kontextfenster – antwortet, ist nicht bestimmt. Der Preflight verlangt daher **genau eine**
geladene Instanz; `--lmstudio-autoload` stellt das durch Entladen aller Instanzen und einmal
Neuladen selbst her.
3. **Effort ist lokal nicht steuerbar.** Der LM-Studio-Endpunkt nimmt keinen Thinking-Level
entgegen. Der angeforderte Wert wird weiterhin protokolliert, aber als
`effort_applied: false` ausgewiesen und ist im Protokoll als *nicht steuerbar* zu führen –
nicht als gesetzte Bedingung. Reasoning-Tokens liefern die Modelle trotzdem: `gemma-4-e4b`
meldete im Smoke-Test 10.218 von 88.650 Tokens als Reasoning.
Für die von Kap. 4.3 geforderten Reproduzierbarkeitsangaben bei lokalem Betrieb schreibt der
Adapter `local_runtime` nach `RawResult.json` – Quantisierung, Architektur, Runtime,
`lms`-Version, Instanzbezeichner sowie maximales und geladenes Kontextfenster – zusätzlich
`context_window` und `_meta/lmstudio-modelle.json` als Rohantwort des Servers. Kosten sind
definitionsgemäß `0` (`cost_source: nicht erfasst (lokaler Betrieb)`), Cache-Metriken liefert
der lokale Server nicht.
**Terminierungsverhalten als eigenständiger Befund.** In zwei Smoke-Läufen schrieb
`gemma-4-e4b` zwar die geforderte Datei, beendete die Aufgabe danach aber nicht, sondern lief
bis zum Laufzeitlimit weiter (25 bzw. 40 Turns). Der Stall-Timeout greift dabei **nicht**, weil
laufend Text erzeugt wird. Lokale Läufe brauchen deshalb zwingend ein absolutes
`--max-runtime`; ein so beendeter Lauf ist als Abbruch zu protokollieren, nicht als Ergebnis.
Das ist keine Adapterschwäche, sondern eine Eigenschaft kleiner lokaler Modelle und für den
Vergleich mit den Cloud-Läufen relevant.
**Nebenbefund zur Fehlersuche:** Ein erster Smoke-Lauf scheiterte an verweigerten Schreibrechten,
obwohl der Zielpfad in der Allowlist stand. Ursache war das Testverzeichnis: OpenCode gleicht
Schreibziele gegen den Pfad *relativ zur Git-Worktree-Wurzel* ab (Skill 10.0.2), und das
Scratchpad war kein Git-Repository. Im Versuchslayout – Codebasis und Laufverzeichnis im selben
Worktree – greift die Freigabe; ein Kontrolltest in einem initialisierten Repository schrieb die
Datei erwartungsgemäß. Die Beobachtung ist festgehalten, weil sie leicht als Adapterfehler
fehlgedeutet wird.
---
@@ -961,6 +1290,13 @@ Ein weiterer Anlauf wäre nur mit gedrosselter Nebenläufigkeit
(`CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS`) sinnvoll – das wäre allerdings eine geänderte
Werkzeugkonfiguration und nicht mehr mit den Sonnet-`builtin`-Läufen vergleichbar.
Seit dem 31.08. kommt eine zweite solche Zelle hinzu: `claude-opus-5 / custom`. Sie ist
**messbar, aber nicht wiederholbar bezahlbar** – ein einzelner Lauf verbrauchte rund 128 % des
Modellkontingents, und zwar bereits in der sparsamsten sinnvollen Fassung (`medium` statt `high`,
Rollen ohne Weiterdelegation). Der Unterschied zur Opus-`builtin`-Zelle ist wesentlich: Dort
entstand kein Artefakt, hier ein vollständiges und regelkonformes. Die Grenze ist in beiden
Fällen das Kontingent, nicht das Verfahren.
**Bedingungsverletzt statt unbelegt:** Die Zelle `claude-fable-5 / builtin / *` ist messbar, aber
die Modellbedingung ist dort nicht herstellbar – die Subagenten laufen auf `claude-opus-5[1m]`.
Läufe dieser Zelle sind für Modellvergleiche unbrauchbar und nur als Beleg für die
@@ -971,17 +1307,34 @@ entfiel auf Läufe ohne verwertbares Ergebnis, überwiegend durch Parallelbetrie
Kontingentgrenze. Seit dem 27.08. wird strikt seriell gefahren.
**Offen für Versuch 2 und 3:** Bei Delegation ist die Modellbedingung über `--model` allein nicht
herstellbar (zwei dokumentierte Fälle). `extract-subagenten.py` ist noch nicht gegen
`custom`-Agententypen geprüft. Für V3 fehlt im Skill ein Protokollfeld für die
MCP-Konfiguration, und der Zustand des laufenden Systems – Datenbankstand, Mandant, Datenart –
ist als Teil des Untersuchungsgegenstands je Lauf zu erfassen.
herstellbar – inzwischen **drei** dokumentierte Fälle, der jüngste erstmals auftragsscharf
lokalisiert (8 von 56 Subagenten des Opus-Laufs auf `claude-sonnet-5`). `extract-subagenten.py`
ist seit dem 31.08. an zwei `custom`-Läufen erprobt und rechnet dort exakt gegen
`subagent_stats` auf; es erreicht jedoch nur die direkt vom Hauptagenten gestarteten Subagenten.
Für V3 fehlt im Skill ein Protokollfeld für die MCP-Konfiguration, und der Zustand des laufenden
Systems – Datenbankstand, Mandant, Datenart – ist als Teil des Untersuchungsgegenstands je Lauf
zu erfassen.
**Offen aus den V2-Läufen:** Die Bindungstabelle im Werkzeugkontext führt für Schritt 6
(Traceability-Anreicherung) keinen Bearbeiter, obwohl `iso29148-orchestrator` dafür zuständig
wäre; die Zeile ist zu ergänzen. `--agents` ergänzt die Agent-Registry, statt sie zu ersetzen –
soll V2 ausschließlich die beigestellten Rollen zulassen, braucht es zusätzlich eine Sperre und
damit eine neue Bedingung. Die Regel „Rollen legen keine Dateien an" ist zu präzisieren:
Ergebnisdateien verboten, Scratchpad-Übergabe zulässig und zu dokumentieren. Schließlich ist
`extract-subagenten.py` auf die seit CLI 2.1.251 je Subagent persistierten Transkripte zu
erweitern – erst damit werden auch verschachtelte Ebenen auswertbar.
**Nicht durchgeführt:** Die Stakeholder-Validierung nach Kapitel 4.3. Alle Aussagen dieses
Protokolls beruhen auf maschinell erhebbaren Größen. Ob die erzeugten Anforderungen sachlich
korrekt sind, ist damit ausdrücklich **nicht** gezeigt.
**Nicht abgedeckt:** Versuch 2 (Agentendateien) und Versuch 3 (MCP-Server). Der Skill ist darauf
vorbereitet (Modus `custom`), die Agentendefinitionen existieren aber noch nicht.
**Stand der Versuche:** Versuch 2 (Agentendateien) ist seit dem 31.08. mit zwei Läufen belegt –
`claude-sonnet-5 / custom / high / verschachtelt` und `claude-opus-5 / custom / medium /
unverschachtelt`. Beide sind gültig, aber wegen dreier gleichzeitig gewechselter Größen nicht
gegeneinander als Modellvergleich verwertbar; für eine saubere Trennung fehlt ein Lauf
`claude-sonnet-5 / custom / medium / unverschachtelt`. **Nicht abgedeckt bleibt Versuch 3**
(MCP-Server): Der Skill ist darauf vorbereitet, die MCP-Konfiguration und das zugehörige
Protokollfeld fehlen aber noch.
**Offene Aufräumarbeiten:** Drei Streudateien in `C:\DEV\` aus Lauf 13; die Erweiterung der
Nachlaufprüfung um Streudateien außerhalb des Laufverzeichnisses.
@@ -1015,7 +1368,10 @@ Stichprobe.
- Exakt gesendeter Prompt je Lauf: `_meta/combined_prompt.md`
- Subagenten-Prompts: `_meta/subagenten.md`
- Maschinelle Anforderungsauswertung: `_meta/anforderungen.md` und `.json`
- Prozessvorgabe: `.claude/skills/run-experiment/SKILL.md` (Version 8.0.0, mit Änderungshistorie)
- Prozessvorgabe: `.claude/skills/run-experiment/SKILL.md` (Version 10.1.0, mit Änderungshistorie)
- OpenCode-Adapter (TensorX und LM Studio): `.claude/skills/run-experiment/references/opencode-adapter.md`
- Messprotokolle Versuch 2: `Versuche/Versuch_02/<Iteration>/<ModellID>/custom/<Effort>/<Laufverzeichnis>/Protokoll.md`
- Agentenrollen: `Versuche/Versuch_02/02_Agents.json` (verschachtelt), `03_Agents.json` (unverschachtelt)
- Nachweis des Untersuchungsgegenstands: `Versuche/Versuch_01/_Codebasis-Nachweis.md`
- Struktur- und Umbenennungshistorie: `Versuche/Versuch_01/_Umbenennung_*.md`,
`_Umstrukturierung_2026-08-26.md`