Lokale Matrix liefert Ergebnisse: 119 Anforderungen aus Gemma und Qwen

Skill 13.0.0/13.1.0, Adapter 2.5.2.

Spiegel-Arbeitsverzeichnis: OpenCode laeuft nicht mehr direkt im
Codebasis-Root, sondern in einem Verzeichnis aus Junctions auf die
Top-Level-Eintraege, mit einem echten Ergebnisverzeichnis, dessen Inhalt
nach dem Lauf uebernommen wird. Damit landen relative wie absolute
Ausgabepfade am richtigen Ort, ohne dass der Prompt vom Wortlaut der
Claude-Laeufe abweichen muss. Der Spiegel liegt in _meta des Laufs; die
Codebasis bleibt unberuehrt.

Der Spiegel allein genuegte nicht. Sechs Laeufe schrieben mit korrektem
absolutem Pfad und wurden dennoch abgewiesen, weil OpenCode Ziele im
Repository gegen den worktree-relativen Pfad abgleicht - ein Befund, der
seit Skill 10.0.2 dokumentiert war und erst sichtbar wurde, als der
Spiegel vom Temp-Verzeichnis ins Projekt wanderte.

analyse-anforderungen.py erkennt Kennungen als Markdown-Ueberschrift, auch
ohne Feldnamen, sofern die Pflichtfelder folgen. Regressionsprobe an fuenf
Claude-Laeufen unveraendert.

Ergebnisse der gueltigen Laeufe: Qwen 3.5-9B liefert 107 der 119
Anforderungen, davon 75 im Modus custom mit nur drei Subagenten. Gemma
kommt auf 12. Der Modus builtin fiel bei beiden Modellen aus - drei von
drei Laeufen endeten nach einem Turn ohne einen Werkzeugaufruf. Die 13
Laeufe mit Adapter 2.3.0 bis 2.5.1 sind Artefakte der Fehlersuche und
als adapterbedingte Fehlmessungen gekennzeichnet.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Christoph Schwörer
2026-09-01 22:49:53 +02:00
co-authored by Claude Opus 5
parent 28e927013b
commit 6c5c26a2e4
416 changed files with 85993 additions and 13 deletions
+3 -1
View File
@@ -2,7 +2,7 @@
name: run-experiment
description: Führt einen Versuchs-Prompt aus einer Prompt-Datei als messbaren Headless-Lauf mit Claude Code, Codex CLI oder OpenCode (TensorX oder lokales LM Studio) aus 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.
argument-hint: <Pfad zur Prompt-Datei> <Root-Verzeichnis>
version: 12.2.0
version: 13.1.0
---
# RunExperiment – Versuchslauf mit Messprotokoll
@@ -1354,6 +1354,8 @@ der Historie unten – im selben Arbeitsschritt.
| Version | Änderung | Grund | Verwendet in |
|---|---|---|---|
| **13.1.0** | **Der Adapter ergaenzt fuer den Spiegel auch die worktree-relative Freigabeform; `analyse-anforderungen.py` erkennt Kennungen als Markdown-Ueberschrift.** Das Spiegel-Arbeitsverzeichnis liegt jetzt standardmaessig in `_meta` des Laufs (`--spiegel-basis`), `Ergebnisse` ist dort ein echtes Verzeichnis, dessen Inhalt nach dem Lauf uebernommen wird. Adapter-Version 2.5.2. | Der Spiegel allein genuegte nicht: Sechs Laeufe schrieben mit korrektem absolutem Pfad und wurden dennoch abgewiesen. Ursache war der bereits in 10.0.2 festgehaltene Befund - **OpenCode gleicht Ziele innerhalb des Repositories gegen den worktree-relativen Pfad ab**. Solange der Spiegel unter `%TEMP%` lag, griff diese Regel nicht und der Zusammenhang blieb unsichtbar; erst die Verlagerung ins Projekt machte ihn erkennbar. Beim Auswerten zeigte sich zudem, dass korrekt gefuellte Bloecke unerkannt blieben, wenn die Kennung als Ueberschrift ohne Feldnamen gesetzt war (`### StRS-001`). Sie wird nur dann als ID gewertet, wenn die Pflichtfelder unmittelbar folgen - sonst zaehlte jede Zwischenueberschrift als Anforderung. Regressionsprobe an fuenf Claude-Laeufen: 42/82/60/73/67 unveraendert. MINOR: Korrektur an Adapter und Messinstrument, keine Aenderung der Versuchsbedingung. | ab den gueltigen Laeufen der Iteration 15 bzw. 8 |
| **13.0.0** | **Spiegel-Arbeitsverzeichnis fuer den OpenCode-Adapter** (`--arbeitsverzeichnis spiegel`, Standard der LM-Studio-Matrix). Statt direkt im Codebasis-Root zu arbeiten, laeuft OpenCode in einem Verzeichnis aus Verknuepfungen: je eine Junction auf jeden Top-Level-Ordner der Codebasis, je ein Hardlink auf jede Top-Level-Datei, und `Ergebnisse` als Junction auf das Laufverzeichnis. Relative *und* absolute Ausgabepfade landen damit am richtigen Ort. Der Abbau entfernt nur die Verknuepfungen (`os.rmdir`, nie `rmtree`). `RawResult.json` fuehrt `arbeitsverzeichnis` und `arbeitswurzel`. Adapter-Version 2.3.0, zwei Regressionstests. | Sechs Laeufe der Iteration 13/6 erzeugten kein einziges Artefakt, obwohl `gemma-4-e4b` die richtigen Dateinamen bildete: Es loest `Ergebnisse/StRS.md` relativ zum Arbeitsverzeichnis auf, wo die eingefrorene Codebasis liegt - jeder Schreibversuch wurde abgewiesen. Ein umformulierter Ausgabeblock (Iteration 14/7) half nur in zwei von sechs Laeufen und entfernte den Prompt zugleich vom Wortlaut der Claude-Laeufe. Der Spiegel loest das Problem **strukturell**: Der Prompt bleibt unveraendert bei der Fassung, mit der die Claude-Laeufe gemessen wurden, und die Codebasis bleibt unberuehrt - die Verknuepfungen liegen im Spiegel, nicht im Snapshot. Eine Arbeitskopie wie beim Codex-Adapter schied aus: ueber zehn Minuten fuer 24.663 Dateien je Lauf. Verifiziert: `src` und `README.md` durch den Spiegel lesbar, relativer Schreibpfad landet im Laufverzeichnis, Abbau laesst die Ergebnisse stehen und die Quelle unveraendert. MAJOR: Der Isolationsmechanismus ist eine Versuchsbedingung; Laeufe ab dieser Version sind mit den frueheren nicht poolbar. | ab Iteration 15 (V1) bzw. 8 (V2) |
| **12.2.0** | **`analyse-anforderungen.py` erkennt Feldnamen in Markdown-Fettschrift und Modulpraefixe in IDs.** `**ID:** M003-StRS-01` wird wie `ID: StRS-01` gelesen; die Ebene wird aus der ID auch dann bestimmt, wenn ein Praefix vorangeht. Zwei neue Hilfsskripte: `lauf-uebersicht.py` verdichtet die `RawResult.json` einer Matrix zu einer Tabelle und zeigt mit `--details` die tatsaechlichen Schreibziele; `protokoll-geruest.py` erzeugt aus den Rohdaten eines Laufs das Protokollgeruest und fuellt nur belegbare Felder - Deutung und Gueltigkeit bleiben Handarbeit. | Der erste lokale Lauf mit Artefakten (`Iteration 7/.../v12.1.0-001c`) erzeugte vier regelkonform gefuellte Dateien, wurde vom Parser aber mit **0 Anforderungen** gezaehlt: Das Modell formatierte die Feldnamen als Markdown. Nach der Korrektur sind es **9**. Die Praefixregel behob zugleich eine falsche Auffaelligkeitsmeldung ('StRS-Block in StRS.md' als Fremdablage). Regressionsprobe an vier Claude-Laeufen: 42/82/60/73 Anforderungen vor und nach der Aenderung identisch - die Korrektur findet nur zusaetzlich, was zuvor uebersehen wurde. `lauf-uebersicht.py` entstand, weil `written_files` bei fehlgeleiteten Schreibversuchen schlicht leer bleibt und die Ursache so unsichtbar ist. MINOR: Korrektur am Messinstrument, keine Aenderung der Versuchsbedingung; rueckwirkend auf alle Laeufe anwendbar. | rueckwirkend; ab sofort |
| **12.1.0** | **Speicherhygiene und Kontextgroesse fuer lokale Laeufe; Modellwechsel `qwen/qwen3.8-27b` -> `qwen/qwen3.5-9b`.** Der Preflight entlaedt vor jedem Lauf **alle** Modelle (`lms unload --all`) und bricht ab, wenn neben dem angeforderten ein weiteres geladen ist. Neue Optionen `--lmstudio-context` (Standard `max`: laedt das Modellmaximum statt der Mindestgroesse), `--lmstudio-parallel` (Standard 4) und `--lmstudio-gpu` (Standard `max`). `local_runtime` fuehrt zusaetzlich `parallel_slots`, `gpu_offload` und `alleiniges_modell`. Adapter-Version 2.2.0. | Messungen vom 01.09.2026 auf einer RTX 5080 Laptop GPU (16.303 MiB): Gemma und Qwen 27B waren **gleichzeitig geladen** - 15.836 MiB belegt, 168 MiB frei, Durchsatz 0,028 Mio. Tokens/h. Nach `unload --all` laeuft Gemma mit 48,3 tok/s. Das Modellmaximum kostet fast nichts: 131.072 statt 32.768 Kontext bedeutet 6.854 statt 5.162 MiB und 46,8 statt 48,3 tok/s - vierfaches Fenster fuer 1,5 tok/s. `--parallel 4` ist gegenueber 1 messtechnisch neutral (47,7 vs. 48,3 tok/s). **Der Modellwechsel ist hardwarebedingt:** `qwen3.8-27b` belegt mit 17,74 GB Gewichten mehr, als die Karte hat; ein Generierungstest brach nach 10 Minuten ohne Ergebnis ab. Die 27B-Klasse ist auch mit kleinerer Quantisierung nicht messbar, weil der KV-Cache bei brauchbarem Kontext mehrere GB zusaetzlich fordert. `qwen3.5-9b` ist die groesste Qwen-Variante, die mit vollem Fenster hineinpasst, und laeuft wie Gemma in **Q4_K_M** - damit unterscheiden sich die beiden lokalen Modelle nur in der Groesse, nicht zusaetzlich in der Quantisierung. MINOR fuer die Ladeparameter; der Modellwechsel eroeffnet ohnehin eine neue Iteration, weil `qwen3.8-27b` keinen gueltigen Messpunkt geliefert hat. | ab der LM-Studio-Matrix in Iteration 13 (V1) bzw. 6 (V2) |
| **12.0.0** | **Die Shell-Rechte des OpenCode-Adapters werden eine Denylist statt einer Allowlist** – spiegelbildlich zu den Claude-Eintraegen: alles erlaubt ausser den ausdruecklich gesperrten schreibenden und bauenden Kommandos (`rm`, `mv`, `sed -i`, schreibende `git`-Kommandos inkl. `fetch`/`pull`/`remote`, `dotnet`, `msbuild`, `npm install`, `Remove-Item`, `Set-Content`, `Out-File` u. a.). Das Catch-all `"*": "allow"` steht zuerst, weil OpenCode die **zuletzt passende** Regel gewinnen laesst. Zusaetzlich lehnt der Adapter `--stall-timeout > 0` jetzt fuer **jeden** lokalen Provider ab, nicht nur fuer die delegierenden Modi. Adapter-Version 2.0.0, vier neue Regressionstests. | Der Claude-Adapter erlaubt ueber eine Denylist jedes nicht gesperrte Kommando, der OpenCode-Adapter nur explizit Gelistetes. Die Werkzeugfreiheit war zwischen beiden **nie aequivalent** – ein Confounder fuer jeden Werkzeugvergleich. Ausloeser war der erste Qwen-Lauf (`v11.1.0-45b1`): Dessen **einzige beide** Werkzeugaufrufe, `Get-ChildItem ... | Format-Table ...`, wurden verweigert, weil die Allowlist nur Praefixe trifft und an Pipelines scheitert. Bei Gemma war das ein Randfall (1 von 106 Aufrufen), bei Qwen legte es den Lauf still. Der zweite Ausloeser: Qwen 27B benoetigte fuer einen einzelnen Schritt mehr als 15 Minuten, sodass der Stall-Timeout auch in `solo` Modellgeschwindigkeit als Haenger wertete. **Kontrolltest am 01.09.2026 bestaetigte beide Richtungen:** `Get-ChildItem ... | Format-Table Name` lief durch, `rm opfer.txt` wurde verweigert, und die Datei blieb auf der Platte. MAJOR: Die Toolfreigabe ist eine unabhaengige Variable; Laeufe ab dieser Version sind mit allen frueheren OpenCode- und TensorX-Laeufen nicht poolbar. | ab dem naechsten OpenCode-Lauf; Iterationen 10 und 11 bleiben unter der Allowlist |