diff --git a/runner-agents.md b/runner-agents.md new file mode 100644 index 0000000..86f7a19 --- /dev/null +++ b/runner-agents.md @@ -0,0 +1,181 @@ +# 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-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`. + +## Output-Parsing (Listing + Summary) + +Genau eine der folgenden Varianten muss 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). + +## 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 / 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 = , col = , 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 = "..." }` + +## 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.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 oder output_parser implementiert +- parse_test_output implementiert +- collect_failed_locations implementiert +- command_spec `{ cmd, cwd }` korrekt zurückgegeben + +## Projekt- und Prozessanforderungen + +- Eine englischsprachige `README.md` ist zu erstellen. + - Sie muss bei jedem weiteren Prompt aktualisiert werden, wenn die Aenderungen es erfordern. +- 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` darf im Runner-Repo angelegt werden. +- Eine Gitea-Action ist zu erstellen, die bei jedem Push die Tests ausfuehrt. + - Beispiel (anpassbarer Workflow): + +```yaml +name: tests + +on: + push: + branches: + - "**" + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Run tests + run: bash run_test.sh +```