Skip to content

feat(mla): A5 Lesender Monitor — /proc-Quellen, Ringpuffer, Drill-down (#96) - #119

Merged
Toqsick merged 23 commits into
mainfrom
feature/mla-96-monitor
Oct 19, 2026
Merged

Toqsick merged 23 commits into
mainfrom
feature/mla-96-monitor

Conversation

@Toqsick

@Toqsick Toqsick commented Oct 17, 2026 •

Copy link
Copy Markdown
Owner

A5 Lesender Monitor in der GTK-Shell (#96)

Schreibfreier Systemmonitor im GTK4-Prototyp: fünf Werte aus /proc, ein Ringpuffer fester Größe, Diagramme mit Einheit, Messzeit und Quelle, Drill-down in die rechte Detail-Leiste. Umgesetzt per SDD-Plan docs/superpowers/plans/2026-10-02-mla-96-monitor.md (Basis de0026d = main): 21 Commits, 20 Dateien, +2507/−29. Spec-Artefakt: docs/mla-next/MONITOR.md §1–§7. Handoff mit allen Belegen: Abschnitt „Handoff #96" in docs/mla-next/VERIFY.md.

Was drin ist

Bereich Inhalt
Werte (§1) CPU /proc/stat (Δbusy/Δtotal), RAM /proc/meminfo (MemAvailable), PSI CPU/Speicher/I/O some avg10; je Quelle, Formel, Einheit, Dezimalen, Toleranz (VALUE_SPECS)
Ringpuffer (§2) feste Kapazität, Überlauf verwirft den ältesten, strikte Zeitmonotonie (NaN immer abgelehnt, auch als Erstappend; ±inf geordnet), Kapazität nur int ≥ 1
Serien (§2) 60 × 3 s auf monotoner Uhr als Kettenraster (Errata E2/E3): Lücke nur bei echtem Abstand ≥ 1,5 Intervallen. Lücke = None → stale, nie 0
Sampler (§3) ein Lesevorgang je Wert und Tick, Lese-/Parsefehler werden je Wert zur Lücke mit Grund; kein Subprozess, kein Socket, kein Root
UI (§4) Cairo-Diagramm je Wert (Linienbruch an Lücken, Einzelwerte als Punkt, Farben nur aus Tokens), Caption Quelle · Einheit · Messzeit[ · stale: N], Drill-down nur per Primärklick, ein GLib-Zeitgeber mit Doppelstart-Guard und Abbestellung in do_shutdown
Tests (§6) 7 synthetische Fixtures, FakeReader/FakeClock; GTK-Suite 94 Tests (84 Modell + 10 Token), Hardcode-Gate über alle drei Shell-Dateien

Abnahme #96

  • Quelle und Einheit je Wert dokumentiert; jedes Diagramm zeigt Einheit, Messzeit und Quelle (MONITOR §1/§4, FormatterTests)
  • Ringpuffer-Tests für Überlauf, Zeitmonotonie und Lücken (Lücke = stale, nie 0)
  • Plausibilisierung gegen den /proc-Rohwert in dokumentierter Toleranz (CPU ±0,5 pp, RAM ±0,2 pp, PSI ±0,01)
  • Tests laufen gegen Fixtures, ohne echtes System (Audit-Hook-Lauf: 0 Zugriffe auf /proc, /sys, subprocess, socket)

Gates (Frischlauf auf e7e8145, nach den Final-Review-Fixes)

Gate Ausgabe
py_compile (mla_app, monitor_model, monitor_ui) Exit 0
GTK-Tests Ran 90 tests / OK
additional/python Ran 53 tests / OK
Flutter-Root Formatted 123 files (0 changed) · No issues found! · +208: All tests passed!
la_core Formatted 24 files (0 changed) · No issues found! · +68: All tests passed!
check-versions.sh version 0.8.0 is consistent
Start-Gates Wayland ×3 / X11 ×3 (timeout 6) je Exit 124, stdout/stderr 0 B

Nach dem Handoff-Commit 6f60352 lief die GTK-Suite erneut: 90 OK. Nach dem PR-Review-Fix 2391512 (Teillauf, kein Dart-Bezug): GTK Ran 94 tests / OK, additional/python 53 OK, check-versions.sh konsistent, Start-Gates Wayland ×3 / X11 ×3 je Exit 124 (1 von 6 mit dem bekannten Teardown-Flake). Nicht ausgeführt: build-deb.sh, das läuft in der CI dieses PRs.

Reviews

  • Je Task (T1–T4): R1 (Funktion/UX/Races) und R2 (Privilegien/Secrets/argv/IPC) parallel, Fix-Runden bis beide APPROVED.
  • Final-Whole-Branch-Review (de0026d..7f01b7b, Opus-Workflow mit 25 Agenten, adversarialen Refutern und Vollständigkeits-Kritiker): CHANGES_REQUESTED, 0 critical / 1 important / 8 minor.
    • Das Important S1: timeout_add_seconds(3) taktet genau mit der Slotbreite. Schon ~60 ms Main-Loop-Verspätung erzeugten eine falsche stale-Lücke; im echten GLib-Loop reproduziert.
    • Behoben in zwei Fix-Runden: Erratum E2 + 18a63df, dann E3 + e7e8145 (Kettenraster, Stall-Szenarien 0/400 falsche Lücken, vorher bis 400/400).
    • Beide Scoped-Re-Reviews APPROVED.
  • Copilot-PR-Review: NaN als erster Zeitstempel blockierte den Puffer dauerhaft; Brüche/bool/nan/inf als Kapazität liefen durch. Behoben über Erratum E4 8af55b6 + 2391512 (TDD, 4 neue Tests zuerst rot), adversarial geprüft (3 Opus-Linsen, je APPROVED, alle Mutanten getötet), Nachtrag in VERIFY.md (abba8f5, 7924d58).
  • Claim-Check der Handoff-Doku gegen Gate-Logs, git und Reports: 24 Korrekturen eingearbeitet.

Offen / bewusst nicht in diesem PR

Rückfallplan

git revert der #96-Commits (5a27740 … 7924d58, also bis zum Branch-Ende; im Wegwerf-Klon geprüft: Exit 0, Baum = de0026d). Das betrifft nur neue Dateien und kleine Änderungen in der GTK-Shell und Doku: kein Datenpfad, keine Unit, kein Packaging, keine Migration, polkit-Trinität unberührt.

Refs #96. Merge erst nach Review und Freigabe (kein Auto-Merge). #96 bleibt bis zur Abnahme offen.

🤖 Generated with Claude Code

Toqsick and others added 17 commits October 2, 2026 11:03
Plan im SDD-Format der Vorlagen #94/#95: 5 Tasks (Parser samt Fixtures
und Wertespec, Ringpuffer, Serien/Sampler, GTK-UI mit Drill-down,
Handoff), Controller-Entscheidungen D1-D9, Gate-Liste, Rueckfallplan.
Umsetzung lokal auf feature/mla-96-monitor; kein Push ohne Freigabe.

Co-Authored-By: Claude Code <noreply@anthropic.com>
)

Fünf /proc-Parser (stat, meminfo, pressure) mit ValueError bei fehlenden
Pflichtfeldern und der Wertespec VALUE_SPECS; dazu sieben synthetische
Fixtures flach in test/fixtures/ und die Spec docs/mla-next/MONITOR.md §1.

Co-Authored-By: Claude Code <noreply@anthropic.com>
100 × 7066996/16066996 = 43,98455… % (nicht „43,9841…"), Review-Fund R1 zu Task 1; Doku-Stellen folgen im Fix-Commit.

Co-Authored-By: Claude Code <noreply@anthropic.com>
…rt (#96)

Review-Auflagen R1: steal/guest-Kante als Mutationstest, source/formula
der fünf VALUE_SPECS exakt gepinnt und der RAM-Beispielwert auf
43,98455… in MONITOR.md/README korrigiert.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Ringpuffer (D3), Tests, MONITOR.md §2.

Co-Authored-By: Claude Code <noreply@anthropic.com>
F1: Guard auf `not ts > letzter ts` (weist NaN ab, Erster-Append unverändert);
F2: Kapazitätsmeldung mit %r statt %d; F3: rejected-Pin im Überlauf-Test plus
ts=0-Test; F4: NaN-Test. Mutationsbeleg für F1 im Fix-Report.

Co-Authored-By: Claude Code <noreply@anthropic.com>
- build_series: festes Raster (Länge exakt capacity, Slot floor(ts/interval),
  Raster endet bei floor(now/interval)), jüngster Eintrag je Slot gewinnt,
  leere Slots None (stale, nie 0.0), Einträge außerhalb des Fensters fallen
  weg; Rückgabe payload.value älteste→neueste.
- stale_count: Anzahl der None-Slots einer Serie.
- ValueSample(wall, value): Wanduhr für die Anzeige, value als Messwert.
- ProcReader(root='/proc').read: nur open+read, keine Subprozesse/Shell.
- Sampler(read, clock, interval=3.0, capacity=60): start/stop-frei; pro Wert
  eigenes try/except (OSError, ValueError) → Lücke in gaps (Format
  'Typ: relpath'), kein Crash; erster CPU-Tick bewusst Lücke (Delta-Basis
  fehlt), Vorprobe wird trotzdem gespeichert; Zugänge series/samples/latest/
  stale_count sowie interval/capacity (Andockpunkte Task 4).
- Rulings R-T3-1…R-T3-7 umgesetzt: Zeitbasen mono/wall, relpath aus
  VALUE_SPECS-Quelle, samples() fürs Drill-down, gaps-Sondertexte, Serien-
  Randfälle (Slot-Grenze, all-None vor dem ersten Tick), gi-freier Docstring,
  single-threaded ohne Lock (Doku MONITOR.md §3).
- MONITOR.md: §2 Serien-Regeln + N1-Korrektur (NaN abgelehnt, ±inf sind
  geordnete Werte), §3 Sampler- & Leseregeln ausformuliert.

Co-Authored-By: Claude Code <noreply@anthropic.com>
#96)

F1 (Doku-only, kein Verhalten): Der ±inf-Satz in MONITOR.md §2 und im
RingBuffer-Docstring wird exakt verhaltensgleich präzisiert — NaN wird
abgelehnt, +inf nimmt als größter Zeitstempel am normalen Vergleich teil,
-inf wird bei bestehendem Puffer abgelehnt (nur als erster Append
akzeptiert); Inline-Kommentar angeglichen.

F2 (Test-Pin): neuer Test test_meminfo_without_usable_total_is_a_named_value_gap
pinnt den Lücken-Text 'Wert ungueltig: meminfo' für parsebares meminfo mit
total 0 (meminfo_percent None) samt latest('ram_percent') is None und frischen
PSI-Werten. Pin bestehenden Verhaltens (grün im ersten Lauf); Mutationsbeleg:
'wert ungueltig'→'wert verfaelscht' lässt genau diesen Test rot laufen,
Rücknahme byte-identisch.

Co-Authored-By: Claude Code <noreply@anthropic.com>
…#96)

Monitor-Screen der GTK-Shell: je Wert eine Zeile aus Caption (Quelle,
Einheit, Messzeit, stale-Suffix) und Cairo-Diagramm (Grundlinie
border-subtle, Polyline accent, feste Y-Skala 0-100 %, Linienbruch an
None-Lücken); Klick auf eine Zeile öffnet das Drill-down (Kopf mit
Quelle/Formel/Toleranz/stale plus letzte 10 Proben, Monospace über die
farbfreie Klasse .mla-drilldown).

Der einzige Mess-Zeitgeber liegt in der Shell (GLib.timeout_add_seconds
mit Doppelstart-Guard, Abbestellung in do_shutdown); MonitorView bleibt
bewusst timerfrei. Die Anzeige-Formatierer (format_value /
format_caption / format_drilldown) sind gi-frei im Modell.
MODULES-Untertitel des Monitor-Eintrags exakt "60 × 3 s · /proc".

Tests: FormatterTests (8, exakte Strings, TZ=UTC) und Erweiterung des
Hardcode-Gates auf mla_app.py, monitor_ui.py und monitor_model.py
(RED-Belege im Task-4-Report). GTK-Suite 72 Tests, bestehende
additional/python-Suite 53 Tests, Start-Gates Wayland/X11 je Exit 124
ohne stderr.

Co-Authored-By: Claude Code <noreply@anthropic.com>
F1 (R1-Minor-1): GestureClick je Monitor-Zeile explizit auf
Gdk.BUTTON_PRIMARY gesetzt; MONITOR.md §4 auf Primärklick präzisiert.
Verhalten ansonsten unverändert; Touch/Tap meldet GTK4 als
Primärbutton und bleibt kompatibel.

Belege: py_compile Exit 0; GTK-Suite unverändert 72 Tests OK;
Start-Gates Wayland/X11 je Exit 124 mit leerem Log (1 von 4
gültigen Wayland-Läufen zeigte 116 B GLib-GIO-CRITICAL im
SIGTERM-Teardown, über 3 Wiederholungen nicht reproduzierbar);
Klick-Nachweis per xdotool auf frischer Instanz: Primärklick auf
RAM- und CPU-Diagramm öffnet das jeweilige Drill-down, Maustaste 3
und Maustaste 2 lassen die Detail-Leiste pixel-identisch (selbe
Sample-Zeit); Sonden-Matrix belegt Button-Zustellung unter Xwayland
(GTK-Default war bereits BUTTON_PRIMARY). Screenshots als
/tmp-Artefakte.

Important 1 (gequetschte Detail-Leiste) geparkt, keine Aktion.

Co-Authored-By: Claude Code <noreply@anthropic.com>
R1-N1: Der isolierte Import von `monitor_ui` warnte mit PyGIWarning, weil
`Gdk` ohne vorheriges `require_version` aufgelöst wurde (Gdk-3.0 und -4.0
beide installiert). Eine Zeile `gi.require_version('Gdk', '4.0')` im Guard
schreibt 4.0 fest; sonst nichts geändert.

RED-Beleg vor dem Fix (`cd prototype/gtk && python3 -c "import monitor_ui"`):
Exit 0, stderr (283 Bytes) enthält:
  monitor_ui.py:12: PyGIWarning: Gdk was imported without specifying a
  version first. Use gi.require_version('Gdk', '4.0') before import to
  ensure that the right version gets loaded.

Grün-Beleg nach dem Fix: dieselbe Probe Exit 0, stderr leer (0 Bytes).
py_compile Exit 0; GTK-Suite unverändert "Ran 72 OK"; Start-Gates Wayland
und X11 je Exit 124, stderr leer.

Co-Authored-By: Claude Code <noreply@anthropic.com>
…#96)

Fünf additive Pin-Tests in prototype/gtk/tests/test_monitor_model.py
(+78/−0, kein Produktionscode):

- RingBuffer: +inf wird gegenüber kleinerem Letzteintrag angenommen, ein
  zweites +inf abgelehnt; −inf nur als Erstappend zulässig (Docstring und
  MONITOR.md §2 waren bisher ungetestet).
- Sampler: stat-Lesefehler in Tick 1 legt keine Delta-Basis ab, Tick 2
  meldet erneut „Delta-Basis fehlt"; abgeschnittene stat-Datei wird zur
  Lücke „ValueError: stat"; interval/capacity aus dem Konstruktor fließen
  in Sampler.series.

Herkunft: uncommittet im Arbeitsbaum seit 2026-10-05 23:30 (Automations-
slot), bisher unreviewt; übernommen per Basti-Entscheid 2026-10-17.
Mutationsbelege (temporäre Worktree, Haupt-Checkout unberührt): jeder
Test fängt seinen gezielten Mutanten in monitor_model.py (Guard :226,
except :353, series :410), Rücknahmen byte-identisch; GTK-Suite 77/77.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
)

Das Final-Whole-Branch-Review (S1, important) hat eine Kollision von
absolutem Slotraster (D4, floor(ts/interval)) und D6-Zeitgeber
(timeout_add_seconds mit Slotbreite) belegt: ~60 ms Verspätung reichen
für eine falsche stale-Lücke. E2 verankert das Raster am letzten Tick
(k = floor((now − ts)/interval + 0.5)); D6 bleibt unverändert. Nur der
Plan wird angepasst (append-only), die Umsetzung folgt im Fix-Commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…Werte, Test-Pins (#96)

Fix-Runde 1 des Final-Whole-Branch-Reviews (Befunde S1-S8, Plan-Erratum E2).

- F1 (S1): build_series rastert am letzten Tick: k = floor((now - ts)/interval + 0.5),
  Index capacity - 1 - k, nur ts <= now und 0 <= k < capacity. Jitter unter
  interval/2 erzeugt keine falschen stale-Luecken mehr. RED auf altem Code:
  Jitter-Test (None statt 2.0 im vierten Slot) und Sampler-Test mit Ticks
  2.94/6.04/8.94.
- F2 (S2): Einzelwerte ohne Nicht-None-Nachbarn werden in monitor_ui als
  gefuellter Kreis in der accent-Farbe gezeichnet (pycairo-Sonde:
  (None,None,55,None,None) 0 -> 14 Akzent-Pixel, Linienfall unveraendert 44).
- F3 (S3): build_series ueberspringt nicht-endliche ts und liefert bei
  nicht-endlichem now das leere Raster; parse_pressure_avg10 wirft bei
  nan/inf ValueError (Sampler-Luecke). RED: OverflowError/ValueError bzw.
  fehlende Exceptions. RingBuffer-Vertrag unveraendert.
- F4 (S4): Test mit TZ=XXX-02 pinnt Messzeit 02:16:40 in Caption und
  Drill-down. Mutation localtime->gmtime je Funktion: rot.
- F5 (S5): Pin format_value(psi_io_avg10, 2.50) == '2.50 %'. Mutation
  round(value, decimals): rot.
- F6 (S6): Pin parse_meminfo('MemTotal:\nMemAvailable: 1 kB\n') -> ValueError.
  Mutation Guard entfernt: rot (IndexError).
- F7 (S8): Testkommentar-Verweis MONITOR.md 3 -> 2; Modul-Docstrings von
  monitor_model.py und Modell-Tests an den heutigen Umfang angepasst.
- MONITOR.md 2 (Serien-Regeln E2, nicht-endliche Zahlen), 3 (avg10 nan/inf),
  4 (Einzelpunkt).

Tests: 77 -> 86 (alle gruen), Python-Suite 53, Start-Gates Wayland/X11 Exit 124.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Das Scoped-Re-Review der Final-Fix-Runde 1 (N1) hat gezeigt, dass E2 nur
Jitter um eine feste Phase verträgt: Stalls ≥ 0,25 s verschieben die Phase
von timeout_add_seconds dauerhaft, ab 1,5 s Summe entsteht wieder eine
falsche stale-Lücke. E3 legt die Slots als Kette über die Abstände
benachbarter Einträge fest. Nur der Plan wird angepasst (append-only).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…innt (#96)

Fix-Runde 2 des Final-Reviews (Scoped-Re-Review N1/N2, Plan-Erratum E3).

- G1 (N1): build_series rastert als Kette. Der jüngste Eintrag (ts <= now,
  endlich) liegt k0 = floor((now - ts)/interval + 0.5) Slots vor dem
  letzten, jeder ältere step = floor(Delta/interval + 0.5) Slots vor dem
  zuletzt berücksichtigten jüngeren; step == 0 = selber Slot (jüngerer
  bleibt), Index < 0 beendet die Kette. Lücken nur bei echten Abständen
  ab 1,5 Intervallen, Phasendrift des Zeitgebers (Main-Loop-Stalls)
  verschiebt nichts mehr. Docstring und MONITOR.md 2 umgeschrieben
  (Jitter-Satz präzisiert, Fenster-Stauchung erwähnt).
- RED auf f0802b3: Abstände 3,3,4,3,3,4,3,3 ergeben
  (None, None, 0.0, 3.0, 6.0, None, 10.0, ...) statt lückenlos; derselbe
  Ablauf über den Sampler (FakeClock) lässt stale-Slots im belegten
  Bereich. Kontrolle: Abstand 4,5 s = genau eine Lücke, 4,49 s keine.
- G2 (N2): Fenstergrenze gepinnt (ts=0, capacity 5, now=15 -> leeres
  Raster). Mutation "index < 0" -> "index < -1": rot.
- Weitere Mutanten (kein step==0-Skip; Kette nie nachgezogen): rot.
- Probe: sim_probe 0/400 falsche Lücken in allen Szenarien (vorher 118/400
  bis 400/400 bei Stalls), echter GLib-Loop mit Stalls 3=0.35,7=0.35:
  inner_none durchgehend 0 (vorher 1 ab Tick 7).

Tests: 86 -> 90 (alle grün), Python-Suite 53, Start-Gates Exit 124.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Schließt Task 5 des SDD-Plans ab:
- VERIFY.md: Abschnitt „Handoff #96" mit Status, Scope, RED-Belegen je
  Task und Fix-Runde, Kernresultaten, Gate-Tabellen (Frischlauf auf
  7f01b7b und nach den Fixes auf e7e8145), roten/übersprungenen Gates,
  manuellen Zorin-Resten, Reviewer-Tabelle, Final-Whole-Branch-Review
  (CHANGES_REQUESTED 0/1/8 → 2 Fix-Runden → APPROVED), Rückfallplan
  inkl. tokens.css (S9) und Grenzen.
- ISSUES.md #96: Abnahme 1–4 und Handoff 1–4 abgehakt, je mit Evidenz.
- MONITOR.md: §5 Vergleichsbasis Flutter, §7 Grenzen/#97 (u. a. geparktes
  N3, Suspend-Verhalten, Teardown-Flake), §6 auf 90 Tests (S7), Kopf.
- prototype/gtk/README.md: Monitor-Screen liest /proc statt Demo-Daten.

Alle Zahlen, SHAs und Verdikte wurden per Claim-Check gegen Gate-Logs,
git log und Reports geprüft; die 24 Abweichungen sind eingearbeitet.
GTK-Suite nach dem Commit: Ran 90 tests, OK.

Refs #96

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings October 17, 2026 04:42

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Fix first-entry NaN rejection and reject fractional ring-buffer capacities.

1 open issue
What changed in this PR

Adds a read-only GTK system monitor backed by /proc, with fixed-size history, charts, sampling, and drill-down details.

Changes:

  • Adds parsers, ring buffers, samplers, fixtures, and tests.
  • Integrates GTK charts, captions, styling, and timer lifecycle.
  • Documents the monitor specification, tokens, implementation, and verification.

Review status: unresolved issues remain around first-entry NaN timestamps and fractional ring-buffer capacities.

File Description
test/​fixtures/​README.md Documents synthetic monitor fixtures.
test/​fixtures/​proc_stat_truncated.txt Provides an invalid CPU fixture.
test/​fixtures/​proc_stat_b.txt Provides a CPU follow-up fixture.
test/​fixtures/​proc_stat_a.txt Provides a CPU baseline fixture.
test/​fixtures/​proc_pressure_memory.txt Provides memory PSI test data.
test/​fixtures/​proc_pressure_io.txt Provides I/O PSI test data.
test/​fixtures/​proc_pressure_cpu.txt Provides CPU PSI test data.
test/​fixtures/​proc_meminfo.txt Provides memory statistics test data.
prototype/​gtk/​tokens.css Adds drill-down styling.
prototype/​gtk/​tests/​test_tokens.py Extends color hardcode checks.
prototype/​gtk/​tests/​test_monitor_model.py Tests monitor models and formatters.
prototype/​gtk/​README.md Documents GTK monitor scope.
prototype/​gtk/​monitor_ui.py Implements charts and interactions.
prototype/​gtk/​monitor_model.py Implements parsing, sampling, buffers, and formatting.
prototype/​gtk/​mla_app.py Integrates monitor polling and drill-down.
docs/​superpowers/​plans/​2026-10-02-mla-96-monitor.md Documents the implementation plan.
docs/​mla-next/​VERIFY.md Records handoff and gate evidence.
docs/​mla-next/​TOKENS.md Documents monitor token usage.
docs/​mla-next/​MONITOR.md Defines the monitor specification.
docs/​mla-next/​ISSUES.md Records acceptance and handoff status.

Review effort: Lite

Comment thread prototype/gtk/monitor_model.py Resolved
Toqsick and others added 6 commits October 17, 2026 06:58
…zität (#96)

Das Copilot-Review von PR #119 zeigte zwei zu weite Task-2-Regeln:
„erster Append immer akzeptiert" ließ ein NaN in den Puffer, das jeden
späteren Append blockierte; „capacity ≥ 1" ließ Brüche, ganzzahlige
Floats, bool und nan/inf durch. E4 legt fest: NaN wird immer abgelehnt,
auch als Erstappend; capacity ist ein int ≥ 1 (ohne bool). Der
±inf-Vertrag und D3 bleiben unverändert, bindend ist MONITOR.md §2.

Refs #96

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ehnen (#96)

Behebt zwei Punkte aus dem Copilot-Review von PR #119:

- RingBuffer.append nahm NaN als ersten Zeitstempel an, weil der Guard
  bei leerem Puffer kurzschloss. Danach scheiterte jeder spätere Append
  an `ts > nan`; der Wert blieb dauerhaft blockiert. NaN wird jetzt vor
  dem Leerpuffer-Kurzschluss abgewiesen (zählt in `rejected`); der
  Sampler macht daraus wie bisher die Lücke „Zeit nicht monoton", der
  nächste gültige Tick misst normal.
- RingBuffer(capacity) prüfte nur `capacity < 1`. Brüche, ganzzahlige
  Floats, bool und nan/inf liefen durch: inf/nan hebelten den Überlauf
  aus, 2.5 scheiterte erst in build_series mit TypeError. Jetzt gilt nur
  `int` >= 1, sonst ValueError — auch über Sampler(capacity=...).

Der gepinnte ±inf-Vertrag bleibt unverändert (+inf geordnet angenommen,
-inf nur als Erstappend). MONITOR.md §2 und §6 nachgezogen.

TDD: 4 neue Tests zuerst rot (7 failures, 1 error), danach GTK-Suite
94/94 OK (84 Modell + 10 Token), additional/python 53 OK,
check-versions konsistent, Start-Gates Wayland/X11 je 3 × Exit 124.

Refs #96

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…anch-Ende (#96)

VERIFY.md Handoff #96 nennt jetzt Erratum E4 (8af55b6) und Fix 3
(2391512) aus dem Copilot-Review von PR #119: RED-Beleg, Gate-Teillauf
(GTK 94 OK, Python 53 OK, Start-Gates je Exit 124) und die adversariale
Prüfung (3 Opus-Linsen, je APPROVED). Kernresultat 2 beschreibt NaN- und
Kapazitätsregel wie umgesetzt. Der Rückfallplan reicht bis zum
Branch-Ende, weil ein Revert nur bis 6f60352 in MONITOR.md konfligiert.

Refs #96

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Die Revert-Probe im Wegwerf-Klon ergab: der Bereich 5a27740^..HEAD
revertiert mit Exit 0 auf den Baum von de0026d; ein Bereich nur bis
6f60352 konfligiert in MONITOR.md und VERIFY.md, nicht nur in
MONITOR.md wie im Nachtrag genannt.

Refs #96

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Die rechte Detail-Leiste war seit dem Scaffold (6c5c625) bei
Erst-Allokation nur ~60 px sichtbar, der Drill-down des Monitors (#96)
wurde abgeschnitten. Ursache: Gtk.Paned liegt im Inhaltsbereich der
NavigationSplitView (1200 px Fenster − 280 px Nav-Sidebar = 920 px),
PANE_POSITION 850 zählt ab dessen linker Kante, und mit dem GTK4-Default
shrink-end-child=TRUE klemmt der Trenner nicht gegen die 280-px-
Mindestbreite. GTK alloziert die Leiste trotzdem mit 280 px, aber ab
Fenster-x 1131 — 211 px liegen jenseits des rechten Rands und werden
vom Paned abgeschnitten (X11 sichtbar 69 px; Wayland skaliert den
Trenner nach dem Compositor-Resize auf 954 px proportional auf 661,
sichtbar 54 px).

Fix: build_detail_pane() setzt shrink-end-child=False; der Trenner wird
auf Paned-Breite − 1 − DETAILS_MIN_WIDTH geklemmt (bei 1200 px: 639,
Leiste 280 px bis exakt zur Fensterkante, auch nach Resize).

Belege: Geometrie-Sonde X11 und Wayland, X11-Pixel-Scan vorher/nachher
(xdotool + import, compare -metric AE; Trenner Fenster-x 1130 → 919,
Text-Pixel an der Fensterkante 55 → 0), test_shell_layout.py RED
(sichtbar 69/54/51/100 px) → GREEN. Auf 7924d58 rebased: GTK-Suite
96 OK (ohne gi bzw. Display 2 übersprungen, wie in CI), Python-Suite
53 OK, Start-Gates je 3× Wayland/X11 Exit 124, stderr 0 B. MONITOR.md
§6/§7 und TOKENS.md §2 (layoutPanePos-Bezug) nachgezogen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
VERIFY.md führte die gequetschte rechte Detail-Leiste noch als geparkt
(manuelle Zorin-Prüfung) bzw. als „vor #97 triagieren“ (Grenzen). Mit
3e920a8 ist sie im selben PR behoben: die Zorin-Prüfung prüft jetzt die
280-px-Leiste mit ungeclipptem Drill-down mit, und die Grenzen nennen
nur noch die beiden offenen Reste für den Visual-/A11y-Durchgang in #97
(fehlendes padding-right der Leiste, auf 639 geklemmtes PANE_POSITION).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Toqsick
Toqsick merged commit 53c9e36 into main Oct 19, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants