- Rust 100%
node test_widget.js prints its check count; the gate had no regex, so the number never appeared and a shrinking suite would have gone unnoticed. |
||
|---|---|---|
| src | ||
| tests | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| README.md | ||
run-gates (Rust)
Rust-Port von ~/coding/scripts/run-gates.py (172 Zeilen). Führt die Test-/Lint-Gates aller
Projekte unter ~/coding/projects aus und druckt eine Zeile pro Gate:
repo | gate | ok/FAIL/skip | dauer | testzahl
Die letzte Spalte ist die Testzahl, wie sie aus der Gate-Ausgabe kommt. Bei den
Go-Gates (go test ./...) zählt sie Pakete mit ok, nicht Testfunktionen
(SuperDaemon hat 201 Testfunktionen, aber 24 Pakete) — für „ist etwas kaputt"
reicht das, für „sind Tests verschwunden" nicht.
Exit 1, sobald ein Gate rot ist. Keine Farben, keine Emojis.
Warum
Das Skript läuft am Anfang jedes Agenten-Runs und prüft danach die ganze Matrix — beim Debuggen
auch einzeln pro Repo. Der Port startet in 0,7 ms statt 28 ms und hängt nicht am Interpreter.
Die Gate-Tabelle, die Statuslogik und beide Ausgabeformate sind unverändert, damit die Aufrufer
(Skill daily-coding-routine, Reports) dieselben Zeilen sehen.
Bauen und installieren
cargo build --release
install -m 755 target/release/run-gates ~/bin/run-gates
Benutzen
run-gates # alle Gates, Tabelle
run-gates --repo OakSeerr # nur ein Repo
run-gates --slow # inkl. DarkOaktyl test-integration (~7,5 min)
run-gates --json --repo sml # maschinenlesbar ({"gates": [...], "summary": {...}, "exit": N})
run-gates --timeout 60 # Timeout pro Gate (default 300 s)
run-gates --selfcheck # prueft die parse_count-Logik gegen sieben Beispiele
Pfade sind hartkodiert wie im Original (/home/pandi/coding/projects, /usr/bin/python3 als
PY für die pytest-Gates, ~/local/go/bin als PATH-Präfix für die Go-Gates).
Neue Projekte müssen in GATES in src/main.rs eingetragen werden (Rust: cargo test --offline --quiet, Python: /usr/bin/python3 -m pytest -q bzw. -m unittest <modul>,
expect als gemessene Untergrenze, danach cargo test gate_table und den Testnamen
gate_table_has_N_entries mitziehen) — sonst tauchen sie in keiner Gate-Runde auf.
Nie zwei Runden gleichzeitig starten: zwei next build kollidieren, ein gekillter Build
hinterlässt ein halbes .next und das folgende tsc fällt mit TS6053 aus. Das gilt für beide
Implementierungen (kein Portfehler, aber beim Paritäts-Vergleich aufgefallen).
Abweichungen
--selfcheck-Erwartungswerte korrigiert. Zwei der sieben Assertions im Original sind arithmetisch falsch und liessen--selfcheckschon am ersten Assert scheitern (Exit 1):24 + 153ergibt 177, nicht 178;"Tests 76 passed (76)"ergibt 76, nicht 79. Die Zaehllogik ist unverändert portiert, nur diese beiden Zielwerte stehen jetzt auf dem, was sie tatsächlich liefert. Alles andere (Regexe, Tabelle, Statuslogik, Ausgabe) ist 1:1.round(dur, 1)nutzt Rustsround()(halb weg von null) statt Pythons banker's rounding. Betrifft nur exakte x.x5-Grenzen der Dauer im JSON, nicht Status/Zähler/Ausgabe der Tabelle.- Detail-Tail: Python
str.splitlines()trennt zusätzlich an\r,\x0b,\x0c,\x1c–\x1e,\x85,U+2028/9; Rustlines()nur an\n(und\r\n). Die „letzten 15 nicht-leeren Zeilen" sind für normale Tool-Ausgaben identisch. --selfcheckim Fehlerfall: Meldung auf stderr + Exit 1 statt Python-Traceback mitAssertionError. Im Erfolgsfall identisch (selfcheck ok, Exit 0).--help: Text ist nachgebaut; argparse bricht dieusage:-Zeile zusätzlich nach Terminalbreite um, Rust nicht.- Abhängigkeiten:
regex(bereits innc-sortier-check-rsundollama-cloud-rsim Einsatz) undserde_jsonmitpreserve_order(gleiche Key-Reihenfolge wie Pythonsjson.dumps). Beides liegt im lokalen Cargo-Cache, Build läuft mit--offline.
Keine Verhaltensabweichung bei: Gate-Tabelle (alle Einträge, inkl. erwarteter Testzahlen,
Regexe, --slow-Flag, 900-s-Timeout für test-integration, GO_PATH), --repo-Filter,
Exitcodes (0/1, 2 bei unbekanntem Repo), Spaltenbreiten 26/17/4, >6.1fs-Dauer, Summary-Zeile,
--- Details (rote Gates) --- mit den letzten 15 nicht-leeren Zeilen, JSON-Struktur.
Tests
cargo test
tests::selfcheck_holds— die sieben--selfcheck-Assertionstests::parse_count_matches_original_strings—parse_countgegen die Original-Strings (Gruppen-Summe vs. Trefferzahl,Noneohne Regex/Match)tests::gate_table_has_45_entries— Tabellengröße (die Zahl steht im Testnamen und inassert_eq!; wer ein Gate ergänzt, zieht beides mit —cargo test gate_table)tests/parity::json_matches_python_for_sml— Rust-Binary vs./usr/bin/python3 coding/scripts/run-gates.py, beide--json --repo sml, JSON-Feldvergleich ohnedur, gleicher Exitcodetests/parity::unknown_repo_exits_two—--repo gibt-es-nicht→ Exit 2 + Meldung
Der Paritätstest überspringt sich selbst, wenn python3 oder das Original fehlt.
Gemessen (2026-10-30)
| Lauf | Rust | Python |
|---|---|---|
--repo sml (Skip-Gate, 20 Iterationen) |
0,7 ms | 27,9 ms |
--repo ipad-notizen-app (5 pytest-Tests) |
0,42–0,48 s | 0,45 s |
Der Repo-Lauf wird von pytest dominiert; der Unterschied ist reiner Start-Overhead.
Real-Lauf --repo OakSeerr --json (16 s): JSON ohne dur identisch zum Original.
Der Lauf am 30.10. meldete cargo-test mit erwartet 193, gefunden 195 (Sollwert war veraltet);
der Sollwert steht jetzt auf 195 (cargo test | grep '^test result' summiert 195 passed).
Die volle Runde nach dem Farbkontrast-Spec (39 neue Frontend-Tests) und den OakSeerr-Advisory-Fixes:
26 ok, 0 FAIL, 2 skip und frontend-test mit erwartet 134 — Matrix grün (Exit 0).
Real-Lauf ~/bin/run-gates (2026-11-05, ohne --slow): 42 ok, 0 FAIL, 2 skip, Exit 0, 68 s —
44 Gates laufen, test-integration fehlt ohne --slow (45 Einträge in der Tabelle). Neu in
dieser Runde: tts-kokoro (unittest, 35 Normalizer-Tests).
ollama-usage-monitor hat ein eigenes Gate, braucht aber ein Projekt-venv (die Pakete
fastapi/httpx fehlen im System-Python, python3 -m pytest bricht mit drei
Collection-Errors ab). Einmalig im Projekt:
uv venv --python 3.11 .venv
uv pip install -r requirements.txt pytest
Das Gate ruft dann .venv/bin/python -m pytest -q (27 Tests). Fehlt das venv, steht das
Gate rot da — das ist gewollt, ein stiller Skip wäre hier eine Lücke.