create runner with ChatGPT-Codex by using the AGENTS.md
Some checks failed
tests / test (push) Failing after 4s
Some checks failed
tests / test (push) Failing after 4s
This commit is contained in:
239
AGENTS.md
Normal file
239
AGENTS.md
Normal file
@@ -0,0 +1,239 @@
|
||||
# runner-agents.md — test-samurai Runner-API
|
||||
|
||||
Ziel: Diese Datei beschreibt die öffentliche Runner-API, die ein neuer Runner
|
||||
implementieren muss, damit alle Commands vollständig unterstützt werden.
|
||||
|
||||
## Modulform (Pflicht)
|
||||
|
||||
- Der Runner ist ein Lua-Modul, das eine Table mit Funktionen zurückgibt.
|
||||
- Beispiel:
|
||||
- `local runner = {}`
|
||||
- `return runner`
|
||||
- Der Modulpfad in `runner_modules` muss exakt zum Dateipfad unter `lua/` passen.
|
||||
- Beispiel: `lua/test-samurai-go-runner/init.lua` -> `require("test-samurai-go-runner")`.
|
||||
- `lua/init.lua` wäre `require("init")` und ist kollisionsanfällig; vermeiden.
|
||||
|
||||
## Pflichtfunktionen (volle Command- und Keymap-Unterstützung)
|
||||
|
||||
- `is_test_file(bufnr) -> boolean`
|
||||
- Wird für die Runner-Auswahl genutzt.
|
||||
- `find_nearest(bufnr, row, col) -> spec|nil, err?`
|
||||
- Für `TSamNearest`.
|
||||
- `spec.file` muss gesetzt sein.
|
||||
- Bei Fehler/kein Treffer: `nil, "reason"` zurückgeben.
|
||||
- `build_command(spec) -> command_spec`
|
||||
- Für `TSamNearest`.
|
||||
- `build_file_command(bufnr) -> command_spec`
|
||||
- Für `TSamFile`.
|
||||
- `build_all_command(bufnr) -> command_spec`
|
||||
- Für `TSamAll`.
|
||||
- `build_failed_command(last_command, failures, scope_kind) -> command_spec`
|
||||
- Für `TSamFailedOnly`.
|
||||
- `parse_results(output) -> results`
|
||||
- Fallback-Parser für vollständigen Output.
|
||||
- `output_parser() -> { on_line, on_complete }`
|
||||
- Muss Streaming unterstützen (Listing wird live befüllt).
|
||||
- `parse_test_output(output) -> table`
|
||||
- Detail-Ausgabe pro Test (Detail-Float und `<cr>` im Listing).
|
||||
- `collect_failed_locations(failures, command, scope_kind) -> items`
|
||||
- Quickfix-Unterstützung (Keymap `<leader>qn`).
|
||||
|
||||
## Output-Parsing (Listing + Summary)
|
||||
|
||||
Beide Varianten müssen vorhanden sein:
|
||||
|
||||
- `parse_results(output) -> results`
|
||||
- `results` muss enthalten:
|
||||
- `passes` (Array von Namen)
|
||||
- `failures` (Array von Namen)
|
||||
- `skips` (Array von Namen)
|
||||
- Optional:
|
||||
- `display = { passes = {}, failures = {}, skips = {} }`
|
||||
- `failures_all` (für Streaming-Parser, um alle bisherigen Failures zu liefern)
|
||||
- Wenn `display` fehlt, werden `passes/failures/skips` direkt im Listing angezeigt.
|
||||
- oder `output_parser() -> { on_line, on_complete }`
|
||||
- `on_line(line, state)` kann `results` liefern (siehe oben).
|
||||
- `on_complete(output, state)` kann `results` liefern (siehe oben).
|
||||
- `on_line` muss Ergebnisse liefern, damit das Listing-Float immer gestreamt wird.
|
||||
|
||||
Hinweis: `parse_results` darf intern `output_parser().on_complete` nutzen, aber beide Funktionen müssen existieren.
|
||||
|
||||
## Listing-Gruppierung fuer Parent/Subtests
|
||||
|
||||
- Wenn Testnamen das Format `Parent/Subtest` oder verschachtelt `Parent/Sub/Subtest` haben
|
||||
und der Parent ebenfalls in den Ergebnissen vorhanden ist, gruppiert das Listing:
|
||||
- Parent kommt vor seinen direkten Kindern.
|
||||
- Mehrstufige Subtests werden hierarchisch gruppiert (Parent -> Kind -> Enkel).
|
||||
- Die Reihenfolge der Kinder folgt der Eingangsreihenfolge des Runners.
|
||||
- Ohne Parent-Eintrag bleibt die normale Reihenfolge erhalten.
|
||||
|
||||
## Detail-Output (TSamShowOutput / <cr> im Listing)
|
||||
|
||||
- `parse_test_output(output) -> table`
|
||||
- Rückgabeform:
|
||||
- `{ [test_name] = { "line1", "line2", ... } }`
|
||||
- `test_name` muss mit `results.*` korrespondieren (gleiches Namensschema).
|
||||
|
||||
## Quickfix-Unterstützung (Failures)
|
||||
|
||||
- `collect_failed_locations(failures, command, scope_kind) -> items`
|
||||
- `items`: Array von Quickfix-Items
|
||||
- `{ filename = "...", lnum = <number>, col = <number>, text = "..." }`
|
||||
|
||||
## Erwartete Datenformen
|
||||
|
||||
- `command_spec`:
|
||||
- `{ cmd = { "binary", "arg1", ... }, cwd = "..." }`
|
||||
- `cmd` darf nicht leer sein.
|
||||
- `cwd` ist optional; wenn nicht gesetzt, nutzt der Core das aktuelle CWD.
|
||||
- `spec` (von `find_nearest`):
|
||||
- Muss mindestens `file` enthalten, z. B.:
|
||||
- `{ file = "...", cwd = "...", test_name = "...", full_name = "...", kind = "..." }`
|
||||
- `results` (für Listing-Float + Keymaps):
|
||||
- `{ passes = { "Name1", ... }, failures = { "Name2", ... }, skips = { "Name3", ... } }`
|
||||
- Optional: `display = { passes = { "DisplayName1", ... }, failures = { "DisplayName2", ... }, skips = { "DisplayName3", ... } }`
|
||||
- `failures` steuert `[ FAIL ]`-Zeilen im Listing und wird von `<leader>nf`/`<leader>pf` genutzt.
|
||||
- `items` (für Quickfix):
|
||||
- `{ { filename = "...", lnum = 1, col = 1, text = "..." }, ... }`
|
||||
- Wird von `<leader>qn` verwendet.
|
||||
|
||||
## Keymaps (Datenlieferung)
|
||||
|
||||
- `<leader>nf` / `<leader>pf`
|
||||
- benötigt `[ FAIL ]`-Einträge im Listing.
|
||||
- Runner muss `results.failures` (und optional `display.failures`) liefern.
|
||||
- `<leader>qn`
|
||||
- springt in die Quickfix-Liste.
|
||||
- Runner muss `collect_failed_locations` implementieren und gültige `items` liefern.
|
||||
- `<cr>` im Listing
|
||||
- öffnet Detail-Float.
|
||||
- Runner muss `parse_test_output` liefern und Testnamen konsistent zu `results.*` halten.
|
||||
|
||||
## Optional empfohlene Metadaten
|
||||
|
||||
- `name` (String)
|
||||
- Wird in Fehlermeldungen und Logs angezeigt.
|
||||
- `framework` (String)
|
||||
- Wird zur Framework-Auswahl (z. B. JS) genutzt.
|
||||
|
||||
## Prompt-Beispiel
|
||||
|
||||
"Erstelle mir anhand der `runner-agents.md` einen neuen Runner für Rust."
|
||||
|
||||
## Minimaler Runner-Skeleton (Template)
|
||||
|
||||
```lua
|
||||
local runner = {
|
||||
name = "my-runner",
|
||||
framework = "my-framework",
|
||||
}
|
||||
|
||||
function runner.is_test_file(bufnr)
|
||||
return false
|
||||
end
|
||||
|
||||
function runner.find_nearest(bufnr, row, col)
|
||||
return nil, "no test call found"
|
||||
end
|
||||
|
||||
function runner.build_command(spec)
|
||||
return { cmd = { "echo", "not-implemented" }, cwd = spec.cwd }
|
||||
end
|
||||
|
||||
function runner.build_file_command(bufnr)
|
||||
return { cmd = { "echo", "not-implemented" } }
|
||||
end
|
||||
|
||||
function runner.build_all_command(bufnr)
|
||||
return { cmd = { "echo", "not-implemented" } }
|
||||
end
|
||||
|
||||
function runner.build_failed_command(last_command, failures, scope_kind)
|
||||
return { cmd = { "echo", "not-implemented" }, cwd = last_command and last_command.cwd or nil }
|
||||
end
|
||||
|
||||
function runner.parse_results(output)
|
||||
return { passes = {}, failures = {}, skips = {}, display = { passes = {}, failures = {}, skips = {} } }
|
||||
end
|
||||
|
||||
function runner.output_parser()
|
||||
return {
|
||||
on_line = function(_line, _state)
|
||||
return nil
|
||||
end,
|
||||
on_complete = function(_output, _state)
|
||||
return runner.parse_results(_output)
|
||||
end,
|
||||
}
|
||||
end
|
||||
|
||||
function runner.parse_test_output(output)
|
||||
return {}
|
||||
end
|
||||
|
||||
function runner.collect_failed_locations(failures, command, scope_kind)
|
||||
return {}
|
||||
end
|
||||
|
||||
return runner
|
||||
```
|
||||
|
||||
## Checkliste für neue Runner
|
||||
|
||||
- is_test_file implementiert
|
||||
- find_nearest implementiert (setzt `spec.file`)
|
||||
- build_command implementiert
|
||||
- build_file_command implementiert
|
||||
- build_all_command implementiert
|
||||
- build_failed_command implementiert
|
||||
- parse_results implementiert
|
||||
- output_parser implementiert (Streaming)
|
||||
- parse_test_output implementiert
|
||||
- collect_failed_locations implementiert
|
||||
- command_spec `{ cmd, cwd }` korrekt zurückgegeben
|
||||
|
||||
## Projekt- und Prozessanforderungen
|
||||
|
||||
- Rolle: **TDD-first Entwickler**.
|
||||
- Jede neue Funktion, jedes neue Kommando und jede Verhaltensänderung muss durch Tests abgesichert sein.
|
||||
- Nach jeder Code-Änderung Tests via `bash run_test.sh` ausführen und bei Fehlern korrigieren, bis alles grün ist.
|
||||
- **Nicht raten**:
|
||||
- Bei unklaren oder mehrdeutigen Anforderungen Arbeit stoppen und Klarstellung verlangen.
|
||||
- TODO/NOTE im Code ist zulässig, stilles Raten nicht.
|
||||
- **Keine stillen Änderungen**:
|
||||
- Bestehende Features dürfen nicht unbemerkt geändert oder ersetzt werden.
|
||||
- Notwendige Anpassungen zur Koexistenz mehrerer Features müssen klar erkennbar sein.
|
||||
- Antworten immer auf Deutsch.
|
||||
- Eine englischsprachige `README.md` ist zu erstellen und wird bei Änderungen automatisch aktualisiert.
|
||||
- TDD-Vorgaben (aus `AGENTS.md`) uebernehmen:
|
||||
- Neue Funktionen/Commands/Verhaltensaenderungen muessen getestet werden.
|
||||
- Tests nach jeder Code-Aenderung ausfuehren.
|
||||
- Im Runner erstellter Quellcode ist ebenfalls zu testen.
|
||||
- Eine eigene `run_test.sh` wird im Runner-Repo angelegt.
|
||||
- Eine Gitea-Action ist zu erstellen, die bei jedem Push die Tests ausfuehrt.
|
||||
- Neovim wird per AppImage installiert (kein `apt`).
|
||||
- Runner laeuft auf `gitea-act-runner` mit Raspberry Pi 5 (ARM).
|
||||
- Beispiel (anpassbarer Workflow):
|
||||
|
||||
```yaml
|
||||
name: tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "**"
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Install Neovim (AppImage)
|
||||
run: |
|
||||
curl -L -o nvim.appimage https://github.com/neovim/neovim/releases/download/v0.11.4/nvim.appimage
|
||||
chmod +x nvim.appimage
|
||||
sudo mv nvim.appimage /usr/local/bin/nvim
|
||||
- name: Run tests
|
||||
run: bash run_test.sh
|
||||
```
|
||||
Reference in New Issue
Block a user