diff --git a/STATUS.md b/STATUS.md index 0fab378..efbd19b 100644 --- a/STATUS.md +++ b/STATUS.md @@ -119,8 +119,10 @@ _none active_ | [0022](docs/adr/0022-upstream-anschluss-durch-einmaligen-merge.md) | accepted | ADR-0022: Anschluss an Upstream durch einen einmaligen Merge, nicht durch einen geteilten Graft | | [0023](docs/adr/0023-fremdhistorie-von-der-git-hygiene-ausnehmen.md) | accepted | ADR-0023: Fremde Historie von der Git-Hygiene ausnehmen — erklärt, nicht global | -## Open AARs (4) +## Open AARs (6) +- [AAR — Alle geplanten Prüfungen waren dauerhaft rot und meldeten damit nichts mehr](docs/aar/2026-08-18-alle-pruefungen-dauerhaft-rot.md) +- [AAR — Nach der Freischaltung sendete Safari ungefiltert weiter](docs/aar/2026-08-18-safari-sendete-ungefiltert.md) - [AAR — `v0.6.0-rc.2` brach die Raumliste in Produktion](docs/aar/2026-08-19-rc2-raumliste-produktion.md) - [AAR — Drei DKIM-Einträge verschwanden bei der DMARC-Härtung](docs/aar/2026-08-20-dkim-verlust-zonenaenderung.md) - [AAR — Game-Host-Anbindung: Deploy über zwei Übergaben, Ursache war nie die Firewall](docs/aar/2026-08-20-game-host-anbindung.md) diff --git a/docs/aar/2026-08-18-alle-pruefungen-dauerhaft-rot.md b/docs/aar/2026-08-18-alle-pruefungen-dauerhaft-rot.md new file mode 100644 index 0000000..dfc4415 --- /dev/null +++ b/docs/aar/2026-08-18-alle-pruefungen-dauerhaft-rot.md @@ -0,0 +1,71 @@ +--- +type: aar +status: open +date: 2026-08-18 +related: + - "docs/issues/0104-daueralarme-melden-nichts-mehr.md" + - "docs/adr/0020-bekannte-befunde-quittieren.md" +--- + +# AAR — Alle geplanten Prüfungen waren dauerhaft rot und meldeten damit nichts mehr + +*Nachträglich erstellt am 2026-08-20.* + +## 1. Was geplant war + +Die Prüfungen der Stillstandsprüfungs-Familie (`gruppenpruefung`, `stillstandspruefung`, +`pruefe_upstream_drift`) sollen die Pipeline rot färben, wenn etwas nicht stimmt. AGENTS.md +sagt dazu ausdrücklich: **die rote Pipeline ist die Alarmanlage.** + +## 2. Was geschah + +Aufgefallen am 2026-08-18 bei der Frage nach der Produktionsreife: **Jede** geplante +Prüfung war rot, und zwar dauerhaft — 25 offene Befunde, viele davon seit Tagen bekannt, +keiner davon neu. Damit meldete keine Prüfung mehr etwas: Rot war der Normalzustand. + +Zwei Ursachen kamen zusammen. Erstens echte, aber bekannte und teils bewusst +zurückgestellte Befunde ohne Mechanismus, sie als solche zu kennzeichnen. Zweitens ein +strukturelles Problem: `gitops` hatte **keinen `workflow`-Block** und legte deshalb auch +dann Pipelines an, wenn kein Job auf sie passte — rot ohne jeden Fehler. + +## 3. Warum der Unterschied + +**Spec issue.** Die Prüfungen kannten nur zwei Zustände: Befund oder kein Befund. Ein +dritter fehlte — „bekannt, bewertet, bewusst zurückgestellt". Ohne ihn wächst jede +Alarmanlage in die Dauer-Rotheit hinein, und zwar unabhängig davon, wie gut die einzelnen +Prüfungen sind. + +Die Abstumpfung ist dabei nicht das Nebenprodukt, sondern der eigentliche Schaden: Wer sich +an rote Pipelines gewöhnt, übersieht die eine, die zählt. + +## 4. Lehren + +- **Eine Alarmanlage ohne Quittungsmechanismus verfällt.** Nicht weil die Prüfungen + schlecht sind, sondern weil bekannte Befunde sich ansammeln. +- **Quittungen brauchen eine Frist.** Ohne Ablaufdatum wird aus „bewusst zurückgestellt" + stillschweigend „vergessen". Deshalb ist die Frist in `quittungen.py` Pflicht und + „permanent" nur als ADR zulässig. +- **Rot ohne Fehler ist schlimmer als kein Alarm.** Eine Pipeline, die aus strukturellen + Gründen rot wird (leere Pipeline ohne Jobs), zerstört die Aussagekraft aller anderen. +- **Zuerst die Ursache, dann die Quittung.** Von den 25 Befunden wurden die meisten + behoben; genau **einer** wurde quittiert, weil er sich nicht beheben ließ. + +## 5. Maßnahmen + +| Maßnahme | Stand | +|---|---| +| Quittungsmechanismus mit Pflichtfrist (`quittungen.py`, ADR-0020) | erledigt | +| `workflow`-Block in `gitops` und vorbeugend in `management` | erledigt | +| 25 offene Befunde auf 0, davon 26 quittiert mit Grund und Frist | erledigt | +| #0104 als führendes Issue für das Muster angelegt und geschlossen | erledigt | + +## 6. Offen + +- Die Quittungen laufen ab. Läuft eine aus, ohne dass jemand hinsieht, ist der + Ausgangszustand zurück — die Prüfung meldet das dann selbst, aber nur, wenn jemand die + Meldung liest. +- ⚠️ Am 2026-08-20 kam eine neue Dauer-Rotheit derselben Klasse hinzu: Der Upstream-Merge + brachte 70.265 fremde Commits, die die Git-Hygiene-Prüfung bemängelte, ohne dass sie sich + je ändern ließen. Behoben über ADR-0023 — **zwei Tage nach diesem AAR-Anlass, dieselbe + Klasse.** Das spricht dafür, bei jeder neuen Prüfung im Voraus zu fragen, welche Befunde + sie erzeugen wird, die niemand beheben kann. diff --git a/docs/aar/2026-08-18-safari-sendete-ungefiltert.md b/docs/aar/2026-08-18-safari-sendete-ungefiltert.md new file mode 100644 index 0000000..68cf972 --- /dev/null +++ b/docs/aar/2026-08-18-safari-sendete-ungefiltert.md @@ -0,0 +1,75 @@ +--- +type: aar +status: open +date: 2026-08-18 +related: + - "docs/issues/0054-ki-geraeuschunterdrueckung-element-call.md" + - "docs/adr/0018-ki-geraeuschunterdrueckung-clientseitig-opt-in.md" +--- + +# AAR — Nach der Freischaltung sendete Safari ungefiltert weiter + +*Nachträglich erstellt am 2026-08-20. Der Vorfall war in #0054 ausführlich +dokumentiert, aber nie als AAR geerntet — obwohl er die Lehre trägt, die diese +Sitzung danach mehrfach wiederholt hat.* + +## 1. Was geplant war + +Mit `v0.5.3` wurde die KI-Geräuschunterdrückung freigeschaltet (ADR-0018), nachdem der +Abnahmetest im Call zu zweit am 2026-08-17 bestanden war. Erwartet: Der Filter wirkt für +alle Nutzer, die ihn einschalten. + +## 2. Was geschah + +sorb meldete: **Filter wirkungslos, Stärke 0–100 ohne jeden Unterschied**, sauberer +Alleintest. Auf Rechnern der Chromium-Familie funktionierte derselbe Stand. + +Ein lokaler Prüfstand (Playwright, echter LiveKit-`setProcessor`-Pfad, Sprachsignal mit +Klick-Transienten) zeigte: **Prozessor und Modell arbeiten korrekt** — Sprache passiert, +Klicks verschwinden. Der Fehler lag dahinter. + +**Ursache:** LiveKits `setProcessor` tauscht den Sender-Track per +`this.sender?.replaceTrack(processedTrack)`. Ist der Sender in diesem Moment nicht am +Track — Safari-Timing beim `LocalTrackPublished`-Ereignis —, wird der Tausch **stumm +übersprungen**. Der Prozessor lädt seine 23 MB Modell, meldet Erfolg, und **das rohe +Mikrofon bleibt auf der Leitung**. + +Behoben in `v0.5.4` (threadnet-call `fee9866`): Der Fork prüft und erzwingt den Tausch, +die Konsole weist den Sendepfad aus. + +## 3. Warum der Unterschied + +**Code issue in Fremdcode, aber die Fehlerklasse ist unsere.** Das `?.` verschluckt den +Fehlschlag; eine Kette, die nichts tut, ist von einer erfolgreichen nicht zu +unterscheiden. + +Die Abnahme davor war nicht falsch, aber unvollständig: Sie prüfte **hörbar besser?** in +einem Chromium-Call. Sie prüfte nicht, **welcher Track tatsächlich gesendet wird**. Genau +dieser Unterschied trennt „meldet Erfolg" von „wirkt". + +⚠️ Datenschutzbezug: Wer den Filter einschaltete, durfte annehmen, dass sein rohes Mikrofon +nicht mehr übertragen wird. Es wurde übertragen. + +## 4. Lehren + +- **`?.` und stille Fehlschläge sind dasselbe Problem.** Wo eine Bibliothek einen Schritt + optional überspringt, muss der Aufrufer nachsehen, ob er stattgefunden hat. +- **Eine Abnahme muss die Wirkung messen, nicht die Absicht.** „Klingt besser" im falschen + Browser ist kein Beleg für „der gefilterte Track geht raus". +- **Browserübergreifend prüfen.** Der frühe Freispruch dieses Verdachts kam aus einem + Chromium-Test — ein browserübergreifender Fehlschluss, im Issue ausdrücklich vermerkt. +- Das Issue nennt diesen Vorfall das **„vierte Vorkommen des Sitzungsmusters *meldet + Erfolg, ist aber blind*"**. Vier erkannte Vorkommen — und trotzdem nirgends als + eigenständige Lehre abgelegt. Siehe Maßnahmen. + +## 5. Maßnahmen + +| Maßnahme | Stand | +|---|---| +| Sender-Verifikation im Fork, `v0.5.4` ausgerollt | erledigt (2026-08-17) | +| Abnahme im Call zu zweit auf Safari | erledigt | +| Muster als Wiki-Seite abgelegt statt nur im Issue erwähnt | erledigt (`docs/wiki/stolpersteine/meldet-erfolg-ist-aber-blind.md`) | + +## 6. Offen + +- Ob weitere `?.`-Stellen in den Fork-Patches denselben stillen Pfad haben, ist ungeprüft. diff --git a/docs/wiki/index.md b/docs/wiki/index.md index 4aa78b4..555f1f5 100644 --- a/docs/wiki/index.md +++ b/docs/wiki/index.md @@ -21,7 +21,7 @@ mit Inhalt. Projektfassung des neckbeard-Index (Original: | `vision/` | Eine Datei je Linie: [axion1337.chat](vision/axion1337-chat.md) · [Homelab](vision/homelab.md) · [ThreadNet](vision/threadnet.md) | belegt | | `user-guide/` | Für Nicht-Owner | entfällt — Gate 0: Publikum ist Owner + Sessions | | `requirements/` | Eigenständige Anforderungssicht | nur bei echtem Bedarf | -| `faq/`, `stolpersteine/` | Nur aus AARs und geschlossenen Issues geerntet — nie auf Vorrat: [neckbeard-migration](stolpersteine/neckbeard-migration.md), [wikijs](stolpersteine/wikijs.md) | wächst im Refinement | +| `faq/`, `stolpersteine/` | Nur aus AARs und geschlossenen Issues geerntet — nie auf Vorrat: [neckbeard-migration](stolpersteine/neckbeard-migration.md), [wikijs](stolpersteine/wikijs.md), [meldet Erfolg, ist aber blind](stolpersteine/meldet-erfolg-ist-aber-blind.md) | wächst im Refinement | ## Seitenregeln diff --git a/docs/wiki/stolpersteine/meldet-erfolg-ist-aber-blind.md b/docs/wiki/stolpersteine/meldet-erfolg-ist-aber-blind.md new file mode 100644 index 0000000..0954e1a --- /dev/null +++ b/docs/wiki/stolpersteine/meldet-erfolg-ist-aber-blind.md @@ -0,0 +1,58 @@ +--- +type: wiki-page +area: stolpersteine +sources: + - "docs/aar/2026-08-18-safari-sendete-ungefiltert.md" + - "docs/aar/2026-08-19-rc2-raumliste-produktion.md" + - "docs/aar/2026-08-20-dkim-verlust-zonenaenderung.md" +related: [] +--- + +# „Meldet Erfolg, ist aber blind" — die häufigste Fehlerklasse dieses Projekts + +Ein Schritt läuft durch, meldet Erfolg und hat nichts getan. Der Unterschied zwischen +„funktioniert" und „hat gar nicht erst geprüft" ist von außen **nicht sichtbar** — und +genau deshalb fällt diese Klasse erst auf, wenn jemand das Ergebnis anzweifelt. + +Sie ist in diesem Projekt bisher **mindestens siebenmal** aufgetreten, in fünf +verschiedenen Werkzeugen. Deshalb steht sie hier und nicht in einzelnen Issues. + +## Die belegten Vorkommen + +| Wo | Was meldete Erfolg | Was tatsächlich geschah | +|---|---|---| +| LiveKit `setProcessor` | Prozessor geladen, 23 MB Modell aktiv | `sender?.replaceTrack` übersprang den Tausch stumm — das rohe Mikrofon blieb auf der Leitung | +| Docker-Einzeldatei-Mounts | `docker compose restart` meldet Running | Container hielt den alten Inode und fuhr alten Code | +| `git merge` gegen einen flachen Tag | „0 Konflikte" | Der Merge war nie gelaufen (`refusing to merge unrelated histories`) | +| `grep "error TS"` gegen nx-Ausgabe | keine Fehler gefunden | Farbcodes zwischen `error` und `TS` — das Muster konnte nie greifen | +| `if git … \| tail -3` | „ok" nach jeder Etappe | Geprüft wurde der Rückgabewert von `tail`, nicht der von `git` | +| `/dev/tcp` in einem dash-Container | Verbindung fehlgeschlagen | `/dev/tcp` ist eine bash-Eigenheit — meldet dort *immer* Fehlschlag | +| `dig @` im Lab | vier übereinstimmende Antworten | Port 53 wird abgefangen; alle vier kamen vom lokalen Resolver | + +## Woran man sie erkennt + +- Ein Ergebnis, das **zu schnell** kommt (0 Konflikte, 0 Fehler, „ok in 0s"). +- Ein Ergebnis, das **immer gleich** ist, egal was man ändert. +- Eine Prüfung, die **nie** rot war, seit sie existiert. +- Eine Kette aus mehreren Werkzeugen, bei der nur das letzte seinen Zustand meldet. + +## Was dagegen hilft + +**Die Positivkontrolle ist Pflicht, nicht Kür.** Wer eine Prüfung baut, muss sie einmal +absichtlich brechen und sehen, dass sie es merkt. Ein Tor, das nur grün war, ist kein +Beleg — es ist eine Vermutung. + +**Die Gegenprobe gehört an den Anfang, nicht ans Ende.** `pruefe-dns.sh` prüft heute +zuerst, ob Port 53 abgefangen wird, und warnt **vor** seinen Messungen. `pruefe-ports.sh` +misst gegen einen bekannt offenen Port, bevor es „geschlossen" meldet. + +**Am selben Ort und zur selben Zeit messen wie die Arbeit.** Ein `nc`-Test aus einem +anderen Pod lief zufällig nach der NetworkPolicy-Programmierung und sah sauber aus, +während der eigentliche Job scheiterte. + +**Bei Ketten jedes Glied einzeln prüfen.** `set -o pipefail`, `PIPESTATUS`, oder gar nicht +erst durch eine Pipe leiten, wenn der Rückgabewert zählt. + +**Erfolg ohne auswertbare Ausgabe ist ein Fehler.** Der `typecheck`-Job scheitert +ausdrücklich, wenn `tsc` gar nichts geliefert hat — sonst wäre die leere Ausgabe der +bequemste Weg zu grün.