Skip to content

feat(mla): Modul-Registry und HubModule-Adapter (#60) - #89

Merged
Toqsick merged 24 commits into
mainfrom
feature/mla-gtk-scaffold
Sep 30, 2026
Merged

Toqsick merged 24 commits into
mainfrom
feature/mla-gtk-scaffold

Conversation

@Toqsick

@Toqsick Toqsick commented Sep 29, 2026 •

Copy link
Copy Markdown
Owner

Ersetzt die acht navigationsrelevanten switch-Blöcke im Hub durch eine Registry und liefert den Flutter-HubModule-Adapter zu packages/la_core.

Closes #60.

Umfang dieses PRs (wichtig)

Der Branch feature/mla-gtk-scaffold trägt den gesamten MLA-Next-Stand — 24 Commits, die main bisher nicht hat. Dieser PR bringt daher mehr mit als nur #60:

#60 im Einzelnen

  • Neu lib/layouts/hub/hub_module.dart: HubModule, hubModules, hubModuleOf; HubSection/HubTool ziehen dorthin um, hub_shell.dart re-exportiert sie.
  • Acht Switches → Lookups. Verbleibend und erlaubt: BrowserLaunchResult und ThemeMode.
  • Neun Einträge reichen je einen ModuleDescriptor aus la_core durch; la_core bleibt unberührt und Flutter-frei.
  • HubModule ergänzt Icon, Tier, screenBuilder, isAvailable(Environment).
  • Vier neue ARB-Keys in allen vier ARB-Dateien + regenerierte app_localizations*.dart.
  • SystemStatsService: nur lesender Test-Seam sectionActive.

Verhalten

en/de byte-identisch: die Charakterisierungstests H1–H8 wurden zuerst gegen den alten switch-Code geschrieben und blieben unverändert grün. Für it/fi zeigen die vier Werkzeugtitel jetzt echte Übersetzungen statt des englischen _tr-Fallbacks — vom l10n-Gate erzwungen, nicht gewählt; die Wortwahl ist noch unbestätigt.

Gates — lokal ausgeführt, alle Exit 0

Gate Ausgabe
bash tool/check-versions.sh version 0.8.0 is consistent
dart format --output=none --set-exit-if-changed lib test Formatted 122 files (0 changed)
flutter analyze No issues found!
flutter test 00:09 +200: All tests passed!
flutter test test/hub_navigation_test.dart +9: All tests passed!
flutter test test/hub_module_registry_test.dart +7: All tests passed!
python3 -m unittest discover -s tests -t . Ran 49 tests / OK
la_core: analyze · format · test No issues found! · 13 files (0 changed) · +30: All tests passed!

Kein CI-Grün — .github/workflows/build.yml triggert diesen Branch nicht; Ersatzwahrheit ist der lokale Lauf. Beweise, akzeptierte Befunde, Planabweichungen und Rückfallplan stehen im Abschnitt „Abnahme #60" in docs/mla-next/VERIFY.md.

Offen (nach Merge)

🤖 Generated with Claude Code

Toqsick and others added 8 commits September 30, 2026 01:40
…odies

Spiegel der GitHub-Stände vom 2026-09-30: sieben MLA-Next-Milestones
(#12-#18 auf GitHub), 17 Issues #90-#106 (Label track:mla-next) und die
ausgearbeiteten Bodies der Roadmap-Issues #58-#87. Nur neue Dateien unter
docs/mla-next/; kein Code, keine Policy, kein Packaging.

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

Schnitt 1 von #93: es wandern nur Modelle und Parse-Funktionen, die Runner
bleiben app-seitig (sie hängen an Linux.runCommandWithCustomArguments bzw.
CommandHelper, ein Umzug würde runInShell/expandCommand/kDebugMode verschieben).

Neu in packages/la_core: parseDfOutput + DeviceInfo, parsePsOutput +
ProcessStat, parseUptime + Uptime, parseLoadAvg, MemoryInfo.parseFreeOutput +
MemoryInfo. Die Rümpfe sind 1:1 aus der App übernommen, nur static -> Top-Level;
@immutable entfällt, damit der Kern dependency-frei bleibt.

Neu: test/parsers_test.dart mit denselben Fixtures wie der App-Test, inline -
eine gemeinsame Fixture-Ablage ist #94 und von diesem Schnitt blockiert.
dart test 14 -> 30.

Das SDK-Bound bleibt bei ^3.11.0 (bf4942b, deckungsgleich mit
packages/la_core/pubspec.lock); ergänzt ist nur ein Kommentar, der erklärt,
warum ein Absenken kein No-op wäre: die Spracheversion steuert, welche
Formatierer-Regeln `dart format` auf das Paket anwendet.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Die drei Fassaden lib/linux/{linux_filesystem,linux_process,linux_system}.dart
halten nur noch Klassenrumpf und Runner; die Parser-statics delegieren prefixed
an la_core und die Modelle werden re-exportiert:

  import 'package:la_core/la_core.dart' as core;
  export 'package:la_core/la_core.dart' show DeviceInfo;

Das Präfix ist Pflicht, nicht Stil: ein unqualifizierter Aufruf im Body eines
gleichnamigen static bindet über den Class-Scope auf sich selbst und ergäbe eine
Endlosrekursion, die sauber kompiliert und von keinem Analyzer-Gate gefangen wird.

lib/services/system_stats_service.dart bekommt import UND export von MemoryInfo:
ein export importiert nicht in dieselbe Library, der import deckt den eigenen
Scope (Feld SystemStats.memory, Aufruf in refresh), der export hält
package:linux_assistant/... als Bezugsweg für den bestehenden Test offen.
SystemStats und SystemStatsService bleiben unverändert app-seitig.

test/system_parsers_test.dart bleibt byte-identisch (kein Diff). Gates:
la_core dart test 30/30, analyze/format/compile exe + Headless-Probe grün;
App flutter test +184, gezielter Parser-Test +22, flutter analyze sauber,
dart format 0 changed, tool/check-versions.sh konsistent, Python 49 OK.

Nebenbei, unabhängig von #93: flutter pub get hat die gegen die installierte
Flutter 3.47.5 veraltete pubspec.lock neu aufgelöst - intl 0.20.2 -> 0.20.3
(flutter_localizations verlangt intl ^0.20.3), test_api 0.7.12, matcher 0.12.20,
meta 1.19.0, vector_math 2.4.3; die sdks-Zeile steht damit auf dart >=3.11.0,
was zum SDK-Bound von la_core passt.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Handoff-Abschnitt zu den Commits 94b5ef8 und 755665c: Basis-SHA, Pfade der
verschobenen Parser, die zwei Fallen (Class-Scope-Schatten im Delegator,
export importiert nicht), alle tatsächlich ausgeführten Gates mit Ausgabe,
nicht ausgeführte Gates (CI triggert den Branch nicht; kein Runner-
Verhaltensnachweis) und Rückfallplan. Dazu die festgehaltene Planabweichung:
das SDK-Bound blieb ^3.11.0 statt wie geplant auf ^3.4.0 zu sinken.

Unabhängige Verifikation durch den read-only Workflow mla-93-parser-move-verify
(vier Linsen + Synthese, 5 Agenten): Synthese-Verdikt PASS ohne Blocker;
Endlosrekursion, gespaltener Typ und Logikdrift gezielt ausgeschlossen, Rümpfe
gegen 513def1 byte-identisch. Festgehalten sind auch die Einschränkungen der
Runde: leere Belegketten der Linsen 1/2/4, bewegter Arbeitsbaum während der
Verifikation, und die Formatierer-Methodik (dart format liest die
Spracheversion aus .dart_tool/package_config.json - erst dart pub get, dann
formatieren).

Co-Authored-By: Claude Code <noreply@anthropic.com>
Der Handoff-Abschnitt in VERIFY.md stand nach dem Push noch auf "unpushed"
und listete nur zwei der drei Commits. Jetzt: drei Commits, gepusht als
Fast-Forward 513def1..080becf. Im Rückfallplan entfällt der reset-Weg, weil
der Branch geteilt ist -- revert ist der gangbare Pfad.

Co-Authored-By: Claude Code <noreply@anthropic.com>
…ions-Switches (#60)

Die acht navigationsrelevanten switch-Blöcke in lib/layouts/hub/hub_shell.dart sind
durch Lookups in die neue Registry lib/layouts/hub/hub_module.dart ersetzt (HubModule,
hubModules, hubModuleOf). Die Enums HubSection/HubTool ziehen dorthin um und werden von
hub_shell.dart re-exportiert.

Die neun Einträge reichen je einen ModuleDescriptor aus packages/la_core durch — la_core
bleibt unangetastet und Flutter-frei. HubModule ergänzt den Kern um Icon, Tier,
screenBuilder und isAvailable(Environment).

Vier neue ARB-Keys (browser, quickNotes, fileManager, systemMonitor) in allen vier
ARB-Dateien plus regenerierte app_localizations*.dart. SystemStatsService bekommt den
nur lesenden Test-Seam sectionActive.

en/de sind byte-identisch: die Charakterisierungstests H1–H8 wurden zuerst gegen den alten
switch-Code geschrieben und blieben unverändert grün. Für it/fi zeigen die vier
Werkzeugtitel jetzt echte Übersetzungen statt des englischen _tr-Fallbacks — vom l10n-Gate
erzwungen, nicht gewählt.

Tests: test/hub_navigation_test.dart (H1–H9), test/hub_module_registry_test.dart (T1–T7),
test/hub_test_harness.dart. Voller Lauf +200 grün. Der Abschnitt „Abnahme #60" in
docs/mla-next/VERIFY.md belegt alle Gates mit ausgegebener Ausgabe.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Basis-SHA, Gate-Tabelle mit tatsächlichen Ausgaben, Rest-Switch-Beweis, Abnahmekriterien,
Synthese-Verdikt (PASS), akzeptierte Befunde, nicht ausgeführte Gates, Test-Nebenwirkung,
Planabweichungen, Leak-Grep-Einordnung und Rückfallplan. Dazu drei alte Stellen korrigiert:
la_core dart test 14 -> 30, Gate-1-Box für #60 mit geliefertem Adapter, HubModule-Adapter
nicht mehr als offen geführt.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Journal- und pkexec-Auszüge in drei Handoff-Dateien trugen den lokalen Nutzernamen
(viermal unix-user/pkexec bzw. eine uid-Zeile, dazu ein --home-Pfad) sowie einen absoluten
Repo-Pfad. Ersetzt durch <user> bzw. $HOME. Kein Code, keine Aussage geändert.

Co-Authored-By: Claude Code <noreply@anthropic.com>
@Toqsick Toqsick changed the title docs(mla): GTK4 scaffold, IPC contract and agent plan (draft) feat(mla): Modul-Registry und HubModule-Adapter (#60) Sep 30, 2026
@Toqsick
Toqsick marked this pull request as ready for review September 30, 2026 01:24
Copilot AI balanced review requested due to automatic review settings September 30, 2026 01:24

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@Toqsick
Toqsick merged commit 6c5c625 into main Sep 30, 2026
1 check passed
Toqsick added a commit that referenced this pull request Sep 30, 2026
* docs(mla): SDD-Plan Follow-up-Paket (#89-#95-Reviews)

Umfang «Kompakt + Spawn-Tests» (User-Entscheidung 2026-09-30):
parsePsOutput-Filterreihenfolge, ProbeLevel->ProbeSeverity,
ProbeStatus-Doc-Hinweis, RAM-Anzeige-Bug (free -m statt free,
1024x-Anzeigefehler), Leak-Check .ai-TLD + subTests,
Spawn-Echtheits-Nachweis mit Fake-Binaries, checkout@v4,
BASELINE 6.4/8-Halbsatz, Plan-Erratum, AGENTS.md-Zahlen.

Quellen: Final-Review-Minors der SDD-Laeufe #89/#93/#94/#95.

* fix(la_core): parsePsOutput liefert trotz Bare-Lines die geforderte Anzahl; ProbeLevel heisst jetzt ProbeSeverity

Follow-up aus #94-Review (take-vor-Filter, Namenskollision) und #89-Review (ProbeStatus-Diskriminator).

- parsePsOutput: `.take(count)` griff vor dem Filtern der Bare-Lines
  (Kernel-Thread-Zeilen ohne Command), sodass weniger als `count`
  Eintraege herauskommen konnten, obwohl genug gueltige Zeilen folgten.
  Jetzt werden ungueltige Zeilen uebersprungen und erst die gesammelten
  gueltigen auf `count` begrenzt; uebersprungene Zeilen zaehlen nicht
  mit. TDD: neuer Test lieferte zuerst RED.
- ProbeLevel heisst jetzt ProbeSeverity, zur Abgrenzung von ProbeState
  (Zustandsmaschine unknown/running/ok/stale/failed): Severity ist die
  Bewertung eines Probe-Ergebnisses. describe()-Format unveraendert.
- ProbeStatus: Doc-Hinweis, dass der Diskriminator fuer Verzweigungen
  `state` ist, nie `data != null` (data kann in non-ok-Zustaenden
  nicht-null sein, z. B. stale).

* fix(linux): RAM-Werte in MiB erfassen (free -m) — Anzeige war 1024x zu hoch

Der Capture in LinuxSystem.hasSwap (lib/linux/linux_system.dart) lief
/usr/bin/free ohne -m und erhielt damit KiB-Werte, waehrend MemoryInfo.*Mb
laut Dokumentation Mebibytes erwartet ("free -m") und die Formatter
(_formatGb/_gb, je /1024) MiB zu GiB umrechnen: auf diesem Pfad waren alle
RAM-/Swap-Zahlen um den Faktor 1024 zu hoch. CommandHelper.run uebergibt den
Befehl als nacktes argv.first, deshalb fuehrt der Fix das Argument ueber
CommandHelper.runWithArguments("/usr/bin/free", ["-m"]) — "free -m" als
einzelner String waere ein ungueltiger Pfad.

Die Fixture zorin_free.txt (belegte den Fehler: "Mem: 16066996" = KiB) wurde
unprivilegiert mit dem korrigierten Aufruf neu aufgezeichnet
(LC_ALL=C /usr/bin/free -m, jetzt Mem: 15690 MiB) und die Erwartungen in
test/system_parsers_test.dart und packages/la_core/test/parsers_test.dart an
die MiB-Werte angepasst; free_no_swap.txt bleibt unveraendert (synthetisch,
bereits MiB-skaliert). test/fixtures/README.md dokumentiert das korrigierte
Capture-Kommando und den Bug-Sachverhalt.

Quellen: Follow-up aus dem #94-Review-Minor zu MemoryInfo MiB/KiB und
Ad-hoc-Befund RAM-Anzeige vom 2026-09-30 (SDD-Plan
docs/superpowers/plans/2026-09-30-mla-followups-compact.md, Task 2). Der
Dashboard-Poller (system_stats_service.dart) fuehrte free -m bereits
korrekt; der Fix beseitigt den letzten KiB-Capture. /usr/bin/free bleibt
unprivilegierter Lese-Befehl und steht in keiner Stelle der
Polkit-Tritaet (_privilegedEntryPoints, Policy exec.path, chmod +x).

* test(python): Leak-Check erkennt .ai-Domains und nennt die Fixture im subTest

MUST_FLAG erhaelt den generischen Vektor "visit https://foo.bar.ai now"
(RED beobachtet: nicht geflaggt); .ai wandert in die TLD-Allowlist, damit
domainaehnliche .ai-Hosts wie die reale Account-URL aus dem #94-Review
zuverlaessig flaggen. Fehlalarm-Check: alle Fixtures und MUST_NOT_FLAG-
Vektoren bleiben unkritisch (Wortgrenze schliesst .airport & Co. aus).

FixturesClean uebergibt jede Fixture-Datei an ein subTest(fixture=...),
ein Fund benennt damit die Datei statt nur 'irgendein Scan schlug fehl'.

Testvektoren: die echten Accountnamen (bratan/braten) in den Home- und
Media-Vektoren durch generische Platzhalter ersetzt (alice/bob) — gleiche
Regel wird getestet, kein Identitaetsabdruck im Testcode.

Quellen: #94-Review-Minors (TLD-Allowlist-Luecke .ai, keine subTests in
FixturesClean, Username in Testvektoren) aus dem Final-Review des
Fixture-Leak-Checks.

* test(app): Echter Prozess-Spawn-Nachweis fuer ProcessCommandRunner mit Fake-Binaries

Schliesst die #93-Handoff-Luecke 'Kein echter Prozess-Spawn-Beweis fuer
pkexec/flatpak-spawn': echte Process.run-Laeufe gegen POSIX-Fake-Skripte,
die per PATH-Injektion ueber das environment-Argument eingeschleust werden
und ihr argv in eine Dump-Datei schreiben. Der innere Befehl wird nie
ausgefuehrt; nichts Privilegiertes wird gestartet.

Gepinnt: pkexec-Praefix, flatpak-spawn mit/ohne --host, Kombination
flatpak-spawn --host pkexec, Exit-Code/Stdout/Stderr-Mapping, fehlendes
Binary als Erfolg=false/ExitCode=-1 statt Exception sowie die
Umgebungs-Semantik. Gemessene Dart-Realitaet: Process.run merged das
Eltern-Env herein (includeParentEnvironment-Default true) — ein ueber-
gebenes environment ohne PATH-Schluessel loest den nackten Praefix weiter
ueber den Eltern-PATH auf; ein explizit uebergebenes PATH entscheidet die
Aufloesung allein. Als Dokumentations-Test gepinnt, kein Produktionsfix.

* chore(ci): checkout@v4 und Doku-Nachtraege aus den Task-Reviews

CI: actions/checkout@v3 -> @v4 (Node-20-Deprecation-Warnung);
upload-artifact@v4 bleibt unveraendert.

Nachtraege aus den Task-1-4-Reviews des Follow-up-Plans
(2026-09-30-mla-followups-compact):
- Plan-Erratum Spawn-Tests: Design-Entscheidung korrigiert —
  Process.run merged per Default (includeParentEnvironment: true),
  ein uebergebenes Environment ersetzt das Eltern-Env nicht; belegt
  in test/process_command_runner_test.dart, Tests 7+8.
- #95-Plan-Erratum: je Zelle 5 Startup- + 5 Steady-Lauefe getrennt
  (WAYLAND_DEBUG-Perturbations-Isolation), nicht kombiniert 5 Laeufe.
- BASELINE §6.4: Analyzer-Exclude-Thema als erledigt textiert
  (Commit 1367d3c) — damit ist das #90-Abnahme-Teilitem geschlossen;
  Screenshot und -dev-Pakete bleiben offen.
- BASELINE §8 Befund (a): Halbsatz — die ~101 % CPU enthalten auch
  den moeglichen Anteil des 3-s-Stat-Polls (Subprozess-Spawns), sind
  nicht reine Renderkosten (Final-Review-Minor M2, #95).
- AGENTS.md: Testzahlen frisch erhoben (18 Dart-Testdateien, 208
  Faelle, 53 Python-Tests) und la_core-Gates ergaenzt.
- test/fixtures/README.md: Paritaetszeile zorin_free.txt verweist
  auf lib/linux/linux_system.dart:13-14 (Capture nach dem free--m-Fix).
- Leak-Check-Kommentar: ALLOWED_TLDS ist die Liste der erkannten/
  geflaggten TLDs, keine Ausnahmeliste (nur Kommentar).
- #94-Plan: Testvektoren zu /home/alice/secret.txt und
  /media/bob/USB genericisiert (Konsistenz mit dem Task-3-Test-Change).

Gates: Python 53 Tests OK; Root format/analyze/test Exit 0 (+208);
la_core format/analyze/test Exit 0 (+61); check-versions konsistent.

* docs(mla): Env-Erratum praezisieren und Impeller-Formulierungen angleichen

F1 (Review MAJOR): Das Erratum im Follow-ups-Plan behauptete, eine
vollständige Ablösung des Eltern-Envs wuerde das Kind nicht PATH-los
lassen, "da Dart dann einen Default-PATH setzt" — empirisch falsch.
Korrektur: Bei includeParentEnvironment: false bleibt das Kind PATH-los,
Dart setzt keinen Default-PATH (nackter Name -> ProcessException).
Fehleindruck-Herkunft: ein Shell-Kind wie /bin/sh setzt sich selbst
einen Default-PATH — Shell-, kein Dart-Verhalten. Kernaussage unveraendert:
der Runner merged per Default (includeParentEnvironment: true), Tests 7+8
in test/process_command_runner_test.dart belegen es.

F2 (Minor): Sprachrest im Leak-Check-Test entfernt — Inline-Kommentar an
Muster 4 sagt jetzt "TLD from the recognized-TLD list" statt "allowlist",
passend zum korrigierten Kopkommentar (die Liste ist keine Allowlist).

F3 (Minor, 2 Stellen): Unqualifizierte "Impeller-Dauerrendern"-
Formulierungen um den BASELINE §8 Befund (a)-Qualifizierer ergänzt
(nicht reine Renderkosten, enthält den 3-s-Poll-Anteil) — in
VERIFY.md Handoff #95 Kernresultate und im #95-Plan-Erratum.

Quellen F2/F3: Task-5-Reviews. Keine Zahlen/Verdicts geaendert.
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.

[V0.9] FU1 Modul-Registry (#27)

2 participants