Compare commits
3
Commits
7df384f6d2
...
affde3a45f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
affde3a45f | ||
|
|
844b4e5569 | ||
|
|
f349d189c7 |
@@ -1,15 +1,15 @@
|
|||||||
---
|
---
|
||||||
name: run-experiment
|
name: run-experiment
|
||||||
description: 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.
|
description: Führt einen Versuchs-Prompt aus einer Prompt-Datei als messbaren Headless-Lauf mit Claude Code oder Codex CLI 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>
|
argument-hint: <Pfad zur Prompt-Datei> <Root-Verzeichnis>
|
||||||
version: 4.0.0
|
version: 5.0.0
|
||||||
---
|
---
|
||||||
|
|
||||||
# RunExperiment – Versuchslauf mit Messprotokoll
|
# RunExperiment – Versuchslauf mit Messprotokoll
|
||||||
|
|
||||||
Du führst einen wissenschaftlichen Versuchslauf für die Masterarbeit aus. Der Prompt aus der
|
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
|
übergebenen Datei wird als **separater Headless-Lauf** über den zum Modell passenden
|
||||||
Tokenverbrauch und Modell exakt und maschinenlesbar erfasst werden. Anschließend
|
Werkzeugadapter ausgeführt, damit Tokenverbrauch und Modell maschinenlesbar erfasst werden. Anschließend
|
||||||
schreibst du ein Messprotokoll neben die Prompt-Datei.
|
schreibst du ein Messprotokoll neben die Prompt-Datei.
|
||||||
|
|
||||||
## Parameter
|
## Parameter
|
||||||
@@ -36,10 +36,11 @@ Laufverzeichnis neben der Prompt-Datei**, niemals im Root-Verzeichnis:
|
|||||||
```
|
```
|
||||||
<Verzeichnis der Prompt-Datei>\
|
<Verzeichnis der Prompt-Datei>\
|
||||||
<NN>_Prompt.md
|
<NN>_Prompt.md
|
||||||
<ModellID>\<Agentenmodus>\<Effort>\
|
<Iteration>\<ModellID>\<Agentenmodus>\<Effort>\
|
||||||
<NN>_Lauf_<yyyy-MM-dd_HHmmss>_v<skillversion>-<id4>\
|
<NN>_Lauf_<yyyy-MM-dd_HHmmss>_v<skillversion>-<id4>\
|
||||||
Protokoll.md
|
Protokoll.md
|
||||||
RawResult.json
|
RawResult.json (adapterübergreifend normalisierte Messdaten)
|
||||||
|
RawEvents.jsonl (nur Codex: unveränderter JSONL-Ereignisstrom)
|
||||||
Stderr.log
|
Stderr.log
|
||||||
_meta\ (Laufsteuerung: combined_prompt.md, before.txt, after.txt, Zeitstempel,
|
_meta\ (Laufsteuerung: combined_prompt.md, before.txt, after.txt, Zeitstempel,
|
||||||
subagenten.md/.json, anforderungen.md/.json)
|
subagenten.md/.json, anforderungen.md/.json)
|
||||||
@@ -48,6 +49,26 @@ Laufverzeichnis neben der Prompt-Datei**, niemals im Root-Verzeichnis:
|
|||||||
|
|
||||||
**Die unabhängigen Variablen bilden die Ordnerebenen, nicht den Dateinamen:**
|
**Die unabhängigen Variablen bilden die Ordnerebenen, nicht den Dateinamen:**
|
||||||
|
|
||||||
|
- `<Iteration>` – `Iteration 1`, `Iteration 2`, … fortlaufend. Die Ebene hält Blöcke auseinander, die
|
||||||
|
unter unterschiedlichem Stand des Versuchsaufbaus **oder des Untersuchungsgegenstands**
|
||||||
|
entstanden sind. **Vor dem Anlegen die höchste vorhandene Iteration ermitteln** und entscheiden,
|
||||||
|
ob der Lauf dazugehört oder eine neue Iteration eröffnet – im Zweifel den User fragen.
|
||||||
|
|
||||||
|
Eine neue Iteration ist zu eröffnen, wenn sich etwas ändert, das Läufe **nicht mehr poolbar**
|
||||||
|
macht: der Codebasis-Snapshot, die Prompt-Version, die Werkzeugkonfiguration oder eine
|
||||||
|
MAJOR-Version dieses Skills. Reine PATCH- und MINOR-Änderungen begründen keine neue Iteration.
|
||||||
|
|
||||||
|
**Abgrenzung zur Prompt-Version.** `<Iteration>` meint die *Versuchs*iteration – eine Menge
|
||||||
|
poolbarer Läufe. Die Fassung der Prompt-Datei heißt seit Version 4.4.0 durchgängig
|
||||||
|
**Prompt-Version** (`01_Prompt.md` = Prompt-Version 01). Beides fällt nicht zusammen:
|
||||||
|
Iteration 2 und Iteration 3 laufen beide unter Prompt-Version 02 und unterscheiden sich nur
|
||||||
|
im Untersuchungsgegenstand.
|
||||||
|
|
||||||
|
Die Ebene hieß bis Version 4.3.0 `<Versuchstag>` mit Werten `Tag 1`, `Tag 2`, …. Der Name band
|
||||||
|
sie an das Kalenderdatum, obwohl sie die Vergleichbarkeit abbildet: Iteration 2 und Iteration 3
|
||||||
|
entstanden am selben Tag, unterscheiden sich aber im Untersuchungsgegenstand (Iteration 3
|
||||||
|
enthält den DB-Schema-Dump `SSMS_DB_SCHEMA.sql`, Iteration 2 nicht). Maßgeblich ist die
|
||||||
|
Vergleichbarkeit, nicht das Datum.
|
||||||
- `<ModellID>` – die an `--model` übergebene ID, z. B. `claude-sonnet-5`, `claude-opus-5`,
|
- `<ModellID>` – die an `--model` übergebene ID, z. B. `claude-sonnet-5`, `claude-opus-5`,
|
||||||
`claude-fable-5`
|
`claude-fable-5`
|
||||||
- `<Agentenmodus>` – `solo`, `builtin` oder `custom`
|
- `<Agentenmodus>` – `solo`, `builtin` oder `custom`
|
||||||
@@ -62,7 +83,7 @@ Der Verzeichnisname trägt nur noch, was den einzelnen Lauf identifiziert:
|
|||||||
|
|
||||||
**Warum Ordnerebenen statt Namensbestandteile:** Der Name wuchs mit jeder neuen unabhängigen
|
**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
|
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
|
Bedingungen navigierbar, je Zelle abzählbar (`ls "<tag>/<modell>/<modus>/<effort>" | wc -l` ergibt
|
||||||
unmittelbar die Anzahl der Messpunkte) und beim Hinzufügen einer weiteren Variable erweiterbar,
|
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
|
ohne bestehende Namen zu brechen. Die Angaben sind **redundant zum Protokoll** – bei Widerspruch
|
||||||
gilt das Protokoll.
|
gilt das Protokoll.
|
||||||
@@ -79,7 +100,8 @@ Der Skill ist zweigeteilt:
|
|||||||
- **`## Prozess`** beschreibt werkzeugneutral, **was** je Lauf zu tun und zu erheben ist. Dieser
|
- **`## Prozess`** beschreibt werkzeugneutral, **was** je Lauf zu tun und zu erheben ist. Dieser
|
||||||
Teil gilt unabhängig davon, mit welchem LLM oder welcher CLI gearbeitet wird.
|
Teil gilt unabhängig davon, mit welchem LLM oder welcher CLI gearbeitet wird.
|
||||||
- **`## Werkzeugadapter`** beschreibt **wie** das mit einem konkreten Werkzeug umgesetzt wird.
|
- **`## Werkzeugadapter`** beschreibt **wie** das mit einem konkreten Werkzeug umgesetzt wird.
|
||||||
Derzeit ist nur der Adapter für Claude Code ausgearbeitet.
|
Ausgearbeitet sind Adapter für Claude Code und Codex CLI. Konkrete Flags und Rohfelder sind
|
||||||
|
ausschließlich dem gewählten Adapterabschnitt zu entnehmen.
|
||||||
|
|
||||||
**Arbeitsteilung mit der Prompt-Datei:** Der Prompt enthält ausschließlich die *Analyseanweisung*
|
**Arbeitsteilung mit der Prompt-Datei:** Der Prompt enthält ausschließlich die *Analyseanweisung*
|
||||||
und ist damit von jedem LLM verwendbar. Alles Werkzeug- und Ablaufbezogene – verfügbare
|
und ist damit von jedem LLM verwendbar. Alles Werkzeug- und Ablaufbezogene – verfügbare
|
||||||
@@ -91,9 +113,20 @@ per stdin übergebenen Text angehängt (siehe Schritt „Prompt zusammenstellen"
|
|||||||
|
|
||||||
### 1. Vorbereitung
|
### 1. Vorbereitung
|
||||||
|
|
||||||
1. Prompt-Datei lesen. Existiert sie nicht: abbrechen und den User informieren.
|
1. **Prompt-Datei bestimmen und lesen.** Nennt der User eine Datei ausdrücklich, gilt diese.
|
||||||
2. Aus dem Metadaten-Block der Prompt-Datei (falls vorhanden) Versuch/Iteration übernehmen.
|
Andernfalls im Versuchsordner die **höchste Prompt-Versionsnummer** wählen (`02_Prompt.md` vor
|
||||||
3. **CLI-Pfad auflösen.** Unter Windows liegt `claude` in der Regel **nicht im PATH**. Erst
|
`01_Prompt.md`) und die getroffene Wahl im Abschlussbericht nennen. Existiert die Datei
|
||||||
|
nicht: abbrechen und den User informieren.
|
||||||
|
|
||||||
|
Die gewählte Datei wird mit Pfad **und** SHA-256 ins Protokoll übernommen. Ältere
|
||||||
|
Prompt-Versionen bleiben unverändert liegen – sie sind der Beleg dafür, unter welcher Fassung
|
||||||
|
frühere Läufe entstanden sind, und dürfen nicht nachträglich angepasst werden.
|
||||||
|
2. Aus dem Metadaten-Block der Prompt-Datei (falls vorhanden) Versuch/Prompt-Version übernehmen.
|
||||||
|
3. **Werkzeugadapter bestimmen und CLI-Pfad auflösen.** Die Modell-ID entscheidet eindeutig:
|
||||||
|
`claude-*` verwendet Claude Code, OpenAI-IDs wie `gpt-*` oder `o*` verwenden Codex CLI.
|
||||||
|
Keine Modell-ID an eine CLI übergeben, die sie nicht unterstützt.
|
||||||
|
|
||||||
|
Unter Windows liegt `claude` in der Regel **nicht im PATH**. Erst
|
||||||
`Get-Command claude -ErrorAction SilentlyContinue` versuchen; schlägt das fehl, auf die
|
`Get-Command claude -ErrorAction SilentlyContinue` versuchen; schlägt das fehl, auf die
|
||||||
VSCode-Extension zurückfallen und die höchste Versionsnummer wählen:
|
VSCode-Extension zurückfallen und die höchste Versionsnummer wählen:
|
||||||
```powershell
|
```powershell
|
||||||
@@ -103,13 +136,17 @@ per stdin übergebenen Text angehängt (siehe Schritt „Prompt zusammenstellen"
|
|||||||
Sort-Object FullName | Select-Object -Last 1 -ExpandProperty FullName
|
Sort-Object FullName | Select-Object -Last 1 -ExpandProperty FullName
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
Findet sich keine ausführbare Datei: abbrechen und den User informieren. Den aufgelösten
|
Für OpenAI-Modelle entsprechend `Get-Command codex -ErrorAction SilentlyContinue` verwenden;
|
||||||
Pfad fürs Protokoll festhalten.
|
als Fallback die höchste VS-Code-Extension unter
|
||||||
|
`$env:USERPROFILE\.vscode\extensions\openai.chatgpt-*-win32-x64\bin\windows-x86_64\codex.exe`
|
||||||
|
wählen. Findet sich die benötigte ausführbare Datei nicht: abbrechen und den User informieren.
|
||||||
|
Adapter und aufgelösten Pfad fürs Protokoll festhalten.
|
||||||
4. **Modell beim User erfragen.** Hat der User das Modell nicht bereits im Aufruf genannt,
|
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
|
**immer** per `AskUserQuestion` nachfragen – auch dann, wenn frühere Läufe derselben
|
||||||
Versuchsreihe ein bestimmtes Modell verwendet haben. Es gibt bewusst keinen Default.
|
Versuchsreihe ein bestimmtes Modell verwendet haben. Es gibt bewusst keinen Default.
|
||||||
|
|
||||||
Als Optionen die vollen Modell-IDs anbieten, nicht die Kurzformen:
|
Als Optionen die vollen Modell-IDs anbieten, nicht die Kurzformen. Nur aktuell dokumentierte
|
||||||
|
und von der installierten CLI angebotene IDs aufnehmen:
|
||||||
|
|
||||||
| Modell-ID | Einordnung |
|
| Modell-ID | Einordnung |
|
||||||
|---|---|
|
|---|---|
|
||||||
@@ -118,6 +155,12 @@ per stdin übergebenen Text angehängt (siehe Schritt „Prompt zusammenstellen"
|
|||||||
| `claude-fable-5` | schnell und günstig |
|
| `claude-fable-5` | schnell und günstig |
|
||||||
| `claude-haiku-4-5-20251001` | günstigstes Modell |
|
| `claude-haiku-4-5-20251001` | günstigstes Modell |
|
||||||
|
|
||||||
|
| OpenAI-Modell-ID | Einordnung |
|
||||||
|
|---|---|
|
||||||
|
| `gpt-5.6-sol` | stärkstes Modell der GPT-5.6-Familie, 1.050.000 Kontexttokens |
|
||||||
|
| `gpt-5.6-terra` | ausgewogenes Verhältnis aus Leistung und Verbrauch |
|
||||||
|
| `gpt-5.6-luna` | schnelle und günstige GPT-5.6-Variante |
|
||||||
|
|
||||||
In der Frage den letzten verwendeten Stand nennen, damit der User bewusst wechseln oder
|
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").
|
bewusst wiederholen kann (z. B. „Lauf 3 lief mit `claude-sonnet-5`, 11.516.200 Tokens, 23:40").
|
||||||
|
|
||||||
@@ -126,6 +169,11 @@ per stdin übergebenen Text angehängt (siehe Schritt „Prompt zusammenstellen"
|
|||||||
Versuchsbedingung nicht reproduzierbar. Für ein 1-Mio.-Token-Fenster die Variante mit
|
Versuchsbedingung nicht reproduzierbar. Für ein 1-Mio.-Token-Fenster die Variante mit
|
||||||
`[1m]`-Suffix wählen (z. B. `claude-opus-5[1m]`).
|
`[1m]`-Suffix wählen (z. B. `claude-opus-5[1m]`).
|
||||||
|
|
||||||
|
Für OpenAI ebenfalls keine Familienaliase wie `gpt-5.6` verwenden. Die gewünschte Variante
|
||||||
|
vollständig binden, beispielsweise `gpt-5.6-sol`. Vor einem Lauf die Modell-ID gegen die
|
||||||
|
aktuelle offizielle OpenAI-Modelldokumentation und, soweit verfügbar, den lokalen
|
||||||
|
`codex debug models`-Katalog prüfen.
|
||||||
|
|
||||||
Weicht das gewählte Modell vom letzten Lauf ab, im Protokoll unter „Anmerkungen" als
|
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.
|
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
|
5. **Agentenmodus beim User erfragen.** Wie beim Modell: kein Default, immer nachfragen, wenn
|
||||||
@@ -167,32 +215,47 @@ per stdin übergebenen Text angehängt (siehe Schritt „Prompt zusammenstellen"
|
|||||||
der Prompt per SHA-256 gehasht und im Protokoll geführt. So bleibt der eingefrorene Snapshot
|
der Prompt per SHA-256 gehasht und im Protokoll geführt. So bleibt der eingefrorene Snapshot
|
||||||
unangetastet und die Agentenkonfiguration ist eine dokumentierte, versionierte
|
unangetastet und die Agentenkonfiguration ist eine dokumentierte, versionierte
|
||||||
Versuchsbedingung. Format siehe `claude --help` zu `--agents`.
|
Versuchsbedingung. Format siehe `claude --help` zu `--agents`.
|
||||||
|
|
||||||
|
**Codex-Adapter in Version 5.0.0:** ausschließlich `solo` ist freigegeben und wird doppelt
|
||||||
|
mit `--disable multi_agent` sowie `-c agents.enabled=false` erzwungen. Bei `builtin` oder
|
||||||
|
`custom` abbrechen und mitteilen, dass dieser Adaptermodus noch nicht verifiziert ist. Eine
|
||||||
|
stillschweigende Annäherung an Claude-Agentendefinitionen wäre keine reproduzierbare Bedingung.
|
||||||
6. **Effort beim User erfragen.** Kein Default, immer nachfragen, wenn der User die Stufe nicht
|
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`.
|
bereits im Aufruf genannt hat. Stufen: `low`, `medium`, `high`, `xhigh`, `max`.
|
||||||
Übergabe per `--effort <stufe>`.
|
Übergabe bei Claude per `--effort <stufe>`, bei Codex per
|
||||||
|
`-c model_reasoning_effort=\"<stufe>\"`.
|
||||||
|
|
||||||
In der Frage den bisherigen Stand nennen. **Alle Läufe bis einschließlich Lauf B liefen auf
|
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
|
`high`** – geerbt aus der Sitzungseinstellung, nicht bewusst gesetzt; der Wert wurde
|
||||||
nachträglich aus den Transkripten belegt. Wer die Stufe wechselt, ändert die
|
nachträglich aus den Transkripten belegt. Wer die Stufe wechselt, ändert die
|
||||||
Versuchsbedingung und macht den Lauf mit den bisherigen unvergleichbar.
|
Versuchsbedingung und macht den Lauf mit den bisherigen unvergleichbar.
|
||||||
|
|
||||||
**Wichtig – der Effort ist aus `RawResult.json` nicht rekonstruierbar.** Das Ergebnisobjekt
|
**Claude-spezifisch:** Der Effort ist aus dessen `RawResult.json` nicht rekonstruierbar. Das Ergebnisobjekt
|
||||||
enthält kein `effort`-Feld. Nur das Session-Transkript hält ihn je Nachricht fest
|
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
|
(`"effort": "high"`). Fehlt er im Protokoll, ist die Bedingung nachträglich allein über das
|
||||||
Transkript belegbar – und das nur, solange die Session persistiert ist.
|
Transkript belegbar – und das nur, solange die Session persistiert ist.
|
||||||
7. Messgrößen VOR dem Lauf erfassen (PowerShell):
|
7. Messgrößen VOR dem Lauf erfassen (PowerShell):
|
||||||
- Startzeit: `Get-Date -Format o`
|
- Startzeit: `Get-Date -Format o`
|
||||||
- SHA-256 der Prompt-Datei: `(Get-FileHash <datei> -Algorithm SHA256).Hash`
|
- SHA-256 der Prompt-Datei: `(Get-FileHash <datei> -Algorithm SHA256).Hash`
|
||||||
- Claude-Code-Version: `& $claude --version`
|
- Adapter und CLI-Version: `& $cli --version`
|
||||||
- Git-Zustand des Root-Verzeichnisses: `git -C <root> rev-parse HEAD` und
|
- Git-Zustand des Root-Verzeichnisses: `git -C <root> rev-parse HEAD` und
|
||||||
`git -C <root> status --porcelain` (dirty ja/nein)
|
`git -C <repo> status --porcelain -- <pfad-des-roots>` (dirty ja/nein).
|
||||||
|
**Immer pfadskopiert prüfen.** Liegt die Codebasis als Unterverzeichnis im Arbeitsrepo
|
||||||
|
(seit Commit `f045b99a` der Fall, davor ein eigenes Repo per Gitlink), meldet ein
|
||||||
|
unskopiertes `git -C <root> status --porcelain` den Status des **gesamten** Arbeitsrepos –
|
||||||
|
einschließlich aller Versuchsordner. Der Vorher/Nachher-Vergleich schlägt dann bei jedem
|
||||||
|
Lauf falsch an.
|
||||||
- Git-Commit dieses Repos (Stand der Prompt-Datei): `git rev-parse HEAD`
|
- Git-Commit dieses Repos (Stand der Prompt-Datei): `git rev-parse HEAD`
|
||||||
8. **Kollisionsfreies Laufverzeichnis anlegen.** Sekundengenau, mit Agentenmodus und
|
8. **Kollisionsfreies Laufverzeichnis anlegen.** Sekundengenau, mit Agentenmodus und
|
||||||
Zufalls-ID; bei Namenskollision neu würfeln:
|
Zufalls-ID; bei Namenskollision neu würfeln:
|
||||||
```powershell
|
```powershell
|
||||||
# Bedingungen werden Ordnerebenen, nicht Namensbestandteile
|
# Bedingungen werden Ordnerebenen, nicht Namensbestandteile
|
||||||
$zelle = Join-Path (Join-Path $modell $modus) $effort
|
# Iteration ermitteln: hoechste vorhandene Iteration, sonst 'Iteration 1'
|
||||||
$skillVer = 'v4.0.0' # entspricht version: im Frontmatter dieses Skills
|
$iterationen = Get-ChildItem "<promptverzeichnis>" -Directory -Filter 'Iteration *' -EA SilentlyContinue |
|
||||||
|
Sort-Object { [int]($_.Name -replace '\D','') }
|
||||||
|
$iteration = if ($iterationen) { $iterationen[-1].Name } else { 'Iteration 1' }
|
||||||
|
$zelle = Join-Path (Join-Path (Join-Path $iteration $modell) $modus) $effort
|
||||||
|
$skillVer = 'v5.0.0' # entspricht version: im Frontmatter dieses Skills
|
||||||
do {
|
do {
|
||||||
$id4 = '{0:x4}' -f (Get-Random -Maximum 65536)
|
$id4 = '{0:x4}' -f (Get-Random -Maximum 65536)
|
||||||
$lauf = Join-Path "<promptverzeichnis>\$zelle" "<NN>_Lauf_$(Get-Date -Format 'yyyy-MM-dd_HHmmss')_${skillVer}-$id4"
|
$lauf = Join-Path "<promptverzeichnis>\$zelle" "<NN>_Lauf_$(Get-Date -Format 'yyyy-MM-dd_HHmmss')_${skillVer}-$id4"
|
||||||
@@ -205,7 +268,8 @@ per stdin übergebenen Text angehängt (siehe Schritt „Prompt zusammenstellen"
|
|||||||
nicht der gemeinsame Scratchpad:
|
nicht der gemeinsame Scratchpad:
|
||||||
```powershell
|
```powershell
|
||||||
# Leerwertsicher: -Value erzwingt das Schreiben auch bei sauberem Root.
|
# Leerwertsicher: -Value erzwingt das Schreiben auch bei sauberem Root.
|
||||||
Set-Content -Path "$lauf\_meta\before.txt" -Value (git -C <root> status --porcelain | Out-String)
|
Set-Content -Path "$lauf\_meta\before.txt" `
|
||||||
|
-Value (git -C <repo> status --porcelain -- <pfad-des-roots> | Out-String)
|
||||||
```
|
```
|
||||||
**Nicht** `git ... | Set-Content <datei>` verwenden: Ist die Pipeline leer (sauberes Root),
|
**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
|
schreibt `Set-Content` die Datei nicht und lässt einen alten Inhalt stehen. Der
|
||||||
@@ -283,9 +347,26 @@ Schreibe ALLE zu erzeugenden Ergebnisdateien in das Verzeichnis
|
|||||||
Verändere keine Dateien im Arbeitsverzeichnis (der analysierten Codebasis).
|
Verändere keine Dateien im Arbeitsverzeichnis (der analysierten Codebasis).
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Codex-Abweichung bei Block 2.** Der Codex-Adapter läuft mit einem technisch erzwungenen
|
||||||
|
`read-only`-Sandboxmodus. Er kann deshalb auch das externe Laufverzeichnis nicht direkt als
|
||||||
|
Agent beschreiben. Block 2 wird dort durch folgende strukturierte Rückgabeanweisung ersetzt;
|
||||||
|
die CLI erzwingt `codex-output-schema.json`, anschließend materialisiert
|
||||||
|
`normalise-codex-result.py` die Dateien:
|
||||||
|
|
||||||
|
```
|
||||||
|
### Ergebnisausgabe (überschreibt anderslautende Pfadangaben oben)
|
||||||
|
Verändere keine Dateien. Gib alle geforderten Ergebnisdateien im vorgegebenen JSON-Schema zurück.
|
||||||
|
Jeder Eintrag in `files` enthält unter `path` einen relativen Pfad innerhalb von `Ergebnisse`
|
||||||
|
und unter `content` den vollständigen Dateiinhalt. `summary` enthält nur eine kurze Laufzusammenfassung.
|
||||||
|
```
|
||||||
|
|
||||||
### 3. Ausführung (Headless-Lauf)
|
### 3. Ausführung (Headless-Lauf)
|
||||||
|
|
||||||
Dann den kombinierten Prompt per stdin an `claude -p` übergeben. `--add-dir` gibt dem
|
Den Adapter anhand der Modell-ID wählen. Der folgende Aufruf ist **ausschließlich der
|
||||||
|
Claude-Code-Adapter**. Der Codex-Aufruf steht vollständig unter `Adapter: Codex CLI` und darf
|
||||||
|
nicht mit Claude-Flags vermischt werden.
|
||||||
|
|
||||||
|
Den kombinierten Prompt per stdin an `claude -p` übergeben. `--add-dir` gibt dem
|
||||||
Headless-Lauf Schreibrecht auf das Laufverzeichnis außerhalb seines Arbeitsverzeichnisses.
|
Headless-Lauf Schreibrecht auf das Laufverzeichnis außerhalb seines Arbeitsverzeichnisses.
|
||||||
Versuchsläufe können lange dauern – **immer als Background-Task starten** (`run_in_background`),
|
Versuchsläufe können lange dauern – **immer als Background-Task starten** (`run_in_background`),
|
||||||
nicht mit Foreground-Timeout arbeiten:
|
nicht mit Foreground-Timeout arbeiten:
|
||||||
@@ -336,7 +417,7 @@ Bedeutung der Flags:
|
|||||||
| `--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. |
|
| `--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 |
|
| `--strict-mcp-config` | zweite Absicherung gegen MCP-Server aus Projekt- oder User-Konfiguration |
|
||||||
| `--permission-mode acceptEdits` | Schreibrechte für die Ergebnisdateien im Laufverzeichnis |
|
| `--permission-mode acceptEdits` | Schreibrechte für die Ergebnisdateien im Laufverzeichnis |
|
||||||
| `--allowedTools "Bash" "PowerShell"` | **Shell-Zugriff ohne Rückfrage** – Standard seit Iteration 02 |
|
| `--allowedTools "Bash" "PowerShell"` | **Shell-Zugriff ohne Rückfrage** – Standard seit Prompt-Version 02 |
|
||||||
| `--disallowedTools <Denylist>` | schreibende und bauende Kommandos gesperrt; Deny hat Vorrang vor Allow |
|
| `--disallowedTools <Denylist>` | schreibende und bauende Kommandos gesperrt; Deny hat Vorrang vor Allow |
|
||||||
| `--add-dir "$lauf"` | Schreibziel außerhalb des Arbeitsverzeichnisses |
|
| `--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` |
|
| `@agentFlags` | Agentenmodus aus Schritt 5: `solo` sperrt `Task`/`Agent`, `builtin` fügt nichts hinzu, `custom` übergibt `--agents` |
|
||||||
@@ -389,8 +470,9 @@ Regeln:
|
|||||||
|
|
||||||
### 4. Ergebnis auswerten
|
### 4. Ergebnis auswerten
|
||||||
|
|
||||||
`RawResult.json` im Laufverzeichnis lesen und defensiv parsen (Feldnamen können je nach Claude-Code-Version
|
`RawResult.json` im Laufverzeichnis lesen und defensiv parsen. Beim Claude-Adapter ist dies die
|
||||||
leicht abweichen). Relevante Felder:
|
unveränderte CLI-Antwort; beim Codex-Adapter erzeugt `normalise-codex-result.py` diese Datei aus
|
||||||
|
`RawEvents.jsonl` und `_meta\final_response.json`. Relevante Claude-Felder:
|
||||||
|
|
||||||
| Feld | Bedeutung |
|
| Feld | Bedeutung |
|
||||||
|---|---|
|
|---|---|
|
||||||
@@ -429,10 +511,10 @@ und die Summe der Transkript-Nachrichten ist **kein** gültiges Verbrauchsmaß (
|
|||||||
|
|
||||||
Zwei Auswertungsfallen:
|
Zwei Auswertungsfallen:
|
||||||
- **`usage` erfasst ausschließlich den Hauptagenten.** Für den abrechnungsrelevanten
|
- **`usage` erfasst ausschließlich den Hauptagenten.** Für den abrechnungsrelevanten
|
||||||
Gesamtverbrauch ist `modelUsage` über alle Modell-IDs zu summieren. In Iteration 01 standen
|
Gesamtverbrauch ist `modelUsage` über alle Modell-IDs zu summieren. In Prompt-Version 01 standen
|
||||||
105.959 Output-Tokens in `usage` gegenüber 249.040 in `modelUsage`.
|
105.959 Output-Tokens in `usage` gegenüber 249.040 in `modelUsage`.
|
||||||
- **`duration_api_ms` kann die Wanduhrzeit übersteigen**, wenn Subagenten parallel laufen
|
- **`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
|
(Prompt-Version 01: 47:05 API gegenüber 31:31 Wanduhr). Das ist kein Widerspruch, sondern die
|
||||||
Summe nebenläufiger Anfragen – im Protokoll entsprechend einordnen.
|
Summe nebenläufiger Anfragen – im Protokoll entsprechend einordnen.
|
||||||
|
|
||||||
**Pflichtprüfung: tatsächlich eingesetzte Modelle.** Nach jedem Lauf die Schlüssel von
|
**Pflichtprüfung: tatsächlich eingesetzte Modelle.** Nach jedem Lauf die Schlüssel von
|
||||||
@@ -479,7 +561,16 @@ Es schreibt `_meta\subagenten.md` (lesbar, mit vollständigem Prompt je Subagent
|
|||||||
`subagent_type`, `description`, Hintergrund-Flag, Prompt-Länge und Länge des zurückgelieferten
|
`subagent_type`, `description`, Hintergrund-Flag, Prompt-Länge und Länge des zurückgelieferten
|
||||||
Ergebnisses.
|
Ergebnisses.
|
||||||
|
|
||||||
**Plausibilitätskontrolle:** Das Skript vergleicht die gefundene Anzahl mit
|
**Abgewiesene Starts sind keine Subagenten.** Erreicht der Hauptagent das
|
||||||
|
Nebenläufigkeitslimit (20 gleichzeitige Subagenten), erscheint der Aufruf im Transkript wie ein
|
||||||
|
regulärer Start, liefert aber nur die Absage „Concurrent subagent limit reached" zurück und zählt
|
||||||
|
**nicht** in `spawned`. Das Skript trennt beide Fälle und weist die Absagen getrennt aus; ohne
|
||||||
|
diese Trennung meldet der Abgleich eine Abweichung, die es nicht gibt (Lauf
|
||||||
|
`Iteration 3/…/125032_v4.4.0-fb24`: 21 gefundene Aufrufe gegenüber 13 erwarteten – die Differenz
|
||||||
|
waren 8 Absagen). Die Zahl der Absagen ist selbst eine Messgröße: Sie zeigt, wie viel stärker der
|
||||||
|
Agent parallelisieren wollte, als das Werkzeug zuließ.
|
||||||
|
|
||||||
|
**Plausibilitätskontrolle:** Das Skript vergleicht die Anzahl der **echten** Starts mit
|
||||||
`subagent_stats.spawned` minus `spawned_by_subagents`. Im Haupttranskript stehen nämlich nur die
|
`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)
|
**direkt** vom Hauptagenten gestarteten Subagenten – von Subagenten gestartete (`max_depth` > 1)
|
||||||
liegen in deren eigenen Transkripten. Bei Abweichung setzt das Skript eine Warnung in
|
liegen in deren eigenen Transkripten. Bei Abweichung setzt das Skript eine Warnung in
|
||||||
@@ -495,18 +586,26 @@ Vorgabe delegiert – gegenüber den vorformulierten Agenten aus `--agents`.
|
|||||||
**Anforderungen auswerten** – der inhaltliche Ertrag des Laufs, nicht nur sein Aufwand:
|
**Anforderungen auswerten** – der inhaltliche Ertrag des Laufs, nicht nur sein Aufwand:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
python "<skillverzeichnis>nalyse-anforderungen.py" "<laufverzeichnis>"
|
python "<skillverzeichnis>\analyse-anforderungen.py" "<laufverzeichnis>"
|
||||||
```
|
```
|
||||||
|
|
||||||
Das Skript parst das im Prompt vorgegebene Blockformat (`ID:`, `Typ:`, `Belege:`, `Status:` …)
|
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`
|
aus `Ergebnisse\StRS.md`, `SyRS.md` und `SwRS.md` und schreibt `_meta\anforderungen.md`
|
||||||
(fertiger Protokollabschnitt) sowie `_metanforderungen.json` (maschinenlesbar). Erhoben werden:
|
(fertiger Protokollabschnitt) sowie `_meta\anforderungen.json` (maschinenlesbar). Erhoben werden:
|
||||||
|
|
||||||
- **Verteilung** über die drei Ebenen
|
- **Verteilung** über die drei Ebenen
|
||||||
- **Anforderungstypen** (funktional, Sicherheit, Daten, Schnittstelle …)
|
- **Anforderungstypen** (funktional, Sicherheit, Daten, Schnittstelle …)
|
||||||
- **Belegqualität**: Anzahl der Belege, Aufteilung `PRIMÄR`/`SEKUNDÄR`/`KONTEXT`, Median je
|
- **Belegqualität**: Anzahl der Belege, Aufteilung `PRIMÄR`/`SEKUNDÄR`/`KONTEXT`, Median je
|
||||||
Anforderung, Anteil mit mindestens einem Primärbeleg
|
Anforderung, Anteil mit mindestens einem Primärbeleg
|
||||||
- **Status**: belegt, `[HYPOTHESE]`, Workaround, Konsolidierungskandidaten
|
- **Status**: belegt, `[HYPOTHESE]`, Workaround, Konsolidierungskandidaten
|
||||||
|
**Die Ebene einer Anforderung wird nicht aus dem Dateinamen abgeleitet.** Maßgeblich ist das
|
||||||
|
Feld `Ebene:` des Blocks, hilfsweise das ID-Präfix, erst zuletzt die Datei. Agenten legen Blöcke
|
||||||
|
regelmäßig in der Datei einer anderen Ebene ab – im Lauf `Iteration 2/…/094250_v4.2.1-c69e` standen
|
||||||
|
12 StRS- und 5 SyRS-Blöcke in `SwRS.md`. Wird nach Datei gezählt, ist die Verteilungstabelle
|
||||||
|
falsch, obwohl die Gesamtzahl stimmt. Das Skript weist eine solche Fremdablage als eigene
|
||||||
|
Auffälligkeit unter der Verteilungstabelle aus; sie ist ein Befund zur **Set-Qualität**, weil die
|
||||||
|
Dreiteilung dann nicht mehr an der Dateistruktur ablesbar ist.
|
||||||
|
|
||||||
- **Regelkonformität** – geprüft wird gegen die Vorgaben des Prompts selbst:
|
- **Regelkonformität** – geprüft wird gegen die Vorgaben des Prompts selbst:
|
||||||
Belegpflicht (jede Anforderung ≥ 1 Beleg), risikobasierte Priorisierung (Sicherheit,
|
Belegpflicht (jede Anforderung ≥ 1 Beleg), risikobasierte Priorisierung (Sicherheit,
|
||||||
Abrechnung, Berechtigungen brauchen `PRIMÄR` **oder** `[HYPOTHESE]`), Verifizierbarkeit
|
Abrechnung, Berechtigungen brauchen `PRIMÄR` **oder** `[HYPOTHESE]`), Verifizierbarkeit
|
||||||
@@ -532,8 +631,9 @@ Der erzeugte Abschnitt wird **unverändert** als `## Gefundene Anforderungen` in
|
|||||||
übernommen, zwischen `## Ergebnis` und den Vergleichs- bzw. Anmerkungsabschnitten.
|
übernommen, zwischen `## Ergebnis` und den Vergleichs- bzw. Anmerkungsabschnitten.
|
||||||
|
|
||||||
Erzeugte Dateien: Inhalt von `<laufverzeichnis>\Ergebnisse\` auflisten. Zusätzlich prüfen,
|
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`
|
ob das Root unverändert blieb: `git -C <repo> status --porcelain -- <pfad-des-roots>` – mit
|
||||||
vergleichen (Nachher-Stand nach `$lauf\_metafter.txt`) – Abweichungen als Auffälligkeit
|
**demselben Pfadfilter wie in Abschnitt 1** – gegen `before.txt`
|
||||||
|
vergleichen (Nachher-Stand nach `$lauf\_meta\after.txt`) – Abweichungen als Auffälligkeit
|
||||||
ins Protokoll. Beim Vergleich Zeilenenden
|
ins Protokoll. Beim Vergleich Zeilenenden
|
||||||
normalisieren (`before.txt` entsteht je nach Werkzeug mit CRLF, der Nachher-Stand mit LF),
|
normalisieren (`before.txt` entsteht je nach Werkzeug mit CRLF, der Nachher-Stand mit LF),
|
||||||
sonst meldet ein naiver `diff` alle Zeilen als geändert.
|
sonst meldet ein naiver `diff` alle Zeilen als geändert.
|
||||||
@@ -545,10 +645,11 @@ Als `Protokoll.md` ins Laufverzeichnis, neben `RawResult.json` und `Stderr.log`.
|
|||||||
Vorlage:
|
Vorlage:
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
# Messprotokoll – <Versuch> – Iteration <NN>
|
# Messprotokoll – <Versuch> – Prompt-Version <NN>
|
||||||
|
|
||||||
## Lauf
|
## Lauf
|
||||||
- **Prompt-Datei:** <relativer Pfad>
|
- **Prompt-Datei:** <relativer Pfad>
|
||||||
|
- **Prompt-Version:** <Nummer aus dem Dateinamen; bei mehreren vorhandenen Fassungen begründen, warum diese gewählt wurde>
|
||||||
- **SHA-256 (Prompt):** <hash>
|
- **SHA-256 (Prompt):** <hash>
|
||||||
- **Startzeit:** <ISO 8601>
|
- **Startzeit:** <ISO 8601>
|
||||||
- **Endzeit:** <ISO 8601>
|
- **Endzeit:** <ISO 8601>
|
||||||
@@ -560,15 +661,18 @@ Vorlage:
|
|||||||
|
|
||||||
## Werkzeugkonfiguration
|
## Werkzeugkonfiguration
|
||||||
- **Skill-Version:** <version aus dem Frontmatter dieses Skills>
|
- **Skill-Version:** <version aus dem Frontmatter dieses Skills>
|
||||||
- **Claude-Code-Version:** <version>
|
- **Werkzeugadapter:** <Claude Code | Codex CLI>
|
||||||
- **CLI-Pfad:** <aufgelöster Pfad zur claude.exe>
|
- **CLI-Version:** <version>
|
||||||
|
- **CLI-Pfad:** <aufgelöster Pfad zur ausführbaren Datei>
|
||||||
- **Modell (angefordert):** <Wert von `--model`>
|
- **Modell (angefordert):** <Wert von `--model`>
|
||||||
- **Modelle (tatsächlich eingesetzt):** <alle Schlüssel aus `modelUsage` mit Tokenanteil>
|
- **Modelle (tatsächlich eingesetzt):** <alle Schlüssel aus `modelUsage` mit Tokenanteil |
|
||||||
- **Kontrolle Modell:** <bestanden | **verletzt**: nicht angefordertes Modell <ID> mit <N> Tokens>
|
nicht erfasst: Codex-JSONL nennt das tatsächlich bediente Modell nicht>
|
||||||
|
- **Kontrolle Modell:** <bestanden | **verletzt**: nicht angefordertes Modell <ID> mit <N> Tokens |
|
||||||
|
nicht prüfbar: Codex-JSONL enthält keine tatsächliche Modell-ID>
|
||||||
- **Effort:** <low | medium | high | xhigh | max> (per `--effort` gesetzt; Gegenprobe im
|
- **Effort:** <low | medium | high | xhigh | max> (per `--effort` gesetzt; Gegenprobe im
|
||||||
Transkript-Feld `effort`)
|
Transkript-Feld `effort`)
|
||||||
- **Laufverzeichnis-ID:** `v<skillversion>-<id4>` aus dem Verzeichnisnamen
|
- **Laufverzeichnis-ID:** `v<skillversion>-<id4>` aus dem Verzeichnisnamen
|
||||||
- **Ablage:** `<ModellID>/<Agentenmodus>/<Effort>/`
|
- **Ablage:** `<Iteration>/<ModellID>/<Agentenmodus>/<Effort>/`
|
||||||
- **Parallele Läufe:** <nein | ja: welche Laufverzeichnisse liefen zeitgleich>
|
- **Parallele Läufe:** <nein | ja: welche Laufverzeichnisse liefen zeitgleich>
|
||||||
- **Agentenmodus:** <solo (V1) | builtin (V1b) | custom (V2)>; bei `custom` zusätzlich
|
- **Agentenmodus:** <solo (V1) | builtin (V1b) | custom (V2)>; bei `custom` zusätzlich
|
||||||
Pfad und SHA-256 der Agentendefinitionen
|
Pfad und SHA-256 der Agentendefinitionen
|
||||||
@@ -576,9 +680,9 @@ Vorlage:
|
|||||||
- **Sampling-Parameter:** <Temperatur u. a. | nicht steuerbar>
|
- **Sampling-Parameter:** <Temperatur u. a. | nicht steuerbar>
|
||||||
- **Nur bei lokalem Modellbetrieb:** Inferenz-Runtime samt Version, Quantisierungsstufe des
|
- **Nur bei lokalem Modellbetrieb:** Inferenz-Runtime samt Version, Quantisierungsstufe des
|
||||||
Modell-Builds
|
Modell-Builds
|
||||||
- **Permission-Mode:** <acceptEdits | ...>
|
- **Permission-/Sandbox-Modus:** <acceptEdits | read-only / approval never | ...>
|
||||||
- **Toolfreigabe:** `--allowedTools <wörtlich>` / `--disallowedTools <wörtlich>`
|
- **Toolfreigabe:** <adapterabhängige Flags wörtlich>
|
||||||
- **Isolationsmechanismus:** <--safe-mode, --strict-mcp-config, ggf. --setting-sources>
|
- **Isolationsmechanismus:** <adapterabhängige Flags wörtlich>
|
||||||
- **MCP-Server / Agentendateien:** <keine – aus dem Snapshot entfernt, zusätzlich --safe-mode | Liste>
|
- **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>
|
- **Subagenten:** <Anzahl und Typ aus `subagent_stats`, z. B. 8 × Explore, 0 fehlgeschlagen>
|
||||||
- **Verschachtelung:** `spawned` = <N>, davon `spawned_by_subagents` = <M>, `max_depth` = <D>.
|
- **Verschachtelung:** `spawned` = <N>, davon `spawned_by_subagents` = <M>, `max_depth` = <D>.
|
||||||
@@ -620,9 +724,13 @@ Das ist die **berichtete Aufwandsgröße** der Versuchsreihe. `total_cost_usd` b
|
|||||||
`RawResult.json` erhalten, wird aber nicht ins Protokoll übernommen: Token sind modell- und
|
`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.
|
preisunabhängig und bleiben damit über Preisänderungen und Modellwechsel hinweg vergleichbar.
|
||||||
|
|
||||||
|
**Codex-Semantik:** `cached_input_tokens` ist eine Teilmenge von `input_tokens` und wird nicht
|
||||||
|
erneut addiert. Dort gilt `Tokens gesamt = input_tokens + output_tokens`; Reasoning-Tokens sind
|
||||||
|
eine Teilmenge der Output-Tokens. Cache-Write-Tokens werden von `codex exec --json` nicht geliefert.
|
||||||
|
|
||||||
## Gefundene Anforderungen
|
## Gefundene Anforderungen
|
||||||
|
|
||||||
<unverändert aus `_metanforderungen.md` übernehmen – Verteilung, Typen, Belegqualität,
|
<unverändert aus `_meta\anforderungen.md` übernehmen – Verteilung, Typen, Belegqualität,
|
||||||
Status, Regelkonformität>
|
Status, Regelkonformität>
|
||||||
|
|
||||||
## Ergebnis
|
## Ergebnis
|
||||||
@@ -653,8 +761,9 @@ Werkzeug umgesetzt wird und welche Messgrößen dieses Werkzeug liefert.
|
|||||||
|
|
||||||
### Adapter: Claude Code
|
### Adapter: Claude Code
|
||||||
|
|
||||||
Der einzige derzeit ausgearbeitete Adapter. Alle konkreten Aufrufe, Flags und Feldnamen im
|
Alle mit `claude -p`, `--safe-mode`, `--allowedTools`, `modelUsage` und `subagent_stats`
|
||||||
Prozessteil beziehen sich auf ihn; er wurde gegen **CLI 2.1.245** entwickelt und verifiziert.
|
bezeichneten Aufrufe und Felder im Prozessteil gehören zu diesem Adapter. Er wurde gegen
|
||||||
|
**CLI 2.1.245** entwickelt und verifiziert.
|
||||||
|
|
||||||
**Gelieferte Messgrößen** – vollständig aus `RawResult.json`:
|
**Gelieferte Messgrößen** – vollständig aus `RawResult.json`:
|
||||||
|
|
||||||
@@ -673,10 +782,114 @@ Prozessteil beziehen sich auf ihn; er wurde gegen **CLI 2.1.245** entwickelt und
|
|||||||
werden nicht ausgewiesen; der Effort steht **nicht** in `RawResult.json` und ist nur über das
|
werden nicht ausgewiesen; der Effort steht **nicht** in `RawResult.json` und ist nur über das
|
||||||
Session-Transkript belegbar (siehe Schritt 6 der Vorbereitung).
|
Session-Transkript belegbar (siehe Schritt 6 der Vorbereitung).
|
||||||
|
|
||||||
|
### Adapter: Codex CLI / OpenAI-Modelle
|
||||||
|
|
||||||
|
Dieser Adapter wurde für den reproduzierbaren Headless-Betrieb mit `codex exec` und exakten
|
||||||
|
OpenAI-Modell-IDs entworfen. Referenzstand bei Einführung: **Codex CLI 0.149.0-alpha.4.3**.
|
||||||
|
Vor jedem Lauf `codex --version` protokollieren; bei geändertem JSONL-Schema den Normalisierer
|
||||||
|
zuerst mit einem kleinen, ausdrücklich freigegebenen Smoke-Test prüfen.
|
||||||
|
|
||||||
|
**Unterstützter Agentenmodus:** In Version 5.0.0 nur `solo`. `builtin` und `custom` müssen
|
||||||
|
abbrechen. `solo` wird mit zwei unabhängigen Einstellungen erzwungen:
|
||||||
|
`--disable multi_agent` und `-c agents.enabled=false`.
|
||||||
|
|
||||||
|
**Isolation und Ausgabe.** Codex arbeitet im Root mit `--sandbox read-only`. Anders als beim
|
||||||
|
Claude-Adapter erhält der Agent deshalb kein beschreibbares Zusatzverzeichnis. Er liefert ein
|
||||||
|
Schemaobjekt mit vollständigen Dateiinhalten; `--output-last-message` schreibt dieses durch die
|
||||||
|
CLI nach `_meta\final_response.json`. Erst nach Ende des Agenten materialisiert das lokale,
|
||||||
|
deterministische Skript die validierten relativen Pfade unter `Ergebnisse\`. Absolute Pfade,
|
||||||
|
`..`, Laufwerkspräfixe und case-insensitive Duplikate werden abgelehnt.
|
||||||
|
|
||||||
|
Vor dem Start `$codex`, `$skillDir`, `$lauf`, `$root`, `$modell` und `$effort` auf absolute
|
||||||
|
Pfade beziehungsweise die bestätigten Versuchsbedingungen setzen. Den Prompt mit dem
|
||||||
|
Codex-Ausgabeblock aus Abschnitt 2 nach `_meta\combined_prompt.md` schreiben. Der eigentliche
|
||||||
|
Aufruf lautet:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
$codexArgs = @(
|
||||||
|
'--model', $modell,
|
||||||
|
'-c', "model_reasoning_effort=`"$effort`"",
|
||||||
|
'-c', 'service_tier="default"',
|
||||||
|
'--sandbox', 'read-only',
|
||||||
|
'--ask-for-approval', 'never',
|
||||||
|
'--disable', 'multi_agent',
|
||||||
|
'-c', 'agents.enabled=false',
|
||||||
|
'--disable', 'plugins',
|
||||||
|
'--disable', 'apps',
|
||||||
|
'--disable', 'hooks',
|
||||||
|
'--disable', 'skill_search',
|
||||||
|
'--cd', $root,
|
||||||
|
'exec',
|
||||||
|
'--ignore-user-config',
|
||||||
|
'--ignore-rules',
|
||||||
|
'--strict-config',
|
||||||
|
'--json',
|
||||||
|
'--output-schema', (Join-Path $skillDir 'codex-output-schema.json'),
|
||||||
|
'--output-last-message', (Join-Path $lauf '_meta\final_response.json'),
|
||||||
|
'-'
|
||||||
|
)
|
||||||
|
|
||||||
|
Set-Content -Path "$lauf\_meta\startzeit.txt" -Value (Get-Date -Format o)
|
||||||
|
Get-Content "$lauf\_meta\combined_prompt.md" -Raw |
|
||||||
|
& $codex @codexArgs 2> "$lauf\Stderr.log" |
|
||||||
|
Set-Content "$lauf\RawEvents.jsonl" -Encoding utf8
|
||||||
|
$codexExit = $LASTEXITCODE
|
||||||
|
Set-Content -Path "$lauf\_meta\exitcode.txt" -Value $codexExit
|
||||||
|
Set-Content -Path "$lauf\_meta\endzeit.txt" -Value (Get-Date -Format o)
|
||||||
|
|
||||||
|
python (Join-Path $skillDir 'normalise-codex-result.py') $lauf `
|
||||||
|
--model $modell --effort $effort
|
||||||
|
```
|
||||||
|
|
||||||
|
Auch dieser Aufruf ist als Background-Task zu starten. Das Erscheinen von `RawEvents.jsonl`
|
||||||
|
allein bedeutet noch nicht, dass der Lauf fertig ist; Ende ist der abgeschlossene Prozess plus
|
||||||
|
erzeugte `RawResult.json`. Schlägt die Normalisierung fehl, Rohdateien unverändert lassen und
|
||||||
|
den Lauf als Fehler protokollieren.
|
||||||
|
|
||||||
|
**Warum diese Flags:**
|
||||||
|
|
||||||
|
| Flag / Einstellung | Zweck |
|
||||||
|
|---|---|
|
||||||
|
| `--model <id>` | vollständige, vom User bestätigte OpenAI-Modell-ID |
|
||||||
|
| `model_reasoning_effort` | expliziter Denkaufwand |
|
||||||
|
| `service_tier="default"` | verhindert eine geerbte Fast-/Priority-Bedingung |
|
||||||
|
| `--sandbox read-only` | technische Schreibsperre für den Codebasis-Snapshot |
|
||||||
|
| `--ask-for-approval never` | keine interaktiven Unterbrechungen im Headless-Lauf |
|
||||||
|
| `--ignore-user-config`, `--ignore-rules` | keine User-Konfiguration und keine Exec-Regeln |
|
||||||
|
| `--disable plugins/apps/hooks/skill_search` | keine externen oder benutzerspezifischen Erweiterungen |
|
||||||
|
| `--disable multi_agent`, `agents.enabled=false` | keine Subagenten im Modus `solo` |
|
||||||
|
| `--json` | vollständiger maschinenlesbarer Ereignisstrom |
|
||||||
|
| `--output-schema`, `--output-last-message` | validierbare Ergebnisdateien ohne Schreibrecht des Agenten |
|
||||||
|
|
||||||
|
`--ignore-user-config` lässt die gespeicherte Authentifizierung weiterhin nutzbar; niemals
|
||||||
|
`auth.json` kopieren oder in Laufartefakten ablegen. Live-Websuche ist nicht freigegeben, weil
|
||||||
|
`--search` fehlt. Der bereinigte Snapshot bleibt zusätzlich Pflicht, da projektlokale
|
||||||
|
Anweisungsdateien eine eigene Versuchsbedingung wären.
|
||||||
|
|
||||||
|
**Gelieferte Messgrößen** aus `RawEvents.jsonl`, normalisiert nach `RawResult.json`:
|
||||||
|
|
||||||
|
| Messgröße | Quelle |
|
||||||
|
|---|---|
|
||||||
|
| Abbruchstatus | Prozess-Exitcode, `turn.failed`, `error`, fehlerhafte JSONL-Zeilen |
|
||||||
|
| Wanduhrdauer | `_meta\startzeit.txt` bis `_meta\endzeit.txt` |
|
||||||
|
| Tokens gesamt | `turn.completed.usage.input_tokens + output_tokens` |
|
||||||
|
| Cache-Read-Tokens | `turn.completed.usage.cached_input_tokens`, Teilmenge der Input-Tokens |
|
||||||
|
| Reasoning-Tokens | `turn.completed.usage.reasoning_output_tokens`, Teilmenge der Output-Tokens |
|
||||||
|
| Agent-Turns | Anzahl `turn.completed` |
|
||||||
|
| Sitzungskennung | `thread.started.thread_id` |
|
||||||
|
| Werkzeugaktivität | Anzahl abgeschlossener `item.*` je Item-Typ |
|
||||||
|
| Erzeugte Artefakte | validierte Einträge aus `_meta\final_response.json` |
|
||||||
|
|
||||||
|
**Nicht erfasst und niemals schätzen:** reine API-Dauer, Cache-Write-Tokens, einzelne
|
||||||
|
Permission-Denials und die tatsächlich serverseitig bediente Modell-ID. `--model` dokumentiert
|
||||||
|
die angeforderte ID; da `codex exec --json` sie im Ereignisstrom nicht wiederholt, lautet die
|
||||||
|
Modellkontrolle im Protokoll `nicht prüfbar`. Temperatur und weitere Sampling-Parameter sind in
|
||||||
|
diesem CLI-Ablauf nicht steuerbar; Effort und Service-Tier werden dagegen explizit festgelegt.
|
||||||
|
|
||||||
### Weitere Adapter (für Versuch 4 nachzurüsten)
|
### Weitere Adapter (für Versuch 4 nachzurüsten)
|
||||||
|
|
||||||
Kapitel 4 der Arbeit sieht einen LLM-Querschnitt über Codex CLI, Qwen Code CLI über LM Studio
|
Kapitel 4 der Arbeit sieht zusätzlich Qwen Code CLI über LM Studio und DeepSeek über die
|
||||||
und DeepSeek über die Cloud-API vor. Diese Adapter sind noch nicht ausgearbeitet. Damit ein
|
Cloud-API vor. Diese Adapter sind noch nicht ausgearbeitet. Damit ein
|
||||||
Lauf als Messpunkt taugt, muss ein Adapter mindestens liefern:
|
Lauf als Messpunkt taugt, muss ein Adapter mindestens liefern:
|
||||||
|
|
||||||
| Pflichtangabe | Zweck |
|
| Pflichtangabe | Zweck |
|
||||||
@@ -733,6 +946,7 @@ der Historie unten – im selben Arbeitsschritt.
|
|||||||
|
|
||||||
| Version | Änderung | Grund | Verwendet in |
|
| Version | Änderung | Grund | Verwendet in |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
|
| **5.0.0** | **Neuer Codex-CLI-Adapter für OpenAI-Modelle.** Exakte OpenAI-Modell-IDs, expliziter Reasoning-Effort und Service-Tier; technisch read-only ausgeführtes `codex exec`; schemaerzwungene Dateirückgabe; JSONL-Rohdaten und deterministische Normalisierung nach `RawResult.json`. Codex ist zunächst nur im Modus `solo` freigegeben. Zusätzlich fünf beschädigte Backslashes vor `analyse-anforderungen.py`, `anforderungen.*` und `after.txt` repariert. | Der bisherige Skill konnte nur Claude Code ausführen. Ein Codex-Lauf braucht andere Isolations-, Ausgabe- und Messmechanismen. MAJOR, weil Werkzeug, Rohdatenformat und Ergebnisübergabe neue Versuchsbedingungen bilden; der nächste Lauf eröffnet deshalb eine neue Iteration. | ab dem ersten Codex-Lauf |
|
||||||
| **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`) |
|
| **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.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.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`) |
|
||||||
@@ -750,6 +964,12 @@ der Historie unten – im selben Arbeitsschritt.
|
|||||||
| **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.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 |
|
| **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 |
|
||||||
| **4.0.0** | **Ausrichtung auf Kapitel 4 der Arbeit.** Skill zweigeteilt in `## Prozess` (werkzeugneutral) und `## Werkzeugadapter` (konkrete Aufrufe, derzeit nur Claude Code). Der Prompt trägt nur noch die Analyseanweisung; Werkzeugkontext und Ausgabeverzeichnis werden zur Laufzeit angehängt. Versuchszuordnung korrigiert: **V1 = `solo`, V1b = `builtin`**. Neue Protokollfelder: Kontextfenster, Sampling-Parameter, lokale Runtime-Angaben, Abschnitt Validierungsstichprobe. Abschnitt „Gefundene Anforderungen" den drei Qualitätsdimensionen zugeordnet. | Prompt und Skill waren über 24 Läufe organisch gewachsen und stellenweise nicht mehr deckungsgleich mit Kap. 4. Der Prompt enthielt Aussagen zur Werkzeugkonfiguration, die dort nicht hingehören und ihn an Claude Code banden; der Skill verankerte weder den Evaluationsrahmen noch die von Kap. 4.3 geforderten Reproduzierbarkeitsangaben. MAJOR, weil sich die Zuordnung der Versuchsbedingungen ändert. | ab sofort |
|
| **4.0.0** | **Ausrichtung auf Kapitel 4 der Arbeit.** Skill zweigeteilt in `## Prozess` (werkzeugneutral) und `## Werkzeugadapter` (konkrete Aufrufe, derzeit nur Claude Code). Der Prompt trägt nur noch die Analyseanweisung; Werkzeugkontext und Ausgabeverzeichnis werden zur Laufzeit angehängt. Versuchszuordnung korrigiert: **V1 = `solo`, V1b = `builtin`**. Neue Protokollfelder: Kontextfenster, Sampling-Parameter, lokale Runtime-Angaben, Abschnitt Validierungsstichprobe. Abschnitt „Gefundene Anforderungen" den drei Qualitätsdimensionen zugeordnet. | Prompt und Skill waren über 24 Läufe organisch gewachsen und stellenweise nicht mehr deckungsgleich mit Kap. 4. Der Prompt enthielt Aussagen zur Werkzeugkonfiguration, die dort nicht hingehören und ihn an Claude Code banden; der Skill verankerte weder den Evaluationsrahmen noch die von Kap. 4.3 geforderten Reproduzierbarkeitsangaben. MAJOR, weil sich die Zuordnung der Versuchsbedingungen ändert. | ab sofort |
|
||||||
|
| **4.1.0** | **Ebene `<Versuchstag>` über den Bedingungen**: `Tag 1`, `Tag 2`, …; Schritt 8 ermittelt den höchsten vorhandenen Tag. Protokollfeld „Ablage" entsprechend erweitert. | Der Versuchsaufbau änderte sich am ersten Tag über 17 Skill-Versionen hinweg. Die Tagesebene hält Blöcke auseinander, die unter unterschiedlichem Stand entstanden sind, und macht sichtbar, welche Läufe überhaupt unter vergleichbaren Rahmenbedingungen liefen. | rückwirkend: alle 24 Läufe nach `Tag 1` verschoben |
|
||||||
|
| **4.5.0** | `extract-subagenten.py` trennt am Nebenläufigkeitslimit **abgewiesene** Aufrufe von echten Subagenten-Starts und weist sie getrennt aus. | Der erste Lauf mit mehr als 20 gleichzeitigen Subagenten (`Iteration 3/…/125032_v4.4.0-fb24`, 31 gestartet, `refused.concurrency_limit` = 29) meldete eine Abweichung von 21 gefundenen gegenüber 13 erwarteten Aufrufen. Ursache waren 8 Absagen im Haupttranskript, die wie Starts aussehen, aber nur „Concurrent subagent limit reached" zurückliefern und nicht in `spawned` zählen. Ohne die Trennung wäre jeder stark parallelisierende Lauf mit einer Scheinwarnung versehen. MINOR: neue Messgröße, keine Änderung der Versuchsbedingung. | ab sofort; die drei `builtin`-Läufe der Iteration 3 wurden neu extrahiert und stimmen exakt überein |
|
||||||
|
| **4.4.0** | Zwei Umbenennungen zur Auflösung einer Begriffskollision. **(a)** Ordnerebene `<Versuchstag>` → `<Iteration>` (`Tag N` → `Iteration N`), mit ausformuliertem Kriterium: Eine neue Iteration eröffnet, was Läufe nicht mehr poolbar macht – Codebasis-Snapshot, Prompt-Version, Werkzeugkonfiguration oder eine MAJOR-Version dieses Skills. **(b)** Die Fassung der Prompt-Datei heißt nicht mehr „Iteration", sondern **Prompt-Version**; Protokollfeld entsprechend umbenannt. | „Tag" band die Ebene an das Kalenderdatum, obwohl sie die Vergleichbarkeit abbildet: Am 26.08. entstanden zwei nicht poolbare Blöcke am selben Tag – ohne und mit dem DB-Schema-Dump `SSMS_DB_SCHEMA.sql` (Commit `f349d189`). Die Umbenennung in „Iteration" kollidierte dann mit der Prompt-Iteration: Iteration 2 und Iteration 3 laufen beide unter derselben Prompt-Fassung. Erst die zweite Umbenennung macht beide Begriffe eindeutig. MINOR: reine Benennung, keine Änderung der Versuchsbedingung. | rückwirkend: `Tag 1` → `Iteration 1` (24 Läufe), `Tag 2` → `Iteration 2` (5 Läufe); die fünf Läufe mit DB-Schema nach `Iteration 3`. Die Prompt-Dateien selbst bleiben unverändert – ihre SHA-256 sind in 33 Protokollen dokumentiert. |
|
||||||
|
| **4.3.0** | `analyse-anforderungen.py` bestimmt die Ebene einer Anforderung aus dem Feld `Ebene:` beziehungsweise dem ID-Präfix statt aus dem Dateinamen und weist Fremdablage als eigene Auffälligkeit aus. | Das Skript zählte die Ebene nach der Datei, in der ein Block stand. Im Lauf `Iteration 2/…/094250_v4.2.1-c69e` lagen 12 StRS- und 5 SyRS-Blöcke in `SwRS.md`; die Verteilungstabelle meldete daraufhin 9/10/141 statt der tatsächlichen 21/15/124. Die Gesamtzahl war korrekt, die Verteilung – Kenngröße der Set-Qualität nach Kap. 4.3 – nicht. Gegenprobe an einem sauber abgelegten Lauf (`084301_v4.2.0-d6f9`): unverändert 20/120/30. MINOR, weil eine Messgröße korrigiert und eine neue Auffälligkeit ergänzt wird, ohne die Versuchsbedingung zu ändern. | ab sofort; die 24 Protokolle von Iteration 1 wurden geprüft: keine Fremdablage |
|
||||||
|
| **4.2.1** | Vorher/Nachher-Prüfung des Roots wird **pfadskopiert** ausgeführt: `git -C <repo> status --porcelain -- <pfad-des-roots>` statt `git -C <root> status --porcelain` (Schritte 7, 9 und Abschnitt 4). | Seit Commit `f045b99a` liegt die Codebasis als Dateien im Arbeitsrepo statt als Gitlink. Die unskopierte Abfrage lieferte damit den Status des gesamten Arbeitsrepos – beim Lauf `Iteration 2/…/084301_v4.2.0-d6f9` rund 55 KB Ausgabe, praktisch nur Versuchsdateien. Ohne Pfadfilter hätte die Read-only-Verifikation ab sofort bei **jedem** Lauf eine Abweichung gemeldet, die es nicht gibt. PATCH: keine Änderung der Versuchsbedingung, nur eine korrigierte Messung. | ab Lauf `084301_v4.2.0-d6f9` (dort bereits so ausgeführt und im Protokoll vermerkt) |
|
||||||
|
| **4.2.0** | **Auswahlregel bei mehreren Prompt-Versionen**: ohne ausdrückliche Angabe gilt die höchste Prompt-Versionsnummer; neues Protokollfeld „Prompt-Version". Ältere Fassungen bleiben unverändert. | Mit `02_Prompt.md` liegt erstmals mehr als eine Fassung im Versuchsordner. Ohne Regel wäre unklar, welche gilt, und der SHA-256 im Protokoll ließe sich keiner Datei mehr zuordnen. Bei der Einführung fiel auf, dass `01_Prompt.md` nachträglich verändert worden war – der in 24 Protokollen dokumentierte Hash zeigte auf eine Fassung, die es nicht mehr gab. | ab Prompt-Version 02 |
|
||||||
|
|
||||||
## Parallele Läufe
|
## Parallele Läufe
|
||||||
|
|
||||||
@@ -801,4 +1021,4 @@ messbar wird.
|
|||||||
|
|
||||||
**Bisherige Läufe.** Die 24 Läufe in `Versuche/Versuch_01/` verteilen sich auf V1 (`solo`) und
|
**Bisherige Läufe.** Die 24 Läufe in `Versuche/Versuch_01/` verteilen sich auf V1 (`solo`) und
|
||||||
V1b (`builtin`). Die Ordnerstruktur macht die Zuordnung unmittelbar sichtbar; die Zellen sind
|
V1b (`builtin`). Die Ordnerstruktur macht die Zuordnung unmittelbar sichtbar; die Zellen sind
|
||||||
über `ls <ModellID>/<Modus>/<Effort> | wc -l` abzählbar.
|
über `ls "<Iteration>/<ModellID>/<Modus>/<Effort>" | wc -l` abzählbar. Alle 24 liegen unter `Iteration 1`.
|
||||||
|
|||||||
@@ -31,14 +31,35 @@ def feld(block, name):
|
|||||||
return m.group(1).strip() if m else ''
|
return m.group(1).strip() if m else ''
|
||||||
|
|
||||||
|
|
||||||
|
def ebene_von(block, aid, datei_ebene):
|
||||||
|
"""Ebene einer Anforderung bestimmen.
|
||||||
|
|
||||||
|
Die Ebene wird NICHT aus dem Dateinamen abgeleitet: Agenten legen Bloecke
|
||||||
|
regelmaessig in der Datei einer anderen Ebene ab (beobachtet im Lauf
|
||||||
|
Iteration 2/.../094250_v4.2.1-c69e: 12 StRS- und 5 SyRS-Bloecke standen in SwRS.md).
|
||||||
|
Massgeblich ist das Feld `Ebene:` des Blocks, hilfsweise das ID-Praefix,
|
||||||
|
erst zuletzt die Datei.
|
||||||
|
"""
|
||||||
|
f = feld(block, 'Ebene')
|
||||||
|
for eb in EBENEN:
|
||||||
|
if f.strip().upper().startswith(eb.upper()):
|
||||||
|
return eb, False
|
||||||
|
for eb in EBENEN:
|
||||||
|
if aid.strip().upper().startswith(eb.upper()):
|
||||||
|
return eb, aid.strip().upper()[:4] != datei_ebene.upper()[:4]
|
||||||
|
return datei_ebene, False
|
||||||
|
|
||||||
|
|
||||||
def analysiere(lauf):
|
def analysiere(lauf):
|
||||||
erg = os.path.join(lauf, 'Ergebnisse')
|
erg = os.path.join(lauf, 'Ergebnisse')
|
||||||
anf = []
|
anf = []
|
||||||
for eb in EBENEN:
|
for eb_datei in EBENEN:
|
||||||
for b in bloecke(os.path.join(erg, eb + '.md')):
|
for b in bloecke(os.path.join(erg, eb_datei + '.md')):
|
||||||
aid = feld(b, 'ID')
|
aid = feld(b, 'ID')
|
||||||
if not aid:
|
if not aid:
|
||||||
continue
|
continue
|
||||||
|
eb, _ = ebene_von(b, aid, eb_datei)
|
||||||
|
fremd = not aid.strip().upper().startswith(eb_datei.upper())
|
||||||
belege = re.findall(r'\[(PRIM\w*R|SEKUND\w*R|KONTEXT)\]', b)
|
belege = re.findall(r'\[(PRIM\w*R|SEKUND\w*R|KONTEXT)\]', b)
|
||||||
norm = []
|
norm = []
|
||||||
for x in belege:
|
for x in belege:
|
||||||
@@ -46,7 +67,8 @@ def analysiere(lauf):
|
|||||||
else 'SEKUNDÄR' if x.startswith('SEKUND') else 'KONTEXT')
|
else 'SEKUNDÄR' if x.startswith('SEKUND') else 'KONTEXT')
|
||||||
status = feld(b, 'Status')
|
status = feld(b, 'Status')
|
||||||
anf.append(dict(
|
anf.append(dict(
|
||||||
id=aid, ebene=eb, titel=feld(b, 'Titel'), typ=feld(b, 'Typ') or '(ohne)',
|
id=aid, ebene=eb, datei_ebene=eb_datei, fremdabgelegt=fremd,
|
||||||
|
titel=feld(b, 'Titel'), typ=feld(b, 'Typ') or '(ohne)',
|
||||||
belege=norm, status=status,
|
belege=norm, status=status,
|
||||||
hypothese=('HYPOTHESE' in status.upper()) or ('[HYPOTHESE]' in b),
|
hypothese=('HYPOTHESE' in status.upper()) or ('[HYPOTHESE]' in b),
|
||||||
workaround='workaround' in status.lower(),
|
workaround='workaround' in status.lower(),
|
||||||
@@ -123,6 +145,20 @@ def abschnitt(anf):
|
|||||||
z.append('| %s | %d | %s |' % (eb, je_ebene.get(eb, 0), pct(je_ebene.get(eb, 0), n)))
|
z.append('| %s | %d | %s |' % (eb, je_ebene.get(eb, 0), pct(je_ebene.get(eb, 0), n)))
|
||||||
z += ['| **Gesamt** | **%d** | 100 %% |' % n, '']
|
z += ['| **Gesamt** | **%d** | 100 %% |' % n, '']
|
||||||
|
|
||||||
|
fremd = [a for a in anf if a.get('fremdabgelegt')]
|
||||||
|
if fremd:
|
||||||
|
nach = collections.Counter(
|
||||||
|
'%s-Block in `%s.md`' % (a['ebene'], a['datei_ebene']) for a in fremd)
|
||||||
|
z.append('')
|
||||||
|
z.append('> **Auffälligkeit – Ebene weicht von der Ablagedatei ab.** %d von %d '
|
||||||
|
'Anforderungen stehen in der Datei einer anderen Ebene: %s. Die Ebene wurde '
|
||||||
|
'aus dem Feld `Ebene:` beziehungsweise dem ID-Präfix bestimmt, nicht aus dem '
|
||||||
|
'Dateinamen. Für die Set-Qualität ist das relevant: Die Dreiteilung StRS / '
|
||||||
|
'SyRS / SwRS ist dann nicht mehr an der Dateistruktur ablesbar.'
|
||||||
|
% (len(fremd), n,
|
||||||
|
', '.join('%d × %s' % (v, k) for k, v in sorted(nach.items()))))
|
||||||
|
z.append('')
|
||||||
|
|
||||||
z += ['### Anforderungstypen', '', '| Typ | Anzahl | Anteil |', '|---|---:|---:|']
|
z += ['### Anforderungstypen', '', '| Typ | Anzahl | Anteil |', '|---|---:|---:|']
|
||||||
for t, c in typen.most_common(10):
|
for t, c in typen.most_common(10):
|
||||||
z.append('| %s | %d | %s |' % (t, c, pct(c, n)))
|
z.append('| %s | %d | %s |' % (t, c, pct(c, n)))
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"files": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"path": { "type": "string", "minLength": 1 },
|
||||||
|
"content": { "type": "string" }
|
||||||
|
},
|
||||||
|
"required": ["path", "content"],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"summary": { "type": "string" }
|
||||||
|
},
|
||||||
|
"required": ["files", "summary"],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
@@ -51,10 +51,22 @@ for zeile in io.open(pfad, encoding='utf-8'):
|
|||||||
inhalt = c.get('content')
|
inhalt = c.get('content')
|
||||||
if isinstance(inhalt, list):
|
if isinstance(inhalt, list):
|
||||||
inhalt = ' '.join(str(x.get('text', '')) for x in inhalt if isinstance(x, dict))
|
inhalt = ' '.join(str(x.get('text', '')) for x in inhalt if isinstance(x, dict))
|
||||||
ergebnisse[c.get('tool_use_id')] = len(str(inhalt or ''))
|
ergebnisse[c.get('tool_use_id')] = str(inhalt or '')
|
||||||
|
|
||||||
|
# Ein Aufruf, der am Nebenlaeufigkeitslimit scheitert, erscheint im Transkript wie ein
|
||||||
|
# regulaerer Subagenten-Start, ist aber keiner: Er liefert nur die Absage zurueck und
|
||||||
|
# zaehlt nicht in `subagent_stats.spawned`. Ohne diese Trennung meldet der Abgleich eine
|
||||||
|
# Abweichung, die es nicht gibt (Lauf Iteration 3/.../125032_v4.4.0-fb24: 21 gefundene
|
||||||
|
# Aufrufe gegenueber 13 erwarteten - die Differenz waren 8 Absagen).
|
||||||
|
ABSAGE = 'Concurrent subagent limit reached'
|
||||||
|
|
||||||
for a in aufrufe:
|
for a in aufrufe:
|
||||||
a['ergebnis_zeichen'] = ergebnisse.get(a['id'])
|
txt = ergebnisse.get(a['id']) or ''
|
||||||
|
a['ergebnis_zeichen'] = len(txt)
|
||||||
|
a['abgewiesen'] = ABSAGE in txt
|
||||||
|
|
||||||
|
abgewiesen = [a for a in aufrufe if a['abgewiesen']]
|
||||||
|
echte = [a for a in aufrufe if not a['abgewiesen']]
|
||||||
|
|
||||||
meta = os.path.join(lauf, '_meta')
|
meta = os.path.join(lauf, '_meta')
|
||||||
os.makedirs(meta, exist_ok=True)
|
os.makedirs(meta, exist_ok=True)
|
||||||
@@ -65,15 +77,27 @@ md = ['# Subagenten-Aufrufe', '',
|
|||||||
'Session `%s`, Transkript `%s`.' % (sid, os.path.basename(pfad)),
|
'Session `%s`, Transkript `%s`.' % (sid, os.path.basename(pfad)),
|
||||||
'',
|
'',
|
||||||
'`subagent_stats`: **%s** Subagenten gesamt, davon **%s** von Subagenten gestartet '
|
'`subagent_stats`: **%s** Subagenten gesamt, davon **%s** von Subagenten gestartet '
|
||||||
'(max_depth %s). Direkt vom Hauptagenten erwartet: **%s**. Im Transkript gefunden: **%s**.'
|
'(max_depth %s). Direkt vom Hauptagenten erwartet: **%s**. Im Transkript gefunden: '
|
||||||
% (gesamt, verschachtelt, stats.get('max_depth'), erwartet, len(aufrufe)), '']
|
'**%s** echte Starts%s.'
|
||||||
|
% (gesamt, verschachtelt, stats.get('max_depth'), erwartet, len(echte),
|
||||||
|
' und **%d** am Nebenlaeufigkeitslimit abgewiesene Aufrufe' % len(abgewiesen)
|
||||||
|
if abgewiesen else ''), '']
|
||||||
if verschachtelt:
|
if verschachtelt:
|
||||||
md += ['> Die %s von Subagenten gestarteten Aufrufe stehen in deren eigenen Transkripten und'
|
md += ['> Die %s von Subagenten gestarteten Aufrufe stehen in deren eigenen Transkripten und'
|
||||||
' sind hier **nicht** enthalten.' % verschachtelt, '']
|
' sind hier **nicht** enthalten.' % verschachtelt, '']
|
||||||
if erwartet != len(aufrufe):
|
if abgewiesen:
|
||||||
md += ['> **Abweichung** zwischen erwarteter und gefundener Anzahl.',
|
md += ['> **%d Aufrufe wurden am Nebenlaeufigkeitslimit abgewiesen** '
|
||||||
|
'(`subagent_stats.refused.concurrency_limit` = %s) und sind unten **nicht** '
|
||||||
|
'aufgefuehrt. Sie erscheinen im Transkript wie regulaere Starts, liefern aber nur '
|
||||||
|
'die Absage zurueck und zaehlen nicht in `spawned`. Fuer die Auswertung der '
|
||||||
|
'selbstgewaehlten Zerlegung sind sie dennoch aufschlussreich: Der Hauptagent wollte '
|
||||||
|
'staerker parallelisieren, als das Werkzeug zuliess.'
|
||||||
|
% (len(abgewiesen), stats.get('refused', {}).get('concurrency_limit', '?')), '']
|
||||||
|
if erwartet != len(echte):
|
||||||
|
md += ['> **Abweichung** zwischen erwarteter (%s) und gefundener Anzahl echter Starts (%s).'
|
||||||
|
% (erwartet, len(echte)),
|
||||||
'> Ursache pruefen, bevor die Prompts ausgewertet werden.', '']
|
'> Ursache pruefen, bevor die Prompts ausgewertet werden.', '']
|
||||||
for i, a in enumerate(aufrufe, 1):
|
for i, a in enumerate(echte, 1):
|
||||||
md += ['## %d. %s' % (i, a['description'] or '(ohne Beschreibung)'),
|
md += ['## %d. %s' % (i, a['description'] or '(ohne Beschreibung)'),
|
||||||
'',
|
'',
|
||||||
'- **Werkzeug:** `%s` **Typ:** `%s` **Hintergrund:** %s'
|
'- **Werkzeug:** `%s` **Typ:** `%s` **Hintergrund:** %s'
|
||||||
@@ -83,8 +107,10 @@ for i, a in enumerate(aufrufe, 1):
|
|||||||
'', '### Prompt', '', '```', a['prompt'].rstrip(), '```', '']
|
'', '### Prompt', '', '```', a['prompt'].rstrip(), '```', '']
|
||||||
io.open(os.path.join(meta, 'subagenten.md'), 'w', encoding='utf-8').write('\n'.join(md))
|
io.open(os.path.join(meta, 'subagenten.md'), 'w', encoding='utf-8').write('\n'.join(md))
|
||||||
|
|
||||||
print('Subagenten gefunden: %d (direkt erwartet: %s, gesamt: %s, davon verschachtelt: %s)' % (len(aufrufe), erwartet, gesamt, verschachtelt))
|
print('Subagenten gefunden: %d echte%s (direkt erwartet: %s, gesamt: %s, davon verschachtelt: %s)'
|
||||||
for a in aufrufe:
|
% (len(echte), (', %d abgewiesen' % len(abgewiesen)) if abgewiesen else '',
|
||||||
|
erwartet, gesamt, verschachtelt))
|
||||||
|
for a in echte:
|
||||||
print(' - %-42s %s Prompt %6d Z. Ergebnis %s Z.'
|
print(' - %-42s %s Prompt %6d Z. Ergebnis %s Z.'
|
||||||
% ((a['description'] or '')[:42], a['subagent_type'], len(a['prompt']), a['ergebnis_zeichen']))
|
% ((a['description'] or '')[:42], a['subagent_type'], len(a['prompt']), a['ergebnis_zeichen']))
|
||||||
print('geschrieben:', os.path.join(meta, 'subagenten.md'))
|
print('geschrieben:', os.path.join(meta, 'subagenten.md'))
|
||||||
|
|||||||
@@ -0,0 +1,165 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Materialize Codex result files and normalize its JSONL measurements."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
from collections import Counter
|
||||||
|
from datetime import datetime
|
||||||
|
from pathlib import Path, PurePosixPath
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
|
def parse_args() -> argparse.Namespace:
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("run_directory", type=Path)
|
||||||
|
parser.add_argument("--model", required=True)
|
||||||
|
parser.add_argument("--effort", required=True)
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def read_jsonl(path: Path) -> tuple[list[dict[str, Any]], list[str]]:
|
||||||
|
events: list[dict[str, Any]] = []
|
||||||
|
malformed: list[str] = []
|
||||||
|
for number, line in enumerate(path.read_text(encoding="utf-8-sig").splitlines(), 1):
|
||||||
|
if not line.strip():
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
value = json.loads(line)
|
||||||
|
except json.JSONDecodeError as exc:
|
||||||
|
malformed.append(f"line {number}: {exc}")
|
||||||
|
continue
|
||||||
|
if isinstance(value, dict):
|
||||||
|
events.append(value)
|
||||||
|
else:
|
||||||
|
malformed.append(f"line {number}: JSON value is not an object")
|
||||||
|
return events, malformed
|
||||||
|
|
||||||
|
|
||||||
|
def safe_result_path(results_dir: Path, raw_path: str) -> Path:
|
||||||
|
relative = PurePosixPath(raw_path.replace("\\", "/"))
|
||||||
|
if relative.is_absolute() or not relative.parts or ".." in relative.parts:
|
||||||
|
raise ValueError(f"unsafe result path: {raw_path!r}")
|
||||||
|
if any(part in ("", ".") or ":" in part for part in relative.parts):
|
||||||
|
raise ValueError(f"invalid result path: {raw_path!r}")
|
||||||
|
target = results_dir.joinpath(*relative.parts).resolve()
|
||||||
|
root = results_dir.resolve()
|
||||||
|
if root != target and root not in target.parents:
|
||||||
|
raise ValueError(f"result path escapes Ergebnisse: {raw_path!r}")
|
||||||
|
return target
|
||||||
|
|
||||||
|
|
||||||
|
def parse_iso(path: Path) -> datetime | None:
|
||||||
|
if not path.exists():
|
||||||
|
return None
|
||||||
|
value = path.read_text(encoding="utf-8-sig").strip()
|
||||||
|
try:
|
||||||
|
return datetime.fromisoformat(value.replace("Z", "+00:00"))
|
||||||
|
except ValueError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
args = parse_args()
|
||||||
|
run_dir = args.run_directory.resolve()
|
||||||
|
meta_dir = run_dir / "_meta"
|
||||||
|
results_dir = run_dir / "Ergebnisse"
|
||||||
|
events, malformed = read_jsonl(run_dir / "RawEvents.jsonl")
|
||||||
|
envelope = json.loads((meta_dir / "final_response.json").read_text(encoding="utf-8-sig"))
|
||||||
|
if not isinstance(envelope, dict) or not isinstance(envelope.get("files"), list):
|
||||||
|
raise ValueError("final_response.json does not match the Codex output envelope")
|
||||||
|
|
||||||
|
results_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
seen: set[str] = set()
|
||||||
|
materialized: list[str] = []
|
||||||
|
for entry in envelope["files"]:
|
||||||
|
if not isinstance(entry, dict):
|
||||||
|
raise ValueError("file entry is not an object")
|
||||||
|
raw_path = entry.get("path")
|
||||||
|
content = entry.get("content")
|
||||||
|
if not isinstance(raw_path, str) or not isinstance(content, str):
|
||||||
|
raise ValueError("file entry requires string path and content")
|
||||||
|
target = safe_result_path(results_dir, raw_path)
|
||||||
|
key = str(target).casefold()
|
||||||
|
if key in seen:
|
||||||
|
raise ValueError(f"duplicate result path: {raw_path!r}")
|
||||||
|
seen.add(key)
|
||||||
|
target.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
target.write_text(content, encoding="utf-8", newline="\n")
|
||||||
|
materialized.append(str(target.relative_to(results_dir)).replace("\\", "/"))
|
||||||
|
|
||||||
|
usage = Counter()
|
||||||
|
item_types = Counter()
|
||||||
|
errors: list[Any] = list(malformed)
|
||||||
|
thread_id = None
|
||||||
|
turns = 0
|
||||||
|
for event in events:
|
||||||
|
event_type = event.get("type")
|
||||||
|
if event_type == "thread.started":
|
||||||
|
thread_id = event.get("thread_id")
|
||||||
|
elif event_type == "turn.completed":
|
||||||
|
turns += 1
|
||||||
|
turn_usage = event.get("usage") or {}
|
||||||
|
for field in ("input_tokens", "cached_input_tokens", "output_tokens", "reasoning_output_tokens"):
|
||||||
|
value = turn_usage.get(field, 0)
|
||||||
|
if isinstance(value, int):
|
||||||
|
usage[field] += value
|
||||||
|
elif event_type in ("turn.failed", "error"):
|
||||||
|
errors.append(event)
|
||||||
|
if event_type == "item.completed":
|
||||||
|
item = event.get("item") or {}
|
||||||
|
if isinstance(item.get("type"), str):
|
||||||
|
item_types[item["type"]] += 1
|
||||||
|
|
||||||
|
start = parse_iso(meta_dir / "startzeit.txt")
|
||||||
|
end = parse_iso(meta_dir / "endzeit.txt")
|
||||||
|
duration_ms = round((end - start).total_seconds() * 1000) if start and end else None
|
||||||
|
|
||||||
|
exit_code = None
|
||||||
|
exit_code_path = meta_dir / "exitcode.txt"
|
||||||
|
if exit_code_path.exists():
|
||||||
|
try:
|
||||||
|
exit_code = int(exit_code_path.read_text(encoding="utf-8-sig").strip())
|
||||||
|
except ValueError:
|
||||||
|
errors.append("invalid exitcode.txt")
|
||||||
|
if exit_code not in (None, 0):
|
||||||
|
errors.append({"exit_code": exit_code})
|
||||||
|
|
||||||
|
normalized = {
|
||||||
|
"adapter": "codex-cli",
|
||||||
|
"is_error": bool(errors),
|
||||||
|
"subtype": "success" if not errors else "error",
|
||||||
|
"session_id": thread_id,
|
||||||
|
"duration_ms": duration_ms,
|
||||||
|
"duration_api_ms": None,
|
||||||
|
"num_turns": turns,
|
||||||
|
"requested_model": args.model,
|
||||||
|
"actual_models": None,
|
||||||
|
"model_control": "not_verifiable_from_codex_exec_jsonl",
|
||||||
|
"effort": args.effort,
|
||||||
|
"usage": {
|
||||||
|
"input_tokens": usage["input_tokens"],
|
||||||
|
"cached_input_tokens": usage["cached_input_tokens"],
|
||||||
|
"output_tokens": usage["output_tokens"],
|
||||||
|
"reasoning_output_tokens": usage["reasoning_output_tokens"],
|
||||||
|
"total_tokens": usage["input_tokens"] + usage["output_tokens"],
|
||||||
|
"semantics": "cached_input_tokens is a subset of input_tokens and is not added again",
|
||||||
|
},
|
||||||
|
"item_counts": dict(sorted(item_types.items())),
|
||||||
|
"permission_denials": None,
|
||||||
|
"subagent_stats": {"spawned": 0, "source": "multi-agent disabled by configuration"},
|
||||||
|
"materialized_files": materialized,
|
||||||
|
"result": envelope.get("summary", ""),
|
||||||
|
"errors": errors,
|
||||||
|
}
|
||||||
|
(run_dir / "RawResult.json").write_text(
|
||||||
|
json.dumps(normalized, ensure_ascii=False, indent=2) + "\n",
|
||||||
|
encoding="utf-8",
|
||||||
|
newline="\n",
|
||||||
|
)
|
||||||
|
return 1 if errors else 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
File diff suppressed because it is too large
Load Diff
+269
-14
@@ -1,6 +1,7 @@
|
|||||||
# Ablaufprotokoll der Versuchsdurchführung
|
# Ablaufprotokoll der Versuchsdurchführung
|
||||||
|
|
||||||
**Zeitraum:** 25.–26. August 2026
|
**Zeitraum:** 25.–26. August 2026
|
||||||
|
**Ablage der Läufe:** `Versuche/Versuch_01/Tag 1/` – alle 24 Läufe entstanden am 25. August
|
||||||
**Untersuchungsgegenstand:** c-entron ERP-Suite, eingefrorener Snapshot `79c1142`
|
**Untersuchungsgegenstand:** c-entron ERP-Suite, eingefrorener Snapshot `79c1142`
|
||||||
**Zweck dieses Dokuments:** Grundlage für den Ergebnisteil der Arbeit (Kapitel 5 und 6).
|
**Zweck dieses Dokuments:** Grundlage für den Ergebnisteil der Arbeit (Kapitel 5 und 6).
|
||||||
|
|
||||||
@@ -29,7 +30,7 @@ gleichen Bedingungen streuen.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2. Chronologie in fünf Phasen
|
## 2. Chronologie in sechs Phasen
|
||||||
|
|
||||||
### Phase 1 – Erster Lauf und die Entdeckung der Werkzeugkonfiguration (12:29–13:00)
|
### Phase 1 – Erster Lauf und die Entdeckung der Werkzeugkonfiguration (12:29–13:00)
|
||||||
|
|
||||||
@@ -135,10 +136,156 @@ Abgleich der tatsächlich eingesetzten Modelle wurde zur Pflichtprüfung.
|
|||||||
|
|
||||||
### Phase 5 – Nachbereitung und Ausrichtung auf die Arbeit (26.08.)
|
### Phase 5 – Nachbereitung und Ausrichtung auf die Arbeit (26.08.)
|
||||||
|
|
||||||
Nach Abschluss der Läufe wurden Struktur und Dokumentation konsolidiert: Umstellung der
|
Nach Abschluss der Läufe folgte die Konsolidierung. Sie ist kein bloßes Aufräumen: Mehrere
|
||||||
Kostenangabe auf Tokenverbrauch, Ordnerstruktur nach Bedingungen, maschinelle Auswertung der
|
Schritte haben Messfehler aufgedeckt oder die Belastbarkeit der Ergebnisse erst hergestellt.
|
||||||
erzeugten Anforderungen, Sicherung des Untersuchungsgegenstands im Arbeitsrepository sowie die
|
|
||||||
Trennung von Analyseanweisung (Prompt) und Prozessvorgabe (Skill).
|
**Aufwandsgröße von Kosten auf Tokenverbrauch umgestellt** (Skill 3.5.0). USD-Beträge hängen an
|
||||||
|
Preisliste und Modellwahl und veralten; Token sind die unmittelbare Verbrauchsgröße. Bei der
|
||||||
|
Umstellung fiel auf, dass sich die berichteten Streuungsfaktoren ändern: In Dollar lag V1 gegen
|
||||||
|
V1b bei Faktor 2,1 zu 5,6, in Token bei 2,9 zu 4,6. Cache-Read-Token werden günstiger
|
||||||
|
abgerechnet als Output-Token – eine reine Tokensumme gewichtet sie gleich, der Preis nicht.
|
||||||
|
Die inhaltliche Aussage bleibt, der Abstand ist geringer als die Dollarwerte nahelegten.
|
||||||
|
|
||||||
|
**Verschachtelte Subagenten verifiziert** (Skill 3.6.0). Bis dahin war unbelegt, ob Subagenten
|
||||||
|
auf Tiefe 2 in die Tokensumme einfließen. Ein Kontrolltest mit erzwungener Kaskade, bei dem
|
||||||
|
ausschließlich der Enkel-Agent arbeitete, ergab 49.103 Token im Hauptagenten gegenüber 1.689.288
|
||||||
|
in `modelUsage` – die Differenz stammt nachweislich von der tieferen Ebene. Nebenbefund:
|
||||||
|
Subagenten-Transkripte werden nicht separat persistiert, ihre Prompts sind daher nicht
|
||||||
|
rekonstruierbar, ihre Tokens dagegen vollständig erfasst.
|
||||||
|
|
||||||
|
**Untersuchungsgegenstand im Arbeitsrepository gesichert.** Die Codebasis war nur als Gitlink
|
||||||
|
auf `79c1142` getrackt – ohne `.gitmodules` und ohne erreichbares Remote, nachdem das
|
||||||
|
GitHub-Remote zu Versuchsbeginn entkoppelt worden war. Ein Klon des Arbeitsrepositories hätte
|
||||||
|
ein leeres Verzeichnis erhalten; keiner der 3.287 Anforderungsbelege wäre überprüfbar gewesen.
|
||||||
|
Die Historie wurde aus dem Arbeitsbaum ausgelagert und der Dateiinhalt als reguläre Dateien
|
||||||
|
aufgenommen: 24.557 Dateien, rund 333 MB. Prompts, Protokolle, Ergebnisartefakte und der
|
||||||
|
analysierte Quellcode sind damit gemeinsam versioniert.
|
||||||
|
|
||||||
|
**Maschinelle Auswertung der Anforderungen** (Skill 3.9.0). Die Protokolle maßen bis dahin nur
|
||||||
|
den Aufwand, nicht den Ertrag. Ein Auswertungsskript parst die 3.287 Anforderungsblöcke und
|
||||||
|
erhebt Verteilung, Typen, Belegqualität, Status und – methodisch am wertvollsten – die
|
||||||
|
**Regelkonformität gegen die Vorgaben des Prompts selbst**. Erste Anwendung deckte sofort
|
||||||
|
Verstöße gegen die risikobasierte Priorisierung auf, die von Hand nicht auffindbar gewesen wären.
|
||||||
|
|
||||||
|
**Ordnerstruktur nach Bedingungen** (Skill 3.10.0, später 4.1.0). Modell, Agentenmodus und
|
||||||
|
Effort wurden von Namensbestandteilen zu Ordnerebenen; darüber kam die Ebene `<Versuchstag>`.
|
||||||
|
Die Zellenbelegung ist damit unmittelbar abzählbar – und die Struktur macht sichtbar, dass von
|
||||||
|
den möglichen Kombinationen nur fünf belegt sind.
|
||||||
|
|
||||||
|
**Ausrichtung auf Kapitel 4** (Skill 4.0.0). Prompt und Skill waren organisch gewachsen und
|
||||||
|
stellenweise nicht mehr deckungsgleich mit dem Versuchsdesign der Arbeit. Der Prompt enthielt
|
||||||
|
Aussagen zur Werkzeugkonfiguration, die ihn an ein bestimmtes Werkzeug banden; der Skill
|
||||||
|
verankerte weder den Evaluationsrahmen noch die geforderten Reproduzierbarkeitsangaben. Beides
|
||||||
|
wurde getrennt: Der Prompt trägt seither ausschließlich die Analyseanweisung, der Skill den
|
||||||
|
Prozess. Werkzeugkontext und Ausgabeverzeichnis werden zur Laufzeit angehängt.
|
||||||
|
|
||||||
|
Dabei fiel die Zuordnungsfrage an: Die Arbeit kannte nur V1 „Prompt-only, keine Agentendateien".
|
||||||
|
Werkzeugeigene Subagenten sind keine Agentendateien und wären nach Wortlaut in V1 erlaubt –
|
||||||
|
ihr Einsatz verändert die Ergebnisse aber erheblich. Entschieden wurde **V1 = `solo`,
|
||||||
|
V1b = `builtin`**; Kapitel 4 der Arbeit wurde um V1b und um einen Absatz zum vorgezogenen
|
||||||
|
Modellvergleich ergänzt.
|
||||||
|
|
||||||
|
**Prompt-Version 02** (Skill 4.2.0). Auf Basis der Auswertung entstand die erste echte
|
||||||
|
Iteration – ausführlich in Abschnitt 7.
|
||||||
|
|
||||||
|
### Phase 6 – Prompt-Version 02, zehn Läufe und ein geänderter Untersuchungsgegenstand (26.08., ab 08:43)
|
||||||
|
|
||||||
|
Prompt-Version 02 wurde erstmals gemessen: ein serieller Lauf, danach zwei Parallelblöcke zu vier
|
||||||
|
und fünf Läufen. Zwischen den Blöcken änderte sich der Untersuchungsgegenstand, weshalb die zehn
|
||||||
|
Läufe auf **Iteration 2** (fünf Läufe, ohne DB-Schema) und **Iteration 3** (fünf Läufe, mit
|
||||||
|
verfügbarem DB-Schema) aufgeteilt sind. Alle zehn liefen unter `claude-sonnet-5` / `solo` / `high`.
|
||||||
|
|
||||||
|
**Die Menge wird gebunden, die Struktur nicht.** Iteration 2 ergab 123 bis 185 Anforderungen
|
||||||
|
(Faktor 1,50) gegenüber 42 bis 82 unter Prompt-Version 01 (Faktor 2,0). Das Modulinventar aus
|
||||||
|
Schritt 0 bindet die Anzahl also messbar. Die **Ebenenverteilung** streut dagegen über beide
|
||||||
|
Iterationen extrem – von 92,7 % auf Stakeholder- bis 89,4 % auf Softwareebene:
|
||||||
|
|
||||||
|
| Lauf | It. | Anf. | StRS/SyRS/SwRS | Primärbeleg | Tracelinks | Risiko offen | Tokens |
|
||||||
|
|---|---:|---:|---|---:|---:|---:|---:|
|
||||||
|
| d6f9 *(seriell)* | 2 | 170 | 20/120/30 | 85,3 % | 100 % | 1 von 51 | 35,7 Mio. |
|
||||||
|
| 3983 | 2 | 185 | 37/28/120 | 34,6 % | 100 % | **18 von 49** | 17,3 Mio. |
|
||||||
|
| 4840 | 2 | 123 | **114/2/7** | 56,1 % | **56,9 %** | 1 von 17 | **53,4 Mio.** |
|
||||||
|
| f631 | 2 | 156 | 40/56/60 | **98,1 %** | 91,7 % | **0** | 18,2 Mio. |
|
||||||
|
| c69e | 2 | 160 | 21/15/124 | 73,8 % | 100 % | 2 von 42 | 13,0 Mio. |
|
||||||
|
| 0848 | 3 | 211 | 134/39/38 | 43,6 % | **49,8 %** | 7 von 46 | **11,4 Mio.** |
|
||||||
|
| 1b24 | 3 | 215 | 34/101/80 | 42,8 % | 100 % | 8 von 48 | 49,7 Mio. |
|
||||||
|
| 2316 | 3 | 175 | 20/36/119 | 78,3 % | 100 % | **0** | 48,3 Mio. |
|
||||||
|
| 3ef5 | 3 | **237** | 25/28/184 | 38,8 % | 100 % | 9 von 51 | **68,9 Mio.** |
|
||||||
|
| b652 | 3 | 151 | 7/9/135 | **96,0 %** | 100 % | **0** | 42,9 Mio. |
|
||||||
|
|
||||||
|
Der Prompt verlangt in Schritt 0b je Modul mindestens eine Anforderung, sagt aber nicht, **auf
|
||||||
|
welcher Ebene**. Genau diese Lücke erzeugt die verbliebene Streuung. Auch der Inventarbegriff ist
|
||||||
|
je Lauf ein anderer: 120 fachliche Module, 133 nach fachlich und technisch getrennt, oder eine
|
||||||
|
Gliederung nach Verzeichnisstruktur des WPF-Clients. Für Prompt-Version 03 ist das der konkreteste
|
||||||
|
Ansatzpunkt.
|
||||||
|
|
||||||
|
**Befund 6.1 bestätigt sich – in verschärfter Form.** Über alle zehn Läufe korrelieren
|
||||||
|
Anforderungszahl und Primärbelegquote **negativ** (Pearson −0,63, Spearman −0,70). Die Läufe mit
|
||||||
|
der besten Belegqualität liefern die wenigsten Anforderungen (`f631` 98,1 % bei 156, `b652` 96,0 %
|
||||||
|
bei 151), die mengenstärksten die schlechteste (`3ef5` 38,8 % bei 237, `3983` 34,6 % bei 185).
|
||||||
|
Die Anforderungszahl ist damit nicht nur kein Qualitätsmaß – als Maß genommen zeigt sie **ins
|
||||||
|
Gegenteil**.
|
||||||
|
|
||||||
|
**Der Untersuchungsgegenstand änderte sich mitten im Betrieb (10:28:08).** `SSMS_DB_SCHEMA.sql`
|
||||||
|
kam in das Arbeitsverzeichnis: 3.266.626 B, 76.793 Zeilen, 1.558 Tabellen, 182 Views, 63
|
||||||
|
Prozeduren, 30 Funktionen, 134 Fremdschlüssel. Der Prompt fordert Datenbankschemata in Schritt 2
|
||||||
|
ausdrücklich als Quelle; Läufe mit und ohne die Datei sind nicht poolbar. Die Vorher/Nachher-
|
||||||
|
Prüfung erfasste die Änderung selbsttätig – `_meta/before.txt` der neuen Läufe ist 46 B statt 2 B.
|
||||||
|
Der Snapshot wurde als eigener Commit `f349d189` festgeschrieben.
|
||||||
|
|
||||||
|
**Verfügbarkeit ist nicht Nutzung.** Von den fünf Läufen der Iteration 3 haben nur **drei** das
|
||||||
|
Schema geöffnet (`0848`, `1b24`, `2316`); `3ef5` und `b652` haben es in der Verzeichnisauflistung
|
||||||
|
gesehen und ignoriert. Ob das Schema genutzt wird, ist damit eine **abhängige** Variable und wird
|
||||||
|
seither je Lauf erhoben – über Werkzeugaufrufe, deren *Eingabe* den Dateinamen nennt, nicht über
|
||||||
|
Texttreffer im Transkript.
|
||||||
|
|
||||||
|
Ein Verbrauchseffekt ist **nicht belegt**: `0848` nutzte das Schema und war mit 11,4 Mio. Tokens
|
||||||
|
der sparsamste Lauf beider Iterationen, `2316` nutzte es ebenfalls und verbrauchte 48,3 Mio.
|
||||||
|
`3ef5` nutzte es nicht und war mit 68,9 Mio. der teuerste. Der Median der Anforderungszahl steigt
|
||||||
|
von 160 (Iteration 2) auf 211 (Iteration 3), aber die Spannen überlappen deutlich (123–185 gegen
|
||||||
|
151–237), und innerhalb der Iteration 3 trennt die Nutzung die Läufe nicht. Bei n = 5 je Gruppe
|
||||||
|
ist das ein Hinweis, keine Wirkung.
|
||||||
|
|
||||||
|
**Ein Lauf lag auf der Grenze und wurde am Transkript entschieden.** `094249_v4.2.1-4840` startete
|
||||||
|
um 09:43 ohne die Datei und lief noch, als sie erschien. Sein Transkript enthält **null Treffer**
|
||||||
|
für `SSMS_DB_SCHEMA`, `CentronVOED2` und `.sql` – er gehört zweifelsfrei zu Iteration 2. Dabei
|
||||||
|
fiel eine Grenze der Read-only-Verifikation auf: Sein `before.txt` und sein `after.txt` sind beide
|
||||||
|
leer, aber aus verschiedenen Gründen (vorher existierte die Datei nicht, nachher war sie
|
||||||
|
committet). Zwei gleiche Messwerte bei ungleichen Zuständen – für künftige Läufe wäre der
|
||||||
|
Snapshot zusätzlich über einen Inhaltshash zu führen.
|
||||||
|
|
||||||
|
**Drei Defekte am Messinstrument aufgedeckt und behoben.** Keiner ließ einen Lauf fehlschlagen,
|
||||||
|
alle drei hätten Protokollangaben verfälscht:
|
||||||
|
|
||||||
|
- *Root-Prüfung ohne Pfadfilter* (Skill 4.2.1). Seit die Codebasis als Dateien im Arbeitsrepo
|
||||||
|
liegt statt als Gitlink, lieferte `git -C <root> status --porcelain` den Status des gesamten
|
||||||
|
Arbeitsrepos – rund 55 KB, praktisch nur Versuchsdateien.
|
||||||
|
- *Ebenenbestimmung nach Dateiname* (Skill 4.3.0). Das Auswertungsskript leitete die Ebene einer
|
||||||
|
Anforderung aus der Datei ab, in der ihr Block stand. `c69e` legte 12 StRS- und 5 SyRS-Blöcke in
|
||||||
|
`SwRS.md` ab; die Verteilungstabelle meldete 9/10/141 statt der tatsächlichen 21/15/124. Der
|
||||||
|
Agent hatte korrekt gezählt, das Skript widersprach ihm zu Unrecht. Alle 24 Läufe der
|
||||||
|
Iteration 1 wurden gegengeprüft: keine Fremdablage, ihre Protokolle bleiben gültig.
|
||||||
|
- *Schema-Nutzung über Texttreffer*. Die erste Fassung der Erhebung zählte Vorkommen im
|
||||||
|
Transkript und stufte `b652` als Nutzer ein – der Treffer stammte aus der Verzeichnisauflistung.
|
||||||
|
Gezählt werden seither nur Werkzeugaufrufe mit dem Dateinamen in der **Eingabe**.
|
||||||
|
|
||||||
|
Die Fremdablage aus dem zweiten Punkt ist kein Skriptartefakt, sondern ein Befund zur
|
||||||
|
**Set-Qualität**: Die Dreiteilung StRS / SyRS / SwRS ist dann nicht mehr an der Dateistruktur
|
||||||
|
ablesbar.
|
||||||
|
|
||||||
|
**Die Denylist erzeugt systematisch Streudateien.** Drei der zehn Läufe (`f631`, `b652`, `3ef5`)
|
||||||
|
ließen Arbeitsdateien im Ergebnisordner zurück – bis zu sechs bei `3ef5`. In allen Fällen hatte
|
||||||
|
der Agent versucht, sie aufzuräumen (`rm`, `Remove-Item`), und wurde von der Denylist gestoppt;
|
||||||
|
die Löschversuche machen den Großteil aller Permission-Denials dieser Läufe aus. Die Dateien
|
||||||
|
bleiben bewusst liegen: Nachträgliches Löschen würde die Artefaktlage verändern. Der Befund
|
||||||
|
gehört zur Werkzeugkonfiguration, nicht zum Modell – die Denylist sperrt Löschbefehle pauschal,
|
||||||
|
auch im Laufverzeichnis, für das der Agent Schreibrecht hat.
|
||||||
|
|
||||||
|
**Zwei Umbenennungen** (Skill 4.4.0). Die Ordnerebene `<Versuchstag>` heißt jetzt `<Iteration>`:
|
||||||
|
Der alte Name band sie an das Kalenderdatum, obwohl sie die Vergleichbarkeit abbildet – Iteration 2
|
||||||
|
und Iteration 3 entstanden am selben Tag. Weil „Iteration" mit der Fassung der Prompt-Datei
|
||||||
|
kollidierte, heißt diese seither **Prompt-Version**. Die Prompt-Dateien selbst blieben unverändert:
|
||||||
|
Ihre SHA-256 sind in 33 Protokollen dokumentiert.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -146,9 +293,12 @@ Trennung von Analyseanweisung (Prompt) und Prozessvorgabe (Skill).
|
|||||||
|
|
||||||
Der Prompt blieb inhaltlich über alle 24 Läufe **unverändert** – der SHA-256
|
Der Prompt blieb inhaltlich über alle 24 Läufe **unverändert** – der SHA-256
|
||||||
`1B0DB06B…3C02FF` ist in jedem Protokoll dokumentiert. Alle 24 Läufe sind damit
|
`1B0DB06B…3C02FF` ist in jedem Protokoll dokumentiert. Alle 24 Läufe sind damit
|
||||||
Wiederholungsmessungen desselben Prompts, keine Iterationen im Sinne von Kapitel 4.
|
Wiederholungsmessungen desselben Prompts, keine Prompt-Versionen im Sinne von Kapitel 4.
|
||||||
|
|
||||||
Erst nach Abschluss der Läufe wurde er überarbeitet (2026-08-26):
|
Erst nach Abschluss der Läufe wurde er überarbeitet (2026-08-26). Diese Überarbeitung war
|
||||||
|
zunächst rein formal – sie machte den Prompt werkzeugneutral, ohne die Analyseanweisung zu
|
||||||
|
ändern. Die inhaltliche Überarbeitung folgte als **Prompt-Version 02** und ist in Abschnitt 7
|
||||||
|
dokumentiert.
|
||||||
|
|
||||||
| Änderung | Grund |
|
| Änderung | Grund |
|
||||||
|---|---|
|
|---|---|
|
||||||
@@ -165,7 +315,7 @@ Voraussetzung für den in Kapitel 4 geplanten LLM-Querschnitt.
|
|||||||
|
|
||||||
## 4. Entwicklung des Versuchsaufbaus (Skill)
|
## 4. Entwicklung des Versuchsaufbaus (Skill)
|
||||||
|
|
||||||
17 Versionen in zwei Tagen. Jede geht auf eine konkrete Beobachtung zurück:
|
19 Versionen in zwei Tagen. Jede geht auf eine konkrete Beobachtung zurück:
|
||||||
|
|
||||||
| Version | Änderung | Auslöser |
|
| Version | Änderung | Auslöser |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@@ -186,11 +336,16 @@ Voraussetzung für den in Kapitel 4 geplanten LLM-Querschnitt.
|
|||||||
| 3.9.0 | Pflichtabschnitt „Gefundene Anforderungen" | Protokolle maßen nur Aufwand, nicht Ertrag |
|
| 3.9.0 | Pflichtabschnitt „Gefundene Anforderungen" | Protokolle maßen nur Aufwand, nicht Ertrag |
|
||||||
| 3.10.0 | Bedingungen als Ordnerstruktur statt im Dateinamen | Der Name wuchs mit jeder Variable und war kaum noch lesbar |
|
| 3.10.0 | Bedingungen als Ordnerstruktur statt im Dateinamen | Der Name wuchs mit jeder Variable und war kaum noch lesbar |
|
||||||
| 4.0.0 | Zweiteilung Prozess/Werkzeugadapter; V1 = `solo`, V1b = `builtin`; Evaluationsrahmen verankert | Ausrichtung auf Kapitel 4 der Arbeit |
|
| 4.0.0 | Zweiteilung Prozess/Werkzeugadapter; V1 = `solo`, V1b = `builtin`; Evaluationsrahmen verankert | Ausrichtung auf Kapitel 4 der Arbeit |
|
||||||
|
| 4.1.0 | Ebene `<Versuchstag>` über den Bedingungen | Der Aufbau durchlief an Tag 1 siebzehn Versionen; die Tagesebene hält Blöcke auseinander, die unter unterschiedlichem Stand entstanden |
|
||||||
|
| 4.2.0 | Auswahlregel bei mehreren Prompt-Versionen; Protokollfeld „Prompt-Version" | Mit `02_Prompt.md` liegt erstmals mehr als eine Fassung vor; ohne Regel ließe sich der SHA-256 im Protokoll keiner Datei mehr zuordnen |
|
||||||
|
|
||||||
**Beobachtung für die Diskussion:** Zehn der sechzehn Änderungen gehen auf Messfehler oder
|
**Beobachtung für die Diskussion:** Von den achtzehn Änderungen gehen zehn auf Messfehler oder
|
||||||
Fehlannahmen zurück, die erst im Betrieb sichtbar wurden – nicht auf Planungslücken im
|
Fehlannahmen zurück, die erst im Betrieb sichtbar wurden – nicht auf Planungslücken im
|
||||||
klassischen Sinn. Ein Versuchsaufbau für agentische LLM-Werkzeuge lässt sich offenbar nicht
|
klassischen Sinn. Betroffen waren durchweg Annahmen, die plausibel schienen und sich als falsch
|
||||||
vollständig vorab spezifizieren.
|
erwiesen: dass `--safe-mode` genügt, dass `--model` die Subagenten steuert, dass `duration_ms`
|
||||||
|
die Laufzeit misst, dass gesperrte Werkzeuge Denials erzeugen, dass `git status` alle
|
||||||
|
Schreibvorgänge erfasst. Ein Versuchsaufbau für agentische LLM-Werkzeuge lässt sich offenbar
|
||||||
|
nicht vollständig vorab spezifizieren; er entsteht in der Auseinandersetzung mit dem Werkzeug.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -305,7 +460,93 @@ deckt ausschließlich die Codebasis ab. Schreibvorgänge in andere Verzeichnisse
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 7. Grenzen und offene Punkte
|
## 7. Prompt-Version 02 (26.08.)
|
||||||
|
|
||||||
|
Bis hierher waren alle 24 Läufe **Wiederholungsmessungen desselben Prompts** – der SHA-256 blieb
|
||||||
|
über zwei Tage identisch. Prompt-Version 02 ist damit die erste Prompt-Version im Sinne von Kapitel 4:
|
||||||
|
Der Prompt wird auf Basis der Auswertung überarbeitet, jede Änderung ist an einen gemessenen
|
||||||
|
Befund gekoppelt.
|
||||||
|
|
||||||
|
### Was der Prompt bereits zuverlässig steuert
|
||||||
|
|
||||||
|
Diese Teile blieben unverändert, weil die Auswertung keine Schwäche zeigt:
|
||||||
|
|
||||||
|
| Vorgabe | Ergebnis über 3.287 Anforderungen |
|
||||||
|
|---|---|
|
||||||
|
| Prüfidee je Anforderung | 100 % erfüllt |
|
||||||
|
| Tracelinks je Anforderung | 100 % erfüllt |
|
||||||
|
| Belegklassifikation | 78,6 % `PRIMÄR`, 11,5 % `SEKUNDÄR`, 9,8 % `KONTEXT` |
|
||||||
|
| Blockformat der Anforderungen | über alle Läufe eingehalten |
|
||||||
|
|
||||||
|
### Was der Prompt nicht steuerte
|
||||||
|
|
||||||
|
| Befund | Zahl |
|
||||||
|
|---|---|
|
||||||
|
| Anforderungen je Lauf | 42 – 325 (Faktor 5,9) |
|
||||||
|
| Modultabellen im Analysebericht | 0 – 51 Zeilen |
|
||||||
|
| Läufe ohne jede Hypothese | 2 (bei 71 bzw. 148 Anforderungen) |
|
||||||
|
| Hypothesenanteil je Lauf | 0 % – 26,2 % |
|
||||||
|
| Konsolidierungskandidaten je Lauf | 2,4 % – 35,2 % |
|
||||||
|
| Anforderungen mit genau einem Beleg | 45,9 % |
|
||||||
|
| Anforderungen ohne jeden Beleg | 1 |
|
||||||
|
| ISO-25010-Merkmal als eigenes Feld | 50 von 3.287 (1,5 %) |
|
||||||
|
| verschiedene `Typ`-Werte | 301 |
|
||||||
|
|
||||||
|
### Abgeleitete Änderungen
|
||||||
|
|
||||||
|
1. **Abdeckung wird gesteuert statt dem Modell überlassen.** Der Satz „Priorisiere die
|
||||||
|
Analysetiefe selbstständig" entfällt. An seine Stelle tritt eine dreistufige Vorstufe:
|
||||||
|
Modulinventar vor der ersten Anforderung, dann Mindestabdeckung mit mindestens einer
|
||||||
|
Anforderung je Modul, dann Vertiefung nach Risiko. Begründung im Prompt: Ein fehlendes
|
||||||
|
Requirement führt bei einer Neuimplementierung zu Funktionsverlust, eine flach erfasste
|
||||||
|
Funktion lässt sich nachschärfen.
|
||||||
|
2. **Hypothesenpflicht kalibriert.** Wer keine Hypothese führt, begründet das ausdrücklich.
|
||||||
|
`Hypothesen.md` muss deckungsgleich mit den Inline-Markierungen sein.
|
||||||
|
3. **Primärbeleg präzisiert.** Bei Risikoanforderungen genügt ein Dateipfad nicht mehr; der
|
||||||
|
Beleg benennt Datei, Klasse, Methode und die konkrete Prüfung.
|
||||||
|
4. **Belegpflicht verschärft.** Ohne Beleg wird die Anforderung nicht geschrieben, der offene
|
||||||
|
Punkt wird als Hypothese erfasst.
|
||||||
|
5. **Konsolidierungsbegriff an einem Beispiel kalibriert** (Stammblätter gegenüber Assets), mit
|
||||||
|
ausdrücklicher Abgrenzung gegen ebenenübergreifende Dubletten.
|
||||||
|
6. **Feld `Qualitätsmerkmal`** für die ISO-25010-Zuordnung, die bislang keinen Ablageort hatte.
|
||||||
|
7. **Konsistenzcheck erweitert** um eine Liste aller risikorelevanten Anforderungen mit ihrer
|
||||||
|
Belegsituation und um den Abgleich der Hypothesenliste.
|
||||||
|
|
||||||
|
### Bewusst nicht geändert
|
||||||
|
|
||||||
|
Die formale Streuung – 301 `Typ`-Werte, zwei ID-Schemata, acht Hypothesen-Formate – bleibt
|
||||||
|
bestehen. Geschlossene Vokabulare und erzwungene Dateivorlagen hätten sie beseitigt, wurden aber
|
||||||
|
verworfen, um die Formulierungsfreiheit nicht einzuschränken. Für die Auswertung ist diese
|
||||||
|
Streuung als Rauschen zu behandeln; die maschinelle Analyse ist entsprechend heuristisch
|
||||||
|
ausgelegt.
|
||||||
|
|
||||||
|
### Nebenbefund: Der Prompt war nachträglich verändert worden
|
||||||
|
|
||||||
|
Bei der Einführung von `02_Prompt.md` fiel auf, dass `01_Prompt.md` im Zuge der
|
||||||
|
werkzeugneutralen Überarbeitung geändert und committet worden war. Der in allen 24 Protokollen
|
||||||
|
dokumentierte SHA-256 zeigte damit auf eine Fassung, die im Repository nicht mehr existierte.
|
||||||
|
|
||||||
|
Die As-Run-Fassung ließ sich **bitgenau rekonstruieren**: Aus dem je Lauf archivierten
|
||||||
|
`_meta/combined_prompt.md` den Text vor dem angehängten Ausgabeverzeichnis-Block abschneiden,
|
||||||
|
Zeilenenden normalisieren – das Ergebnis stimmt für drei unabhängig geprüfte Läufe exakt mit
|
||||||
|
`1B0DB06B…3C02FF` überein. `01_Prompt.md` wurde darauf zurückgesetzt.
|
||||||
|
|
||||||
|
**Methodische Lehre:** Die Archivierung des tatsächlich gesendeten Prompts je Lauf, ursprünglich
|
||||||
|
als Nebeneffekt der Parallelfähigkeit eingeführt (Skill 3.1.0), hat hier die Reproduzierbarkeit
|
||||||
|
gerettet. Ohne sie wäre der Bezug zwischen Protokoll und Prompt unwiederbringlich verloren
|
||||||
|
gewesen.
|
||||||
|
|
||||||
|
### Offene Frage
|
||||||
|
|
||||||
|
Ob die Steuerung greift, ist eine empirische Frage. Erwartet wird eine höhere Anforderungszahl
|
||||||
|
bei geringerer Tiefe je Modul und eine **kleinere Streuung** zwischen Läufen. Der Vergleich mit
|
||||||
|
den fünf Solo-Läufen von Tag 1 (42 bis 82 Anforderungen, Faktor 2,0) wird das zeigen. Möglich
|
||||||
|
ist auch, dass die Mindestabdeckung nur die Zahl flacher Anforderungen erhöht, ohne die
|
||||||
|
Belegqualität zu halten – dann wäre die Änderung zurückzunehmen.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Grenzen und offene Punkte
|
||||||
|
|
||||||
**Nicht geklärt:** Ob der Verbrauchssprung im Fable-Block vom Modell oder vom Effort kommt –
|
**Nicht geklärt:** Ob der Verbrauchssprung im Fable-Block vom Modell oder vom Effort kommt –
|
||||||
beide Variablen wechselten gleichzeitig. Ein Fable-Block auf `high` oder ein Sonnet-Block auf
|
beide Variablen wechselten gleichzeitig. Ein Fable-Block auf `high` oder ein Sonnet-Block auf
|
||||||
@@ -321,6 +562,20 @@ vorbereitet (Modus `custom`), die Agentendefinitionen existieren aber noch nicht
|
|||||||
**Offene Aufräumarbeiten:** Drei Streudateien in `C:\DEV\` aus Lauf 13; die Erweiterung der
|
**Offene Aufräumarbeiten:** Drei Streudateien in `C:\DEV\` aus Lauf 13; die Erweiterung der
|
||||||
Nachlaufprüfung um Streudateien außerhalb des Laufverzeichnisses.
|
Nachlaufprüfung um Streudateien außerhalb des Laufverzeichnisses.
|
||||||
|
|
||||||
|
**Nicht poolbar:** Iteration 2 und Iteration 3 unterscheiden sich im Untersuchungsgegenstand
|
||||||
|
(`SSMS_DB_SCHEMA.sql`, Commit `f349d189`). Ein Vergleich beider misst die Wirkung des
|
||||||
|
Datenbankschemas – ein eigener Befund, keine Wiederholungsmessung. Mit n = 5 je Gruppe und
|
||||||
|
überlappenden Spannen ist diese Wirkung derzeit **nicht** belegt.
|
||||||
|
|
||||||
|
**Messtechnisch offen:** Der Snapshot-Zustand wird über `git status` geführt. Wird eine Datei
|
||||||
|
zwischen Laufbeginn und Auswertung committet, sind Vorher- und Nachher-Stand gleich, obwohl die
|
||||||
|
Zustände es nicht sind (Fall `4840`). Ein Inhaltshash des Arbeitsverzeichnisses je Lauf würde das
|
||||||
|
schließen.
|
||||||
|
|
||||||
|
**Offen für Prompt-Version 03:** Der Prompt schreibt die Ebene der Mindestabdeckung nicht vor.
|
||||||
|
Das ist die verbliebene Hauptquelle der Strukturstreuung – von 92,7 % StRS bis 89,4 % SwRS bei
|
||||||
|
identischem Prompt.
|
||||||
|
|
||||||
**Einschränkung der Zeitmessung:** 18 der 24 Läufe liefen parallel. Für belastbare
|
**Einschränkung der Zeitmessung:** 18 der 24 Läufe liefen parallel. Für belastbare
|
||||||
Laufzeitvergleiche wären serielle Wiederholungen nötig. Eine Teilauswertung zeigt bei den
|
Laufzeitvergleiche wären serielle Wiederholungen nötig. Eine Teilauswertung zeigt bei den
|
||||||
Solo-Läufen einen messbaren Kontentionseffekt: bei zwei gleichzeitigen Läufen 114–176 Sekunden
|
Solo-Läufen einen messbaren Kontentionseffekt: bei zwei gleichzeitigen Läufen 114–176 Sekunden
|
||||||
@@ -329,9 +584,9 @@ Stichprobe.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 8. Verweise
|
## 9. Verweise
|
||||||
|
|
||||||
- Messprotokolle je Lauf: `Versuche/Versuch_01/<ModellID>/<Modus>/<Effort>/<Laufverzeichnis>/Protokoll.md`
|
- Messprotokolle je Lauf: `Versuche/Versuch_01/Tag 1/<ModellID>/<Modus>/<Effort>/<Laufverzeichnis>/Protokoll.md`
|
||||||
- Rohdaten: `RawResult.json` je Lauf, unverändert erhalten
|
- Rohdaten: `RawResult.json` je Lauf, unverändert erhalten
|
||||||
- Exakt gesendeter Prompt je Lauf: `_meta/combined_prompt.md`
|
- Exakt gesendeter Prompt je Lauf: `_meta/combined_prompt.md`
|
||||||
- Subagenten-Prompts: `_meta/subagenten.md`
|
- Subagenten-Prompts: `_meta/subagenten.md`
|
||||||
|
|||||||
@@ -3,19 +3,17 @@
|
|||||||
## Metadaten
|
## Metadaten
|
||||||
- **Versuch:** V1 Baseline (Prompt-only)
|
- **Versuch:** V1 Baseline (Prompt-only)
|
||||||
- **Iteration:** 01 (Initial-Prompt, zu Versuchsbeginn neu formuliert)
|
- **Iteration:** 01 (Initial-Prompt, zu Versuchsbeginn neu formuliert)
|
||||||
|
- **Werkzeugkonfiguration:** Claude Code, keine Agentendateien, keine MCP-Server
|
||||||
- **Codebasis:** c-entron ERP-Suite (Windows, C#/XAML, MSSQL)
|
- **Codebasis:** c-entron ERP-Suite (Windows, C#/XAML, MSSQL)
|
||||||
|
- **Modell:** Claude (Claude Code)
|
||||||
- **Zeitstempel:** 2026-08-25
|
- **Zeitstempel:** 2026-08-25
|
||||||
- **Änderungsgrund:** Initial-Prompt für V1 Baseline (kein Vorgänger). Vor Erstlauf überarbeitet: Abgleich mit Kap. 4 (RRE-Methodenkette, Evaluationsrahmen) und Kap. 2 (Prozesskontrollen); mit der Vorfassung fand kein Lauf statt. Am 2026-08-26 werkzeugneutral gefasst: Aussagen zu Werkzeugkonfiguration, Modell und Ausgabeverzeichnis entfernt (sie werden vom Versuchsaufbau zur Laufzeit beigestellt und im Messprotokoll dokumentiert); Feld `Übernahmewürdigkeit` aus dem Evaluationsrahmen (Kap. 4.3) ergänzt.
|
- **Änderungsgrund:** Initial-Prompt für V1 Baseline (kein Vorgänger). Vor Erstlauf überarbeitet: Abgleich mit Kap. 4 (RRE-Methodenkette, Evaluationsrahmen) und Kap. 2 (Prozesskontrollen); mit der Vorfassung fand kein Lauf statt.
|
||||||
|
|
||||||
> Dieser Prompt enthält ausschließlich die **Analyseanweisung** und ist damit unabhängig von einem
|
|
||||||
> bestimmten Werkzeug oder Modell einsetzbar. Welche Werkzeuge im jeweiligen Lauf zur Verfügung
|
|
||||||
> stehen und wohin die Ergebnisse geschrieben werden, stellt der Versuchsaufbau beim Start bei.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Prompt
|
## Prompt
|
||||||
|
|
||||||
Du bist ein Requirements Engineer im Reverse Requirements Engineering eines Legacy-ERP-Systems. Erzeuge aus der vorliegenden Codebasis eine Anforderungsspezifikation nach **ISO/IEC/IEEE 29148:2018**. Arbeite ausschließlich auf den im Arbeitsverzeichnis liegenden Artefakten (Quellcode, Konfiguration, UI-Ressourcen, ggf. DB-Skripte). Nutze nur Informationen, die du aus diesen Artefakten gewinnen kannst.
|
Du bist ein Requirements Engineer im Reverse Requirements Engineering eines Legacy-ERP-Systems. Erzeuge aus der vorliegenden Codebasis eine Anforderungsspezifikation nach **ISO/IEC/IEEE 29148:2018**. Arbeite ausschließlich auf den im Arbeitsverzeichnis liegenden Artefakten (Quellcode, Konfiguration, UI-Ressourcen, ggf. DB-Skripte). Es stehen weder spezialisierte Agenten noch MCP-Server zur Verfügung; nutze nur, was als Datei lesbar ist.
|
||||||
|
|
||||||
### Auftrag
|
### Auftrag
|
||||||
|
|
||||||
@@ -53,8 +51,6 @@ Bearbeite die Schritte 2-6 der RRE-Methodenkette (Schritt 1 Scope ist oben vorge
|
|||||||
- **Hypothesenmarkierung:** Aussagen, die sich nicht eindeutig aus Artefakten ableiten lassen, kennzeichnest du explizit mit `[HYPOTHESE]` und einer kurzen Begründung, welche Information zur Bestätigung fehlt.
|
- **Hypothesenmarkierung:** Aussagen, die sich nicht eindeutig aus Artefakten ableiten lassen, kennzeichnest du explizit mit `[HYPOTHESE]` und einer kurzen Begründung, welche Information zur Bestätigung fehlt.
|
||||||
- **Verifizierbarkeit:** Jede Anforderung enthält mindestens eine Prüfidee oder ein Akzeptanzkriterium.
|
- **Verifizierbarkeit:** Jede Anforderung enthält mindestens eine Prüfidee oder ein Akzeptanzkriterium.
|
||||||
- **Eindeutigkeit:** Vermeide vage Begriffe ("schnell", "benutzerfreundlich"); definiere domänenspezifische Begriffe beim ersten Auftreten.
|
- **Eindeutigkeit:** Vermeide vage Begriffe ("schnell", "benutzerfreundlich"); definiere domänenspezifische Begriffe beim ersten Auftreten.
|
||||||
- **Übernahmewürdigkeit:** Beurteile für jede Anforderung, ob ihre Funktion im Zielsystem erhalten bleiben soll. Unterscheide `übernehmen` (fachlich weiterhin erforderlich), `Workaround` (historisch gewachsene Behelfslösung), `Sonderfall` (Ausnahme für einen einzelnen Kunden, Mandanten oder Altbestand) und `veraltet` (durch neuere Logik abgelöst oder fachlich überholt). Begründe die Einstufung in einem Halbsatz. Diese Angabe steuert die spätere fachliche Priorisierung; eine Fehleinschätzung ist unkritisch, eine fehlende Angabe nicht.
|
|
||||||
- **Redundanzfreiheit:** Formuliere jede Anforderung so, dass sie von den übrigen klar abgegrenzt ist. Beschreiben zwei Anforderungen dieselbe fachliche Funktion aus unterschiedlicher Perspektive, führe sie zusammen oder grenze sie im Titel und in der Aussage ausdrücklich gegeneinander ab.
|
|
||||||
|
|
||||||
### Formatvorgabe pro Anforderung
|
### Formatvorgabe pro Anforderung
|
||||||
|
|
||||||
@@ -75,7 +71,6 @@ Belege:
|
|||||||
Prüfidee: <Akzeptanzkriterium oder Testidee>
|
Prüfidee: <Akzeptanzkriterium oder Testidee>
|
||||||
Tracelinks: <verwandte StRS-/SyRS-/SwRS-IDs>
|
Tracelinks: <verwandte StRS-/SyRS-/SwRS-IDs>
|
||||||
Konsolidierung: <nein | Kandidat: <IDs oder Stellen, die dieselbe fachliche Funktion abbilden>>
|
Konsolidierung: <nein | Kandidat: <IDs oder Stellen, die dieselbe fachliche Funktion abbilden>>
|
||||||
Übernahmewürdigkeit: <übernehmen | Workaround | Sonderfall | veraltet> - <kurze Begründung>
|
|
||||||
Status: <belegt | HYPOTHESE>
|
Status: <belegt | HYPOTHESE>
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -108,14 +103,14 @@ Ergebnisse/
|
|||||||
Analysebericht.md (Modul-/Komponentenübersicht, abgedeckte Bereiche, bekannte Lücken)
|
Analysebericht.md (Modul-/Komponentenübersicht, abgedeckte Bereiche, bekannte Lücken)
|
||||||
```
|
```
|
||||||
|
|
||||||
Das Ausgabeverzeichnis wird beim Start des Laufs beigestellt. Die analysierte Codebasis wird ausschließlich gelesen und nicht verändert.
|
Das Ausgabeverzeichnis wird beim Start des Laufs benannt. Die analysierte Codebasis wird ausschließlich gelesen und nicht verändert.
|
||||||
|
|
||||||
### Randbedingungen
|
### Randbedingungen
|
||||||
|
|
||||||
- **Keine Halluzinationen.** Wenn ein Artefakt nicht gelesen oder eine Aussage nicht belegt werden kann, ist das offen zu legen, nicht zu erfinden.
|
- **Keine Halluzinationen.** Wenn ein Artefakt nicht gelesen oder eine Aussage nicht belegt werden kann, ist das offen zu legen, nicht zu erfinden.
|
||||||
- **Keine Generierung von Code.** Es sollen ausschließlich Spezifikationsartefakte entstehen.
|
- **Keine Generierung von Code.** Es sollen ausschließlich Spezifikationsartefakte entstehen.
|
||||||
- **Keine Annahme über nicht beigestellte Hilfsmittel.** Arbeite mit dem, was dir in diesem Lauf zur Verfügung steht. Setze keine zusätzlichen Analysewerkzeuge, Datenbankzugriffe oder laufende Systeme voraus. Stehen für eine Aussage nur indirekte Belege zur Verfügung, ist sie als `[HYPOTHESE]` zu kennzeichnen.
|
- **Keine Annahme nicht vorhandener Tools.** Stehen für eine Aussage nur indirekte Belege zur Verfügung, ist die Aussage als `[HYPOTHESE]` zu kennzeichnen.
|
||||||
- **Migrationsperspektive berücksichtigen.** Erkennbare Workarounds, Sonderfälle und überholte Logik gehören in das Feld `Übernahmewürdigkeit`, nicht in das Feld `Status`. `Status` beschreibt ausschließlich die Belegsituation (`belegt` oder `HYPOTHESE`), `Übernahmewürdigkeit` die fachliche Zukunft der Anforderung. Beide Angaben sind unabhängig voneinander: Eine gut belegte Anforderung kann ein Workaround sein, eine Hypothese kann übernahmewürdig sein.
|
- **Migrationsperspektive berücksichtigen.** Wenn eine Implementierung erkennbar ein historischer Workaround oder Sonderfall ist, vermerke das im Feld `Status` (`belegt; Workaround`), damit es in der späteren Validierung priorisiert geprüft werden kann.
|
||||||
- **Sprache:** Deutsch für Anforderungsaussagen, technische Bezeichner (Klassen, Methoden, Spalten) bleiben in ihrer Originalsprache.
|
- **Sprache:** Deutsch für Anforderungsaussagen, technische Bezeichner (Klassen, Methoden, Spalten) bleiben in ihrer Originalsprache.
|
||||||
|
|
||||||
### Abschluss
|
### Abschluss
|
||||||
@@ -123,9 +118,7 @@ Das Ausgabeverzeichnis wird beim Start des Laufs beigestellt. Die analysierte Co
|
|||||||
Führe vor Abgabe einen **Konsistenzcheck über das gesamte Anforderungs-Set** durch und dokumentiere das Ergebnis im `Analysebericht.md`:
|
Führe vor Abgabe einen **Konsistenzcheck über das gesamte Anforderungs-Set** durch und dokumentiere das Ergebnis im `Analysebericht.md`:
|
||||||
- Doppelte oder mehrfach vergebene IDs
|
- Doppelte oder mehrfach vergebene IDs
|
||||||
- Anforderungen ohne Beleg
|
- Anforderungen ohne Beleg
|
||||||
- Anforderungen ohne Angabe zur `Übernahmewürdigkeit`
|
|
||||||
- Tracelinks auf nicht existierende IDs
|
- Tracelinks auf nicht existierende IDs
|
||||||
- Inhaltlich deckungsgleiche Anforderungen, die nicht als Konsolidierungskandidat markiert sind
|
|
||||||
|
|
||||||
Beende den Lauf mit einer kurzen Selbstbewertung im `Analysebericht.md`:
|
Beende den Lauf mit einer kurzen Selbstbewertung im `Analysebericht.md`:
|
||||||
- Welche Module wurden vollständig analysiert, welche nur stichprobenhaft, welche gar nicht?
|
- Welche Module wurden vollständig analysiert, welche nur stichprobenhaft, welche gar nicht?
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"modulinventar": {
|
||||||
|
"description": "Erstellt das vollständige Modulinventar (Schritt 0) als Bezugsgröße für die Abdeckung. Erzeugt KEINE Anforderungen.",
|
||||||
|
"prompt": "Du erstellst das Modulinventar für ein Reverse-Requirements-Engineering-Vorhaben. Du formulierst KEINE Anforderungen – deine einzige Aufgabe ist eine vollständige, belegte Bestandsaufnahme.\n\nVorgehen:\n1. Verschaffe dir über Verzeichnisauflistungen und Projektdateien (.sln, .csproj, Ordnerstruktur) einen vollständigen Überblick über den Untersuchungsgegenstand. Arbeite von der Struktur aus, nicht von Stichproben.\n2. Erfasse JEDES fachliche Modul und JEDE technische Querschnittskomponente. Ein Modul, das du nicht erfasst, existiert für die gesamte weitere Analyse nicht.\n3. Liefere je Eintrag: laufende ID (M001, M002, …), Modulname, Pfad im Arbeitsverzeichnis, ein Satz zur fachlichen Aufgabe, Anzahl der enthaltenen Quelldateien, und ob es sich um ein fachliches Modul oder eine technische Querschnittskomponente handelt.\n\nHarte Regeln:\n- Der eine Satz zur fachlichen Aufgabe muss aus dem belegen, was du tatsächlich gelesen hast (Klassennamen, UI-Strings, Kommentare, Tabellennamen). Rate nicht aus dem Ordnernamen.\n- Kannst du die Aufgabe eines Moduls nicht bestimmen, führe es mit dem Vermerk `Aufgabe unbestimmt` und einer kurzen Begründung. Lasse es NICHT weg.\n- Nenne am Ende die Gesamtzahl der Module und die Gesamtzahl der Quelldateien, die du dem Inventar zugeordnet hast, sowie die Gesamtzahl der Quelldateien im Arbeitsverzeichnis. Weichen die Zahlen ab, benenne die nicht zugeordneten Bereiche.\n\nDeine Antwort ist das Inventar als Markdown-Tabelle plus die Abschlusszahlen. Keine Einleitung, keine Zusammenfassung."
|
||||||
|
},
|
||||||
|
|
||||||
|
"faktenermittler": {
|
||||||
|
"description": "Erhebt für einen zugewiesenen Modulausschnitt belegte technische Fakten samt der durchsetzenden Codestelle. Formuliert KEINE Anforderungen.",
|
||||||
|
"prompt": "Du erhebst Fakten aus einer Legacy-Codebasis für ein Reverse-Requirements-Engineering-Vorhaben. Du formulierst KEINE Anforderungen und KEINE Interpretationen – die schreibt der Auftraggeber selbst aus deinen Fakten. Liefere ausschließlich zitierfähige technische Beobachtungen.\n\nJe Fakt lieferst du:\n- **Fundstelle:** Pfad, Klasse, Methode und, wenn bestimmbar, Zeilenbereich.\n- **Beobachtung:** Was der Code tatsächlich tut – Statusübergang, Validierungsregel, Berechnungsformel, Berechtigungsprüfung, Constraint, Default. Zitiere die tragende Bedingung wörtlich oder eng paraphrasiert.\n- **Einstufung:** `PRIMÄR`, wenn die genannte Stelle die Regel **durchsetzt**; `SEKUNDÄR`, wenn sie die Regel nur aufruft, konfiguriert oder anzeigt; `KONTEXT`, wenn sie das Umfeld beschreibt.\n\nHarte Regeln – sie entscheiden über die Verwertbarkeit deiner Antwort:\n- **Ein Dateiverweis ist kein Fakt.** „Diese Datei betrifft die Fakturierung\" ist wertlos. Gefordert ist die durchsetzende Stelle samt Bedingung, etwa: `InvoiceService.cs:212, FinalizeInvoice() – wirft InvalidOperationException, wenn invoice.Status == InvoiceStatus.Paid`.\n- **Arbeite nicht mit Stichproben.** Öffne nicht „ein bis drei repräsentative Dateien\". Dein zugewiesener Ausschnitt ist vollständig zu durchsuchen; nutze Suchwerkzeuge, um die tragenden Stellen zu finden, statt zu raten, welche Datei repräsentativ ist.\n- **Melde ausdrücklich, was du NICHT gefunden hast.** Wenn eine Regel offensichtlich existiert, du die durchsetzende Stelle aber nicht lokalisieren konntest, sage das mit Begründung. Diese Meldungen werden zu ausgewiesenen Hypothesen; verschwiegene Lücken werden zu falschen Anforderungen.\n- **Erfinde nichts.** Kein Fakt ohne Fundstelle. Keine Vermutung im Gewand einer Beobachtung.\n\nGehe dort in die Tiefe, wo Sicherheitsregeln, Abrechnungs- und Fakturierungslogik oder Berechtigungsprüfungen liegen. Gliedere deine Antwort nach den Untermodulen deines Ausschnitts."
|
||||||
|
},
|
||||||
|
|
||||||
|
"strs-autor": {
|
||||||
|
"description": "Formuliert Stakeholder-Anforderungen (StRS) im vorgegebenen Blockformat aus gelieferten Fakten. Arbeitet ausschließlich auf der Stakeholder-Ebene.",
|
||||||
|
"prompt": "Du formulierst **ausschließlich Stakeholder-Anforderungen (StRS)** nach ISO/IEC/IEEE 29148. Die Ebene ist deine Zuständigkeit und deine Grenze: Du schreibst keine System- (SyRS) und keine Software-Anforderungen (SwRS), auch dann nicht, wenn die Faktenlage es nahelegt. Verweise stattdessen über Tracelinks.\n\nDie StRS-Ebene beschreibt die **fachliche Sicht**: Akteure, Geschäftsziele, Geschäftsregeln, fachliche Ergebnisse. Sie beschreibt nicht, wie das System das technisch löst.\n\nDu erhältst Fakten mit Fundstelle und Belegeinstufung. Daraus formulierst du Anforderungen im vorgegebenen Blockformat (`ID`, `Titel`, `Ebene`, `Typ`, `Qualitätsmerkmal`, `Akteur`, `Vorbedingung`, `Fakt`, `Aussage`, `Ergebnis`, `Belege`, `Prüfidee`, `Tracelinks`, `Konsolidierung`, `Übernahmewürdigkeit`, `Status`). Das Format ist verbindlich; jedes Feld wird gefüllt.\n\nHarte Regeln:\n- **Keine Anforderung ohne Beleg.** Übernimm Fundstelle und Einstufung aus den gelieferten Fakten unverändert. Erfinde keine Belege und stufe nichts als `PRIMÄR` ein, was dir nicht als `PRIMÄR` geliefert wurde.\n- **Trenne `Fakt` und `Aussage` sauber.** `Fakt` ist die belegte Beobachtung, `Aussage` die fachliche Soll-Formulierung. Vermische beides nicht.\n- **Risikorelevante Anforderungen** (Sicherheit, Abrechnung, Berechtigungen) brauchen einen `PRIMÄR`-Beleg **oder** die Kennzeichnung `[HYPOTHESE]` in `Status`. Ein dritter Weg existiert nicht.\n- **Belege mehrfach, wo möglich.** Eine Anforderung, die von mehreren Stellen getragen wird, führt mehrere Belege. Ein einzelner Beleg ist zulässig, aber kein Ziel.\n- **Prüfidee ist Pflicht** und muss ein prüfbares Kriterium nennen, keine Absichtserklärung.\n\nAntworte ausschließlich mit den Anforderungsblöcken."
|
||||||
|
},
|
||||||
|
|
||||||
|
"syrs-autor": {
|
||||||
|
"description": "Formuliert System-Anforderungen (SyRS) im vorgegebenen Blockformat aus gelieferten Fakten. Arbeitet ausschließlich auf der Systemebene.",
|
||||||
|
"prompt": "Du formulierst **ausschließlich System-Anforderungen (SyRS)** nach ISO/IEC/IEEE 29148. Die Ebene ist deine Zuständigkeit und deine Grenze: Du schreibst keine Stakeholder- (StRS) und keine Software-Anforderungen (SwRS). Verweise stattdessen über Tracelinks.\n\nDie SyRS-Ebene beschreibt das **Systemverhalten**: beobachtbares Verhalten an den Systemgrenzen, Schnittstellen, Statusmaschinen, Validierungen, Performance- und Sicherheitsanforderungen. Sie beschreibt nicht die interne Codestruktur – das ist SwRS.\n\nDu erhältst Fakten mit Fundstelle und Belegeinstufung. Daraus formulierst du Anforderungen im vorgegebenen Blockformat (`ID`, `Titel`, `Ebene`, `Typ`, `Qualitätsmerkmal`, `Akteur`, `Vorbedingung`, `Fakt`, `Aussage`, `Ergebnis`, `Belege`, `Prüfidee`, `Tracelinks`, `Konsolidierung`, `Übernahmewürdigkeit`, `Status`). Das Format ist verbindlich; jedes Feld wird gefüllt.\n\nHarte Regeln:\n- **Keine Anforderung ohne Beleg.** Fundstelle und Einstufung werden unverändert übernommen; nichts wird zu `PRIMÄR` hochgestuft.\n- **Trenne `Fakt` und `Aussage` sauber.**\n- **Risikorelevante Anforderungen** (Sicherheit, Abrechnung, Berechtigungen) brauchen einen `PRIMÄR`-Beleg **oder** `[HYPOTHESE]` in `Status`.\n- **Nicht-funktionale Anforderungen** tragen das ISO-25010-Qualitätsmerkmal im Feld `Qualitätsmerkmal`, nicht im Feld `Typ`.\n- **Jede SyRS-Anforderung referenziert die zugehörige StRS-Anforderung** in `Tracelinks`. Existiert keine, benenne die fachliche Lücke ausdrücklich, statt den Link leer zu lassen.\n- **Prüfidee ist Pflicht** und muss ein prüfbares Kriterium nennen.\n\nAntworte ausschließlich mit den Anforderungsblöcken."
|
||||||
|
},
|
||||||
|
|
||||||
|
"swrs-autor": {
|
||||||
|
"description": "Formuliert Software-Anforderungen (SwRS) im vorgegebenen Blockformat aus gelieferten Fakten. Arbeitet ausschließlich auf der Softwareebene.",
|
||||||
|
"prompt": "Du formulierst **ausschließlich Software-Anforderungen (SwRS)** nach ISO/IEC/IEEE 29148. Die Ebene ist deine Zuständigkeit und deine Grenze: Du schreibst keine Stakeholder- (StRS) und keine System-Anforderungen (SyRS). Verweise stattdessen über Tracelinks.\n\nDie SwRS-Ebene beschreibt die **softwareinterne Sicht**: Komponenten, Datenmodelle, Persistenzregeln, interne Algorithmen und Berechnungsvorschriften, softwareinterne Constraints.\n\nDu erhältst Fakten mit Fundstelle und Belegeinstufung. Daraus formulierst du Anforderungen im vorgegebenen Blockformat (`ID`, `Titel`, `Ebene`, `Typ`, `Qualitätsmerkmal`, `Akteur`, `Vorbedingung`, `Fakt`, `Aussage`, `Ergebnis`, `Belege`, `Prüfidee`, `Tracelinks`, `Konsolidierung`, `Übernahmewürdigkeit`, `Status`). Das Format ist verbindlich; jedes Feld wird gefüllt.\n\nHarte Regeln:\n- **Keine Anforderung ohne Beleg.** Fundstelle und Einstufung werden unverändert übernommen.\n- **Trenne `Fakt` und `Aussage` sauber.**\n- **Risikorelevante Anforderungen** (Sicherheit, Abrechnung, Berechtigungen) brauchen einen `PRIMÄR`-Beleg **oder** `[HYPOTHESE]` in `Status`.\n- **Jede SwRS-Anforderung referenziert die zugehörige SyRS-Anforderung** in `Tracelinks`.\n- **Konsolidierungsprüfung:** Gemeint sind fachlich gleichartige Konzepte in getrennten Implementierungen – etwa zwei Datenhaltungen für denselben fachlichen Gegenstand. Zwei Anforderungen, die denselben Sachverhalt aus Sicht verschiedener Ebenen beschreiben, sind **kein** Konsolidierungsfall; dafür sind die Tracelinks da.\n- **Prüfidee ist Pflicht** und muss ein prüfbares Kriterium nennen.\n\nAntworte ausschließlich mit den Anforderungsblöcken."
|
||||||
|
},
|
||||||
|
|
||||||
|
"konsistenzpruefer": {
|
||||||
|
"description": "Prüft einen fertigen Anforderungssatz gegen die Vorgaben des Auftrags und meldet Verstöße. Formuliert und korrigiert selbst KEINE Anforderungen.",
|
||||||
|
"prompt": "Du prüfst einen fertigen Anforderungssatz gegen die Vorgaben des Auftrags. Du korrigierst nichts und formulierst nichts um – du meldest Verstöße mit Fundstelle, damit der Auftraggeber entscheidet.\n\nPrüfe vollständig und zähle absolut, nicht beispielhaft:\n\n1. **Belegpflicht:** Anforderungen ohne jeden Beleg. Liste jede betroffene ID.\n2. **Risikobasierte Priorisierung:** Anforderungen vom Typ Sicherheit, Abrechnung oder Berechtigungen, die weder einen `PRIMÄR`-Beleg noch die Kennzeichnung `[HYPOTHESE]` tragen. Liste jede betroffene ID. **Dies ist der Prüfpunkt, der in der Praxis am häufigsten verfehlt wird – geh ihn Anforderung für Anforderung durch, nicht überschlägig.**\n3. **Verifizierbarkeit:** Anforderungen ohne Prüfidee oder mit einer Prüfidee, die kein prüfbares Kriterium nennt.\n4. **Traceability:** Anforderungen ohne Tracelinks; Tracelinks, die auf nicht existierende IDs zeigen; SwRS ohne SyRS-Bezug; SyRS ohne StRS-Bezug.\n5. **Formtreue:** doppelte IDs; fehlende Pflichtfelder; nicht-funktionale Anforderungen ohne ISO-25010-Qualitätsmerkmal; Qualitätsmerkmale, die fälschlich im Feld `Typ` stehen.\n6. **Ebenentreue:** Anforderungen, deren Inhalt nicht zur angegebenen Ebene passt (etwa eine Codestruktur-Aussage auf StRS-Ebene), sowie Blöcke, die in der Datei einer anderen Ebene abgelegt sind.\n7. **Deckungsgleichheit:** Weicht die Sammeldatei der Hypothesen von den Inline-Kennzeichnungen ab?\n\nLiefere je Prüfpunkt: Anzahl der Verstöße, Gesamtzahl der geprüften Anforderungen, und die vollständige Liste der betroffenen IDs. Bei null Verstößen sage das ausdrücklich. Schätze nichts und kürze keine Liste mit „und weitere\" ab."
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,164 @@
|
|||||||
|
# Versuch 01 - Baseline (Prompt-only) - Iteration 02
|
||||||
|
|
||||||
|
## Metadaten
|
||||||
|
- **Versuch:** V1 Baseline (Prompt-only)
|
||||||
|
- **Iteration:** 02 (erste Überarbeitung nach Auswertung von Iteration 01)
|
||||||
|
- **Codebasis:** c-entron ERP-Suite (Windows, C#/XAML, MSSQL)
|
||||||
|
- **Zeitstempel:** 2026-08-26
|
||||||
|
- **Vorgänger:** `01_Prompt.md` (SHA-256 `1B0DB06B…3C02FF`), 24 Läufe an Tag 1
|
||||||
|
- **Änderungsgrund:** Auswertung der 24 Läufe von Tag 1 über 3.287 erzeugte Anforderungen. Jede Änderung ist an einen gemessenen Befund gekoppelt:
|
||||||
|
|
||||||
|
| Änderung | Auslösender Befund |
|
||||||
|
|---|---|
|
||||||
|
| Modulinventar als Pflicht-Vorstufe, Mindestabdeckung je Modul, Vertiefung erst danach | Anforderungszahl schwankte je Lauf zwischen 42 und 325 (Faktor 5,9); 55 bis 60 von rund 85 Modulen blieben unanalysiert; die Modultabellen der Analyseberichte reichten von 0 bis 51 Zeilen |
|
||||||
|
| Hypothesenpflicht kalibriert, `Hypothesen.md` deckungsgleich mit den Inline-Markierungen | Zwei Läufe meldeten null Hypothesen bei 71 bzw. 148 Anforderungen; der Anteil schwankte zwischen 0 % und 26,2 %; mehrfach wichen Sammeldatei und Inline-Markierungen voneinander ab |
|
||||||
|
| Primärbeleg muss die durchsetzende Stelle benennen | 45,9 % aller Anforderungen trugen genau einen Beleg; in einem Lauf waren 5 von 31 risikorelevanten Anforderungen weder mit `PRIMÄR` noch als `[HYPOTHESE]` gedeckt |
|
||||||
|
| Belegpflicht verschärft: ohne Beleg keine Anforderung | Eine Anforderung wurde ohne jeden Beleg geschrieben |
|
||||||
|
| Konsolidierungsbegriff an einem Beispiel kalibriert | Anteil der Konsolidierungskandidaten schwankte je Lauf zwischen 2,4 % und 35,2 % |
|
||||||
|
| Eigenes Feld `Qualitätsmerkmal` für die ISO-25010-Zuordnung | Die Zuordnung war gefordert, hatte aber keinen Ablageort: nur 33 von 313 nicht-funktionalen Anforderungen führten sie als eigene Angabe |
|
||||||
|
| Risikoanforderungen im Konsistenzcheck auflisten | Verstöße gegen die risikobasierte Priorisierung fielen erst in der nachgelagerten Auswertung auf, nicht im Lauf selbst |
|
||||||
|
|
||||||
|
Unverändert bleiben Prüfidee, Tracelinks, Belegklassifikation und das Blockformat: Prüfidee und Tracelinks waren in **allen** 3.287 Anforderungen gesetzt, 78,6 % der Belege waren `PRIMÄR`.
|
||||||
|
|
||||||
|
> Dieser Prompt enthält ausschließlich die **Analyseanweisung** und ist damit unabhängig von einem
|
||||||
|
> bestimmten Werkzeug oder Modell einsetzbar. Welche Werkzeuge im jeweiligen Lauf zur Verfügung
|
||||||
|
> stehen und wohin die Ergebnisse geschrieben werden, stellt der Versuchsaufbau beim Start bei.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prompt
|
||||||
|
|
||||||
|
Du bist ein Requirements Engineer im Reverse Requirements Engineering eines Legacy-ERP-Systems. Erzeuge aus der vorliegenden Codebasis eine Anforderungsspezifikation nach **ISO/IEC/IEEE 29148:2018**. Arbeite ausschließlich auf den im Arbeitsverzeichnis liegenden Artefakten (Quellcode, Konfiguration, UI-Ressourcen, ggf. DB-Skripte). Nutze nur Informationen, die du aus diesen Artefakten gewinnen kannst.
|
||||||
|
|
||||||
|
### Auftrag
|
||||||
|
|
||||||
|
Erzeuge eine konsolidierte Spezifikation auf den drei Ebenen:
|
||||||
|
|
||||||
|
1. **StRS** - Stakeholder Requirements Specification (fachliche Sicht, Akteure, Geschäftsziele)
|
||||||
|
2. **SyRS** - System Requirements Specification (Systemverhalten, Schnittstellen, Performance-, Sicherheitsanforderungen)
|
||||||
|
3. **SwRS** - Software Requirements Specification (Komponenten, Datenmodelle, Software-interne Regeln)
|
||||||
|
|
||||||
|
Ziel ist eine Spezifikation, die als belastbare Basis für eine Web-/SaaS-Neuimplementierung dienen kann.
|
||||||
|
|
||||||
|
### Scope (Schritt 1 der RRE-Methodenkette, manuell vorgegeben)
|
||||||
|
|
||||||
|
Der Untersuchungsgegenstand ist die **gesamte Codebasis** im Arbeitsverzeichnis. Es gilt bewusst keine Modulbeschränkung: Alle Module, Datenobjekte und Prozesse sind gleichrangig zu erfassen.
|
||||||
|
|
||||||
|
**Breite geht vor Tiefe.** Ein fehlendes Requirement führt bei einer Neuimplementierung zu Funktionsverlust; eine oberflächlich erfasste Funktion lässt sich dagegen nachschärfen. Erfasse deshalb zuerst die gesamte Breite und vertiefe erst danach. Halte dich an die Reihenfolge aus dem Abschnitt **Vorgehen**: erst Inventar, dann Mindestabdeckung, dann Vertiefung.
|
||||||
|
|
||||||
|
### Vorgehen (statische Analyse, keine Ausführung)
|
||||||
|
|
||||||
|
Bearbeite die Schritte 2-6 der RRE-Methodenkette (Schritt 1 Scope ist oben vorgegeben, Schritt 7 Validierung erfolgt manuell durch Fachexperten). Vorgeschaltet ist eine verbindliche Inventarisierung:
|
||||||
|
|
||||||
|
**Schritt 0 - Modulinventar (vor der ersten Anforderung).** Verschaffe dir zuerst einen vollständigen Überblick über den Untersuchungsgegenstand und lege ihn im `Analysebericht.md` als Tabelle ab: fachliches Modul beziehungsweise Komponente, Pfad im Arbeitsverzeichnis, ein Satz zur fachlichen Aufgabe. Das Inventar wird erstellt, **bevor** die erste Anforderung formuliert wird. Es ist die Bezugsgröße für die Abdeckung und darf später ergänzt, aber nicht gekürzt werden.
|
||||||
|
|
||||||
|
**Schritt 0b - Mindestabdeckung.** Jedes Modul des Inventars erhält **mindestens eine** Anforderung, bevor irgendein Modul vertieft wird. Lässt sich für ein Modul keine belegbare Anforderung bilden, führe es im Inventar als `nicht analysiert` mit einer kurzen Begründung. Ein Modul ohne Anforderung und ohne Begründung ist unzulässig.
|
||||||
|
|
||||||
|
**Schritt 0c - Vertiefung nach Risiko.** Erst wenn die Mindestabdeckung steht, vertiefe einzelne Module. Beginne dort, wo Sicherheitsregeln, Abrechnungs- und Fakturierungslogik oder Berechtigungsprüfungen liegen.
|
||||||
|
|
||||||
|
2. **Artefakterhebung:** Erfasse Quellcode, Konfiguration, UI-Texte, Datenbankschemata, Schnittstellenbeschreibungen sowie Change-Historie und Projektartefakte (Commit-Messages, Tickets, Release Notes, Migrationsnotizen), soweit als Datei lesbar.
|
||||||
|
3. **Technische Analyse:** Identifiziere Module, Komponenten, Abhängigkeiten, Statusmaschinen, Validierungslogik, Berechtigungsprüfungen.
|
||||||
|
4. **Semantische Interpretation:** Leite fachliche Aussagen aus technischen Implementierungen ab (z. B. Statusübergänge → Geschäftsregel).
|
||||||
|
5. **Formalisierung:** Überführe die Aussagen in klare, testbare Anforderungen mit Kontext, Vorbedingung und Ergebnis.
|
||||||
|
6. **Traceability-Anreicherung:** Verknüpfe jede Anforderung mit konkreten Artefaktbelegen.
|
||||||
|
|
||||||
|
### Pflicht-Eigenschaften jeder Anforderung
|
||||||
|
|
||||||
|
- **Belegpflicht:** Jede Anforderung **muss** mindestens einen konkreten Artefaktbeleg führen (Dateipfad, Klasse/Methode, SQL-Statement, UI-String, Konfigurationseintrag). Jeder Beleg erhält eine kurze Begründung, warum er die Aussage trägt. Lässt sich eine Aussage nicht belegen, **schreibe die Anforderung nicht** - erfasse den offenen Punkt stattdessen als Hypothese. Eine Anforderung ohne Beleg ist unter keinen Umständen zulässig.
|
||||||
|
- **Trennung von Fakt und Interpretation:** Die belegte technische Beobachtung (Feld `Fakt`) wird getrennt von der fachlichen Interpretation (Feld `Aussage`) dokumentiert, damit nachvollziehbar bleibt, was im Artefakt steht und was daraus geschlossen wurde.
|
||||||
|
- **Risikobasierte Priorisierung:** Anforderungen zu Sicherheitsregeln, Abrechnungs-/Fakturierungslogik und Berechtigungen unterliegen strengeren Evidenzanforderungen: Sie benötigen mindestens einen `PRIMÄR`-Beleg, andernfalls sind sie zwingend als `[HYPOTHESE]` zu kennzeichnen. Ein `PRIMÄR`-Beleg benennt hier die **durchsetzende Stelle** - Datei, Klasse, Methode und die konkrete Prüfung, Bedingung oder das Constraint. Ein Verweis auf eine Datei ohne Angabe der prüfenden Stelle genügt für diese Anforderungen nicht.
|
||||||
|
- **Belegklassifikation:** Kennzeichne jeden Beleg als
|
||||||
|
- `PRIMÄR` (durchgesetzte Regel im Code oder DB-Constraint),
|
||||||
|
- `SEKUNDÄR` (UI-Label, Fehlermeldung, Reportlayout, Mappingtabelle, Konfigurationsschalter),
|
||||||
|
- `KONTEXT` (Kommentar, Commit-Message, Ticketreferenz).
|
||||||
|
- **Hypothesenmarkierung:** Aussagen, die sich nicht eindeutig aus Artefakten ableiten lassen, kennzeichnest du explizit mit `[HYPOTHESE]` und einer kurzen Begründung, welche Information zur Bestätigung fehlt. Bei einer Codebasis dieser Größe ist eine Analyse ohne jeden offenen Punkt unplausibel: Führst du keine einzige Hypothese, begründe das ausdrücklich in der Selbstbewertung. Umgekehrt ist eine hohe Hypothesenzahl kein Mangel, sondern ein Hinweis auf ehrliche Abgrenzung.
|
||||||
|
- **Verifizierbarkeit:** Jede Anforderung enthält mindestens eine Prüfidee oder ein Akzeptanzkriterium.
|
||||||
|
- **Eindeutigkeit:** Vermeide vage Begriffe ("schnell", "benutzerfreundlich"); definiere domänenspezifische Begriffe beim ersten Auftreten.
|
||||||
|
- **Übernahmewürdigkeit:** Beurteile für jede Anforderung, ob ihre Funktion im Zielsystem erhalten bleiben soll. Unterscheide `übernehmen` (fachlich weiterhin erforderlich), `Workaround` (historisch gewachsene Behelfslösung), `Sonderfall` (Ausnahme für einen einzelnen Kunden, Mandanten oder Altbestand) und `veraltet` (durch neuere Logik abgelöst oder fachlich überholt). Begründe die Einstufung in einem Halbsatz. Diese Angabe steuert die spätere fachliche Priorisierung; eine Fehleinschätzung ist unkritisch, eine fehlende Angabe nicht.
|
||||||
|
- **Redundanzfreiheit:** Formuliere jede Anforderung so, dass sie von den übrigen klar abgegrenzt ist. Beschreiben zwei Anforderungen dieselbe fachliche Funktion aus unterschiedlicher Perspektive, führe sie zusammen oder grenze sie im Titel und in der Aussage ausdrücklich gegeneinander ab.
|
||||||
|
|
||||||
|
### Formatvorgabe pro Anforderung
|
||||||
|
|
||||||
|
```
|
||||||
|
ID: <StRS|SyRS|SwRS>-<laufende Nummer>
|
||||||
|
Titel: <kurzer Titel>
|
||||||
|
Ebene: <StRS | SyRS | SwRS>
|
||||||
|
Typ: <funktional | nicht-funktional | Schnittstelle | Daten | Sicherheit | ...>
|
||||||
|
Qualitätsmerkmal: <nur bei nicht-funktionalen Anforderungen: ISO-25010-Merkmal, sonst leer>
|
||||||
|
Akteur: <Rolle / System / Komponente>
|
||||||
|
Vorbedingung: <Zustand vor Auslösen>
|
||||||
|
Fakt: <belegte technische Beobachtung, z. B. Statusübergang, Constraint, Prüfung>
|
||||||
|
Aussage: Das System soll <...>. (fachliche Interpretation als klare Soll-Aussage)
|
||||||
|
Ergebnis: <erwartetes Ergebnis / Nachbedingung>
|
||||||
|
Belege:
|
||||||
|
- [PRIMÄR] <Pfad/Klasse/Methode/SQL/UI-String> - Begründung: <warum trägt der Beleg die Aussage>
|
||||||
|
- [SEKUNDÄR] <...> - Begründung: <...>
|
||||||
|
- [KONTEXT] <...> - Begründung: <...>
|
||||||
|
Prüfidee: <Akzeptanzkriterium oder Testidee>
|
||||||
|
Tracelinks: <verwandte StRS-/SyRS-/SwRS-IDs>
|
||||||
|
Konsolidierung: <nein | Kandidat: <IDs oder Stellen, die dieselbe fachliche Funktion abbilden>>
|
||||||
|
Übernahmewürdigkeit: <übernehmen | Workaround | Sonderfall | veraltet> - <kurze Begründung>
|
||||||
|
Status: <belegt | HYPOTHESE>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Traceability
|
||||||
|
|
||||||
|
Stelle Forward- und Backward-Traceability zwischen den drei Ebenen her:
|
||||||
|
- Jede SwRS-Anforderung referenziert die zugehörige SyRS-Anforderung.
|
||||||
|
- Jede SyRS-Anforderung referenziert die zugehörige StRS-Anforderung.
|
||||||
|
- Erzeuge zusätzlich eine konsolidierte **Traceability-Tabelle** (Markdown oder CSV): `StRS-ID | SyRS-ID | SwRS-ID | Artefaktbeleg`.
|
||||||
|
|
||||||
|
### Nicht-funktionale Anforderungen
|
||||||
|
|
||||||
|
- Ordne nicht-funktionale Anforderungen den Qualitätsmerkmalen der **ISO/IEC 25010** zu (z. B. Zuverlässigkeit, Performance-Effizienz, Sicherheit, Wartbarkeit, Übertragbarkeit). Trage die Zuordnung in das dafür vorgesehene Feld `Qualitätsmerkmal` ein, nicht in das Feld `Typ`.
|
||||||
|
- Leite Betriebs- und Sicherheitsanforderungen gezielt auch aus indirekt sichtbaren Artefakten ab: Konfigurationen, Deployment-Skripte, Logging-Policies, Rechteprüfungen.
|
||||||
|
|
||||||
|
### Konsolidierungsbedarf
|
||||||
|
|
||||||
|
Die Codebasis enthält fachliche Redundanz: Dieselbe Anforderung kann auf unterschiedlichen Masken oder in unterschiedlichen Modulen mehrfach und teils unterschiedlich implementiert sein. Prüfe daher bei jeder Anforderung, ob andere Anforderungen dieselbe fachliche Funktion abbilden, und vermerke solche Fälle im Feld `Konsolidierung` als Kandidat für eine Zusammenführung im Zielsystem.
|
||||||
|
|
||||||
|
**Gemeint sind fachlich gleichartige Konzepte in getrennten Implementierungen**, nicht bloß ähnlich formulierte Anforderungen. Ein Beispiel aus dieser Codebasis: Drucker werden als „Stammblätter" geführt, sonstige Hardware getrennt davon als „Assets" - zwei Datenhaltungen für denselben fachlichen Gegenstand, die im Zielsystem zu einem Asset-Konzept zusammengeführt werden sollen. Zwei Anforderungen, die denselben Sachverhalt nur aus Sicht verschiedener Ebenen beschreiben (etwa StRS und SwRS), sind **kein** Konsolidierungsfall - dafür sind die Tracelinks da.
|
||||||
|
|
||||||
|
### Ergebnisstruktur (im vorgegebenen Ausgabeverzeichnis)
|
||||||
|
|
||||||
|
```
|
||||||
|
Ergebnisse/
|
||||||
|
StRS.md
|
||||||
|
SyRS.md
|
||||||
|
SwRS.md
|
||||||
|
Traceability.md (oder Traceability.csv)
|
||||||
|
Hypothesen.md (Sammlung aller mit [HYPOTHESE] markierten Aussagen mit offener Frage)
|
||||||
|
Glossar.md (Domänenbegriffe, die in den Anforderungen verwendet werden)
|
||||||
|
Analysebericht.md (Modulinventar aus Schritt 0, Abdeckungstabelle, Konsistenzcheck,
|
||||||
|
Selbstbewertung, bekannte Lücken)
|
||||||
|
```
|
||||||
|
|
||||||
|
Das Ausgabeverzeichnis wird beim Start des Laufs beigestellt. Die analysierte Codebasis wird ausschließlich gelesen und nicht verändert.
|
||||||
|
|
||||||
|
### Randbedingungen
|
||||||
|
|
||||||
|
- **Keine Halluzinationen.** Wenn ein Artefakt nicht gelesen oder eine Aussage nicht belegt werden kann, ist das offen zu legen, nicht zu erfinden.
|
||||||
|
- **Keine Generierung von Code.** Es sollen ausschließlich Spezifikationsartefakte entstehen.
|
||||||
|
- **Keine Annahme über nicht beigestellte Hilfsmittel.** Arbeite mit dem, was dir in diesem Lauf zur Verfügung steht. Setze keine zusätzlichen Analysewerkzeuge, Datenbankzugriffe oder laufende Systeme voraus. Stehen für eine Aussage nur indirekte Belege zur Verfügung, ist sie als `[HYPOTHESE]` zu kennzeichnen.
|
||||||
|
- **Migrationsperspektive berücksichtigen.** Erkennbare Workarounds, Sonderfälle und überholte Logik gehören in das Feld `Übernahmewürdigkeit`, nicht in das Feld `Status`. `Status` beschreibt ausschließlich die Belegsituation (`belegt` oder `HYPOTHESE`), `Übernahmewürdigkeit` die fachliche Zukunft der Anforderung. Beide Angaben sind unabhängig voneinander: Eine gut belegte Anforderung kann ein Workaround sein, eine Hypothese kann übernahmewürdig sein.
|
||||||
|
- **Sprache:** Deutsch für Anforderungsaussagen, technische Bezeichner (Klassen, Methoden, Spalten) bleiben in ihrer Originalsprache.
|
||||||
|
|
||||||
|
### Abschluss
|
||||||
|
|
||||||
|
Führe vor Abgabe einen **Konsistenzcheck über das gesamte Anforderungs-Set** durch und dokumentiere das Ergebnis im `Analysebericht.md`:
|
||||||
|
- Doppelte oder mehrfach vergebene IDs
|
||||||
|
- Anforderungen ohne Beleg
|
||||||
|
- Anforderungen ohne Angabe zur `Übernahmewürdigkeit`
|
||||||
|
- Tracelinks auf nicht existierende IDs
|
||||||
|
- Inhaltlich deckungsgleiche Anforderungen, die nicht als Konsolidierungskandidat markiert sind
|
||||||
|
- **Liste aller risikorelevanten Anforderungen** (Sicherheit, Abrechnung/Fakturierung, Berechtigungen) mit ihrer Belegsituation: ID, Titel, ob ein `PRIMÄR`-Beleg vorliegt, andernfalls die `[HYPOTHESE]`-Kennzeichnung. Diese Liste macht Verstöße gegen die risikobasierte Priorisierung im Lauf selbst sichtbar.
|
||||||
|
- **Abgleich `Hypothesen.md` gegen die Inline-Markierungen:** Beide müssen dieselben Anforderungen nennen. `Hypothesen.md` enthält genau die Anforderungen mit `[HYPOTHESE]`-Markierung und keine zusätzlichen freien Fragen; offene Punkte ohne zugehörige Anforderung gehören in die Selbstbewertung.
|
||||||
|
|
||||||
|
Erstelle außerdem die **Abdeckungstabelle** auf Basis des Modulinventars aus Schritt 0: je Modul die Einstufung `tief | mittel | flach | nicht analysiert` und die Anzahl der daraus erzeugten Anforderungen. Jede Zeile des Inventars muss in der Abdeckungstabelle auftauchen.
|
||||||
|
|
||||||
|
Beende den Lauf mit einer kurzen Selbstbewertung im `Analysebericht.md`:
|
||||||
|
- Wie viele Module des Inventars wurden tief, mittel, flach beziehungsweise gar nicht analysiert? Nenne absolute Zahlen, nicht nur Beispiele.
|
||||||
|
- Wurde die Mindestabdeckung erreicht, also hat jedes Modul mindestens eine Anforderung? Falls nein: welche Module fehlen und warum?
|
||||||
|
- An welchen Stellen war der Beleg dünn (hoher Anteil `SEKUNDÄR`/`KONTEXT` oder `[HYPOTHESE]`)?
|
||||||
|
- Falls keine einzige Hypothese geführt wurde: Begründung, warum die Analyse ohne offene Punkte auskommt.
|
||||||
|
- Welche Erkenntnisse legen einen Nachschlag in einer Folge-Iteration nahe?
|
||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
# Messprotokoll – V1b-Fable (builtin, `claude-fable-5`, Effort `high`) – Iteration 01, Lauf 24 (Lauf R)
|
# Messprotokoll – V1b-Fable (builtin, `claude-fable-5`, Effort `high`) – Prompt-Version 01, Lauf 24 (Lauf R)
|
||||||
|
|
||||||
> ## ⚠ Bedingungsverletzung: Die Subagenten liefen auf einem anderen Modell
|
> ## ⚠ Bedingungsverletzung: Die Subagenten liefen auf einem anderen Modell
|
||||||
>
|
>
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
## Werkzeugkonfiguration
|
## Werkzeugkonfiguration
|
||||||
- **Laufverzeichnis-ID:** `v3.7.0-15db`
|
- **Laufverzeichnis-ID:** `v3.7.0-15db`
|
||||||
- **Ablage:** `claude-fable-5/builtin/high/`
|
- **Ablage:** `Iteration 1/claude-fable-5/builtin/high/`
|
||||||
- **Parallele Läufe:** nein
|
- **Parallele Läufe:** nein
|
||||||
- **Skill-Version:** `3.7.0` (erster Lauf mit Effort im Verzeichnisnamen)
|
- **Skill-Version:** `3.7.0` (erster Lauf mit Effort im Verzeichnisnamen)
|
||||||
- **Claude-Code-Version:** 2.1.245
|
- **Claude-Code-Version:** 2.1.245
|
||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
# Messprotokoll – V1-Fable (solo, `claude-fable-5`, Effort `max`) – Iteration 01, Lauf 22 (Lauf P)
|
# Messprotokoll – V1-Fable (solo, `claude-fable-5`, Effort `max`) – Prompt-Version 01, Lauf 22 (Lauf P)
|
||||||
|
|
||||||
> **Neue Messreihe mit zwei geänderten Variablen.** Gegenüber allen 21 Vorläufen wechseln
|
> **Neue Messreihe mit zwei geänderten Variablen.** Gegenüber allen 21 Vorläufen wechseln
|
||||||
> **gleichzeitig Modell und Effort**: `claude-fable-5` statt Sonnet/Opus, `max` statt `high`.
|
> **gleichzeitig Modell und Effort**: `claude-fable-5` statt Sonnet/Opus, `max` statt `high`.
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
## Werkzeugkonfiguration
|
## Werkzeugkonfiguration
|
||||||
- **Laufverzeichnis-ID:** `v3.6.0-7adf`
|
- **Laufverzeichnis-ID:** `v3.6.0-7adf`
|
||||||
- **Ablage:** `claude-fable-5/solo/max/`
|
- **Ablage:** `Iteration 1/claude-fable-5/solo/max/`
|
||||||
- **Parallele Läufe:** ja – `fable5_solo_v3.6.0-58d2`
|
- **Parallele Läufe:** ja – `fable5_solo_v3.6.0-58d2`
|
||||||
- **Skill-Version:** `3.6.0`
|
- **Skill-Version:** `3.6.0`
|
||||||
- **Claude-Code-Version:** 2.1.245
|
- **Claude-Code-Version:** 2.1.245
|
||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
# Messprotokoll – V1-Fable (solo, `claude-fable-5`, Effort `max`) – Iteration 01, Lauf 23 (Lauf Q)
|
# Messprotokoll – V1-Fable (solo, `claude-fable-5`, Effort `max`) – Prompt-Version 01, Lauf 23 (Lauf Q)
|
||||||
|
|
||||||
> **Neue Messreihe mit zwei geänderten Variablen.** Gegenüber allen 21 Vorläufen wechseln
|
> **Neue Messreihe mit zwei geänderten Variablen.** Gegenüber allen 21 Vorläufen wechseln
|
||||||
> **gleichzeitig Modell und Effort**: `claude-fable-5` statt Sonnet/Opus, `max` statt `high`.
|
> **gleichzeitig Modell und Effort**: `claude-fable-5` statt Sonnet/Opus, `max` statt `high`.
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
## Werkzeugkonfiguration
|
## Werkzeugkonfiguration
|
||||||
- **Laufverzeichnis-ID:** `v3.6.0-58d2`
|
- **Laufverzeichnis-ID:** `v3.6.0-58d2`
|
||||||
- **Ablage:** `claude-fable-5/solo/max/`
|
- **Ablage:** `Iteration 1/claude-fable-5/solo/max/`
|
||||||
- **Parallele Läufe:** ja – `fable5_solo_v3.6.0-7adf`
|
- **Parallele Läufe:** ja – `fable5_solo_v3.6.0-7adf`
|
||||||
- **Skill-Version:** `3.6.0`
|
- **Skill-Version:** `3.6.0`
|
||||||
- **Claude-Code-Version:** 2.1.245
|
- **Claude-Code-Version:** 2.1.245
|
||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
# Messprotokoll – V1-Opus (Baseline solo, `claude-opus-5`) – Iteration 01, Lauf 17 (Lauf K)
|
# Messprotokoll – V1-Opus (Baseline solo, `claude-opus-5`) – Prompt-Version 01, Lauf 17 (Lauf K)
|
||||||
|
|
||||||
> **Neue Messreihe.** Erster Block mit `claude-opus-5`; alle 16 Vorläufe nutzten
|
> **Neue Messreihe.** Erster Block mit `claude-opus-5`; alle 16 Vorläufe nutzten
|
||||||
> `claude-sonnet-5`. Modus, Effort, Prompt, Snapshot und Parallelitätsgrad sind identisch zur
|
> `claude-sonnet-5`. Modus, Effort, Prompt, Snapshot und Parallelitätsgrad sind identisch zur
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
## Werkzeugkonfiguration
|
## Werkzeugkonfiguration
|
||||||
- **Laufverzeichnis-ID:** `v3.6.0-2603`
|
- **Laufverzeichnis-ID:** `v3.6.0-2603`
|
||||||
- **Ablage:** `claude-opus-5/solo/high/`
|
- **Ablage:** `Iteration 1/claude-opus-5/solo/high/`
|
||||||
- **Parallele Läufe:** ja – die vier übrigen Läufe dieses Blocks (`opus5_solo_v3.6.0-6bfe`, `opus5_solo_v3.6.0-5070`, `opus5_solo_v3.6.0-26d8`, `opus5_solo_v3.6.0-f63e`)
|
- **Parallele Läufe:** ja – die vier übrigen Läufe dieses Blocks (`opus5_solo_v3.6.0-6bfe`, `opus5_solo_v3.6.0-5070`, `opus5_solo_v3.6.0-26d8`, `opus5_solo_v3.6.0-f63e`)
|
||||||
- **Skill-Version:** `3.6.0`
|
- **Skill-Version:** `3.6.0`
|
||||||
- **Claude-Code-Version:** 2.1.245
|
- **Claude-Code-Version:** 2.1.245
|
||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
# Messprotokoll – V1-Opus (Baseline solo, `claude-opus-5`) – Iteration 01, Lauf 18 (Lauf L)
|
# Messprotokoll – V1-Opus (Baseline solo, `claude-opus-5`) – Prompt-Version 01, Lauf 18 (Lauf L)
|
||||||
|
|
||||||
> **Neue Messreihe.** Erster Block mit `claude-opus-5`; alle 16 Vorläufe nutzten
|
> **Neue Messreihe.** Erster Block mit `claude-opus-5`; alle 16 Vorläufe nutzten
|
||||||
> `claude-sonnet-5`. Modus, Effort, Prompt, Snapshot und Parallelitätsgrad sind identisch zur
|
> `claude-sonnet-5`. Modus, Effort, Prompt, Snapshot und Parallelitätsgrad sind identisch zur
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
## Werkzeugkonfiguration
|
## Werkzeugkonfiguration
|
||||||
- **Laufverzeichnis-ID:** `v3.6.0-6bfe`
|
- **Laufverzeichnis-ID:** `v3.6.0-6bfe`
|
||||||
- **Ablage:** `claude-opus-5/solo/high/`
|
- **Ablage:** `Iteration 1/claude-opus-5/solo/high/`
|
||||||
- **Parallele Läufe:** ja – die vier übrigen Läufe dieses Blocks (`opus5_solo_v3.6.0-2603`, `opus5_solo_v3.6.0-5070`, `opus5_solo_v3.6.0-26d8`, `opus5_solo_v3.6.0-f63e`)
|
- **Parallele Läufe:** ja – die vier übrigen Läufe dieses Blocks (`opus5_solo_v3.6.0-2603`, `opus5_solo_v3.6.0-5070`, `opus5_solo_v3.6.0-26d8`, `opus5_solo_v3.6.0-f63e`)
|
||||||
- **Skill-Version:** `3.6.0`
|
- **Skill-Version:** `3.6.0`
|
||||||
- **Claude-Code-Version:** 2.1.245
|
- **Claude-Code-Version:** 2.1.245
|
||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
# Messprotokoll – V1-Opus (Baseline solo, `claude-opus-5`) – Iteration 01, Lauf 19 (Lauf M)
|
# Messprotokoll – V1-Opus (Baseline solo, `claude-opus-5`) – Prompt-Version 01, Lauf 19 (Lauf M)
|
||||||
|
|
||||||
> **Neue Messreihe.** Erster Block mit `claude-opus-5`; alle 16 Vorläufe nutzten
|
> **Neue Messreihe.** Erster Block mit `claude-opus-5`; alle 16 Vorläufe nutzten
|
||||||
> `claude-sonnet-5`. Modus, Effort, Prompt, Snapshot und Parallelitätsgrad sind identisch zur
|
> `claude-sonnet-5`. Modus, Effort, Prompt, Snapshot und Parallelitätsgrad sind identisch zur
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
## Werkzeugkonfiguration
|
## Werkzeugkonfiguration
|
||||||
- **Laufverzeichnis-ID:** `v3.6.0-5070`
|
- **Laufverzeichnis-ID:** `v3.6.0-5070`
|
||||||
- **Ablage:** `claude-opus-5/solo/high/`
|
- **Ablage:** `Iteration 1/claude-opus-5/solo/high/`
|
||||||
- **Parallele Läufe:** ja – die vier übrigen Läufe dieses Blocks (`opus5_solo_v3.6.0-2603`, `opus5_solo_v3.6.0-6bfe`, `opus5_solo_v3.6.0-26d8`, `opus5_solo_v3.6.0-f63e`)
|
- **Parallele Läufe:** ja – die vier übrigen Läufe dieses Blocks (`opus5_solo_v3.6.0-2603`, `opus5_solo_v3.6.0-6bfe`, `opus5_solo_v3.6.0-26d8`, `opus5_solo_v3.6.0-f63e`)
|
||||||
- **Skill-Version:** `3.6.0`
|
- **Skill-Version:** `3.6.0`
|
||||||
- **Claude-Code-Version:** 2.1.245
|
- **Claude-Code-Version:** 2.1.245
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user