# 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 ```