Commit Graph

19 Commits

Author SHA1 Message Date
marcus hinz 2251a1d45f Technische ID als Identität der Notizen; Pfad wird zur Eigenschaft
Bisher war der Dateipfad die Identität einer Notiz: Umbenennen brach
Verweise, und der Pfad tauchte in der Oberfläche auf (Tooltips, Menüpunkte
"Dateiname ändern"/"Ordnerpfad ändern"). Jede Notiz trägt jetzt eine
technische ID im Frontmatter (id: <uuid>), die nie wechselt; der
Systempfad ist nur noch eine Eigenschaft.

- ensure_ids ergänzt fehlende IDs beim Seitenaufbau (wie ensure_node_texts);
  frontmatter() schreibt sie bei jedem Anlegen als erste Zeile.
- Doc, WikiDocEntry, FolderNode und Suchtreffer führen die ID mit;
  resolve_id löst sie auf den aktuellen relpath auf.
- Commands sprechen IDs: archive_read/write/set_title/delete nehmen `id`,
  archive_create_doc/create_folder die ID des Elternknotens plus Namen,
  panel_archive_cmd den Zielknoten als ID.
- Frontend adressiert durchgehend über IDs: Auswahl, Klapp-Zustand,
  Verlauf des Zurück-Knopfs, Wikilink-Sprünge, Suchtreffer-Vormerkung und
  der Zielordner-Baum des Archiv-Dialogs.
- Der Pfad ist aus der Oberfläche verschwunden: die Menüpunkte zum
  Umbenennen von Datei und Ordner samt Commands (archive_rename,
  archive_move, archive_move_folder) sind entfallen — es gibt nur noch den
  Titel, Name und Titel können nicht mehr auseinanderlaufen.

Offen dadurch: Verschieben im Baum fehlt (ToDo: Drag & Drop).

Archiv-Dialog nebenbei überarbeitet: modales Popup im Design der
Archiv-Ansicht mit Abbrechen und zuverlässigem Escape, Zielordner über
einen einklappbaren Baum statt Pfadeingabe, zusätzlicher Knopf "Auf Platte
legen" (panel_save_as); Archivieren öffnet keinen Dateimanager mehr.
2026-07-26 17:53:19 +02:00
marcus hinz 9de58d43e8 Archiv als eigenes Fenster: Trilium raus, Notizbaum mit In-Place-Bearbeitung
Trilium-Integration komplett zurückgenommen (Revert von 47951a6): keine
verwaltete Instanz, kein Runtime-Download, kein ETAPI, kein Keyring-Token,
kein Setup-Wizard. Das Archiv sind wieder Markdown-Dateien unter archiveHome
samt FTS5-Suche und Wikilinks.

Notizmodell (an Trilium orientiert, ohne dessen Überbau):
- Jeder Knoten besitzt eine Textdatei — ensure_node_texts legt fehlende beim
  Seitenaufbau an (Ordner: gleichnamiges .md daneben, Wurzel: index.md);
  Ordner und Zwillingsdatei sind EINE Notiz mit Inhalt und Kindern.
- Der angezeigte Titel steht im Frontmatter der Datei, der Datei-/Ordnername
  ist technischer Verwaltungsname; move_folder nimmt den Knotentext mit.

Archiv-Ansicht (wiki-view):
- Baum links: Knoten- und Blatt-Symbole, Führungslinien pro Ebene, Dokumente
  näher an der Linie als Ordner; ganze Zeile wählt aus, nur der Pfeil klappt.
- Notiz-Ansicht rechts: großer Titel (Klick bearbeitet ihn → archive_set_title),
  Zurück-Knopf mit Auswahl-Verlauf, Details als Popup am Info-Knopf, Kindliste
  als abgesetzter Karten-Block mit Anlage-/Änderungsdatum.
- Bearbeiten in place: Split-View aus Rohtext und Live-Vorschau, Speichern per
  Knopf oder Ctrl+S (archive_read/archive_write; Frontmatter bleibt).
- Rechte Maustaste im Baum als einziger Aktionsweg (eigenes Kontextmenü,
  Standard-Menü des Webviews aus); Anlegen/Umbenennen über modale Dialoge.

Feste Flächenaufteilung statt Ablösen/Andocken:
- Angedocktes Panel = Session-Begleiter (ToDo, Befehle, flüchtiger Entwurf);
  der Dokument-Tab ist aus der Leiste raus.
- Archiv-Fenster = Archiv + Suche, Größe und Position einmalig beim Öffnen
  aus dem Monitor des rufenden Terminal-Fensters (85 % / 92 %); Öffner-Klick
  bei stehendem Fenster fokussiert und schaltet den Tab (panel-mode).
- Terminal-Fenster zu → Archiv-Fenster geht mit.

Neue Commands: archive_read, archive_write, archive_set_title.
2026-07-26 14:44:06 +02:00
marcus hinz 47951a615b Trilium als Archiv: verwaltete Instanz pro Projekt, MD-Archiv und Dokument-Tab entfernt
- domain/trilium.rs: Runtime-Download (gepinnt 0.104.0), Instanz pro Projekt auf 127.0.0.1
  mit FNV-Port, ETAPI (archive_note, search_notes), Token im Keyring
- Setup bis aufs Passwort automatisiert: trilium_connect macht new-document (skipDemoDb),
  set-password und ETAPI-Login; Modul-Flag erst nach Token-Erfolg
- write_panel legt direkt eine Trilium-Notiz an (text|path, folder/description/tags);
  noteopen-Kanal, das Terminal-Fenster öffnet die Notiz (ersetzt archive_panel)
- MD-Altbestand raus: archive*/wiki*, archiveHome samt Permissions, panel_set/panel_load/
  wiki_open, panel_archive*/archive_docs/*_archive_home, reveal_path, spellcheck
- Dokument-Tab raus: Panel = ToDo/Befehle/Suche + Archiv-Knopf (trilium_open);
  panel-view/archive-form gelöscht, Markup/CSS/Messages bereinigt
- Lösch-Stufe Archiv: Instanz stoppen, Trilium-Datadir und Keyring-Token löschen
2026-07-24 21:42:03 +02:00
marcus hinz f58b9887c7 Archiv-Navigator: Baum nur Ordner + flache Inhaltsliste (Zeilen: öffnen/umbenennen/löschen), Ordner/Dokument anlegen (Dateiname ohne Stempel, Datum im Frontmatter), Write-back geöffneter Archiv-Dokumente über Quell-Verknüpfung; Ablösen übergibt aktiven Tab 2026-07-23 21:17:41 +02:00
marcus hinz 1523856ea7 Modul-System (Registry Backend+Frontend, generierte Tabs, Settings-Sektion); ToDo-Modul: persistente Liste mit Anlegen/Bearbeiten im Panel (todos_add/todos_update, Formular mit Abbrechen); alte Hook-Todoliste (OFFENE-PUNKTE.md) komplett entfernt 2026-07-23 11:35:29 +02:00
marcus hinz 513e1a768f Dopplungen konsolidiert: settings.json-Permissions-Helfer, pool.json-Lesen über read_pool, gemeinsame Helfer für Pool-Anlage, Projekt-Config, Icon-Übernahme und Running-Guard 2026-07-22 12:58:38 +02:00
marcusH ea08563411 Version 0.3.0, Selbstinstallation nach ~/Applications, Gatekeeper im README
Erster Start aus DMG oder Downloads bietet einmalig an, sich nach
~/Applications zu kopieren und von dort neu zu starten — der Weg dorthin
braucht kein Administrator-Passwort, anders als /Applications. Ein DMG
kann das nicht selbst leisten: der Applications-Alias darin ist ein
absoluter Symlink auf /Applications.

Die Kopie erbt per ditto die Quarantäne des Downloads, deshalb wird sie
am Ziel gelöst — sonst käme beim Neustart erneut die Gatekeeper-Warnung
für dieselbe, gerade laufende App. Ablehnen merkt sich die App
(moveOfferDismissed), im Debug-Build fragt sie nie.

README: ~/Applications als gleichwertiger Installationsort, dazu der
Weg über System-Einstellungen -> Datenschutz & Sicherheit fuer alle, die
kein Terminal aufmachen wollen.

0.8 ist fuer den Windows-Stand reserviert.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 10:47:36 +02:00
marcusH df828daea9 Pools können auf ein vorhandenes Config-Verzeichnis verweisen
Wer claude schon benutzt, hat einen fertigen Login in ~/.claude. Bisher
begann ai-control trotzdem bei null: jeder Pool war ein neu angelegtes
Verzeichnis, der erste Sessionstart verlangte /login. Ein Pool kann jetzt
stattdessen auf ein bestehendes Verzeichnis zeigen.

pool.json trägt dafür optional `dir` (home-kontrahiert). Der Pool-Ordner
ist dann nur die Hülle für diese Datei; pool_config_dir() löst auf und
ist die einzige Stelle, über die Sessionstart, Verbrauchsstatistik,
Panel-Provisionierung und Keychain-Name gehen.

Zeigt ein Pool auf claudes Default-Verzeichnis, bleibt CLAUDE_CONFIG_DIR
ungesetzt: claude nimmt dieses Verzeichnis von sich aus und damit den
unsuffixierten Keychain-Eintrag, an dem der bestehende Login hängt (am
Keychain gegengeprüft — "Claude Code-credentials" ohne Suffix neben den
suffixierten Pool-Einträgen). Ein Verweis auf ein anderes Verzeichnis
setzt die Variable wie gewohnt.

Das verwiesene Verzeichnis gehört der App nicht: dort entsteht nur die
Panel-Ausstattung (Skill, MCP-Eintrag, Freigabe-Ergänzung, alles
additiv), keine settings.json-Grundausstattung. Löschen trifft nur die
Hülle; Runtime-Symlinks und das Zurücksetzen des Keychain-Eintrags sind
gesperrt. Ein Verzeichnis kann nur ein Pool belegen, Ziele innerhalb von
pools/ sind ausgeschlossen.

In der UI erscheint der Knopf nur, wenn ~/.claude existiert und noch
kein Pool darauf zeigt; die Liste zeigt den Pfad unter dem Namen und
statt "Zurücksetzen" den Hinweis, dass die Anmeldung claude gehört.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 09:43:00 +02:00
marcus hinz cf2c25df79 Archiv-Wechsel mit Migrations-Option
Bei gesetztem Archiv-Home fragt ein Dialog nach: Dokumente ins neue
Archiv verschieben (Checkbox, standardmäßig aus — nichts wandert
implizit) oder liegen lassen. change_archive_home_cmd setzt das neue
Home, zieht auf Wunsch die Einträge um (gleiche Platte rename, sonst
Kopie + Löschen; Kollision im Ziel bricht laut ab) und nimmt die Rechte
des alten Ordners zurück.
2026-07-20 13:48:49 +02:00
marcus hinz 6c765ff7b5 Projekt löschen in drei Stufen mit Artefakt-Vorschau; Listen-Scroll gefixt
Eskalationsleiter: 'integration' nimmt nur die ai-control-Spuren zurück
(Registry, .ai-control/, Archiv-Rechte + Todo-Hook in settings.json,
Panel-Dateien, .desktop — Ordner, memory/ und Claude-Code-Grundgerüst
bleiben), 'archive' löscht zusätzlich das Archiv, 'full' den Projekt-
ordner mit Arbeitsordner-Flag. delete_preview liefert die konkrete
Artefaktliste; der Dialog zeigt sie je Stufe. Ersetzt delete_project/
remove_project (Handler, App-ACL-Manifest und Capability nachgezogen).

Außerdem: main scrollt nicht mehr — Toolbars und Fehlerzeile stehen,
nur die Listen scrollen (alle drei Tabs, .list-scroll).
2026-07-20 13:37:02 +02:00
marcus hinz ab1c561d6c Robustheit: App-Settings-Lesepfad, Pool-Round-Trip, Archiv per create_new
- write_app_setting: nur eine fehlende Datei ergibt ein frisches Objekt;
  unlesbares/kaputtes JSON bricht ab, statt die übrigen App-Settings zu
  verwerfen.
- struct Pool reicht unbekannte Keys per serde(flatten) durch; Umbenennen
  schreibt den gelesenen Bestand zurück.
- Archiv-Dokumente entstehen über create_new (Kollisionsgarantie vom
  Dateisystem statt exists()-Vorabblick — TOCTOU beim Maschinen-Sync).
2026-07-20 13:37:02 +02:00
marcus hinz b743de5f34 Sicherheitsrunde II: PTY-Label, Tool-Grenzen, atomare Schreibvorgänge
- term_start nur noch für das eigene term-<projekt>-Fenster — das
  (abgelöste) Panel-Fenster kann keine Shell mehr starten und beschreiben.
  Die Tauri-ACL greift für App-Commands nachweislich nicht (kein
  __app-acl__-Manifest, Prüfung gegen tauri 2.11.5); die Label-Prüfung
  ist damit die Schranke, nicht deren Verdopplung.
- archive_panel verliert das dir-Argument: Archiv-Home samt dauerhafter
  Rechtevergabe (additionalDirectories + Edit-Allow) setzt nur noch die
  UI mit Nutzer-Dialog, kein Tool-Argument des Modells.
- write_panel(path) liest nur noch aus Projekt-, Arbeits- und
  Archiv-Ordnern (canonicalize, symlink-fest), reguläre Dateien bis 2 MB
  mit hartem Byte-Cap — der promptfreie Weg umgeht das
  Read-Permission-Modell von Claude Code nicht mehr.
- write_atomic (temp + rename) für alle JSON-Config-Schreiber: Projekt-
  Config, .claude/settings.json, Registry, App-Settings, pool.json,
  Pool-settings.json, claudes .claude.json, Todo-Hook.
- write_secret_file: create_new mit 0600 statt schreiben-und-abdichten;
  kein umask-Fenster, Symlinks werden nicht gefolgt.
- PTY-Umgebung: geerbte ANTHROPIC_API_KEY/ANTHROPIC_AUTH_TOKEN entfernt.
- panel_file & Geschwister prüfen die Projekt-ID (zweite Linie).
- Befehlskacheln filtern Bidi-/Zero-Width-Zeichen aus Anzeige und
  Zwischenablage; der Lösch-Abgleich behält den Originaltext.
2026-07-20 12:01:21 +02:00
marcus hinz b9d006184a Projekt-Identität und -Config neu: .ai-control/config.json mit UUID und Name
- Projekt-Config zieht von ai-control.json nach .ai-control/config.json um,
  das Icon liegt daneben und synct mit dem Projekt.
- Jedes Projekt trägt eine UUID (id) und den Anzeigenamen (name) in der
  Config; die UUID ist Registry-Schlüssel und project-Parameter aller
  Commands, der Name reine Darstellung.
- Pool-Zuordnung ist maschinenlokal und liegt in der projects.json-Registry,
  nicht mehr in der syncbaren Projekt-Config.
- open_terminal prüft die ID im Ordner gegen die Registry (verschobene oder
  ersetzte Ordner scheitern laut).
- Import übernimmt eine mitgebrachte ID, legt Arbeitsordner und Archiv-Home
  an und zieht die Archiv-Permission nach.
- Migration beim App-Start: Alt-Datei umziehen, Pool in die Registry,
  Icons aus ~/.config/ai-control/icons ins Projekt, Registry auf UUIDs.
- ProjectConfig reicht unbekannte Keys per serde(flatten) durch den
  Round-Trip (Regressionstest config_roundtrip_erhaelt_fremde_keys).
2026-07-20 11:01:33 +02:00
marcusH 6d44f77671 Sicherheitsrunde: Befehlsinjektion, Pool-Pfad, Namensprüfung, Bild-Beacon
Vier Befunde aus einer Prüfung entlang der Angriffsflächen (MCP-Tools,
Command-Grenze, Credentials, Schreibpfade und Abhängigkeiten):

- todo.rs: Der SessionStart-Hook interpolierte den Projektpfad unquotiert in
  eine Shell-Kommandozeile, die Claude Code bei jedem Sessionstart ausfuehrt.
  Ein Ordner `repo$(...)` -- etwa aus einem geklonten Fremd-Repo -- ergab
  dauerhafte Codeausfuehrung; ein Leerzeichen zerbrach den Hook still.
  Der Pfad wird jetzt gequotet, inklusive Apostroph.
- project_pool_dir: Der Pool-Name kommt aus der ai-control.json im
  Projektordner, also aus einer versionierten Datei. Ungeprueft bestimmte er
  mit ../ ein beliebiges Verzeichnis als CLAUDE_CONFIG_DIR, dessen
  settings.json wiederum apiKeyHelper traegt -- ein Kommando, das beim
  Sessionstart laeuft. Jetzt durch check_name abgesichert.
- check_name: Steuerzeichen, Backslash und fuehrender Punkt werden abgelehnt.
  Ein Newline im Projektnamen hing bisher eigene Schluessel an die .desktop-
  Datei; Exec= braucht keinen Schraegstrich, den der alte Check verbot.
- markdown.ts: Bilder duerfen nur noch lokale Ziele laden. Ein auswaertiges
  <img> laedt ohne Zutun und meldet damit IP, Zeitpunkt und im Pfad kodierte
  Daten -- der Panelinhalt stammt aus einer LLM-Session, ist also
  injizierbar. Schema-relative URLs (//host/x) waren durch ein zu laxes
  Muster erfasst. Links bleiben auswaerts erlaubt, jetzt mit
  rel="noopener noreferrer". escapeHtml escaped zusaetzlich das Apostroph.

Dazu cargo audit nachgeholt: plist 1.9.0 -> 1.10.0 hebt quick-xml auf 0.41.0
und schliesst RUSTSEC-2026-0194/0195 fuer den Laufzeitpfad. Die zweite
Instanz von quick-xml 0.39.4 bleibt ueber wayland-scanner im Lockfile --
ein proc-macro, das nur zur Compile-Zeit laeuft und ausgelieferte
Protokoll-XMLs parst, nicht im Binary landet.

77 Rust-Tests, 39 Frontend-Tests.
2026-07-19 23:47:29 +02:00
marcusH e245600235 Aufräumrunde zur Bugfix-Runde: Suche entzerrt, Flatten-Fix vervollständigt
- archive_search: match_expr in search() aufgelöst. sanitize_query lief zweimal
  pro Anfrage, und die Leer-Entscheidung stand an zwei Stellen mit leicht
  abweichender Bedingung.
- Der Tag-Filter geht jetzt durch dieselbe Quoting-Regel wie der Volltext. Ein
  leerer Tag ergab tags:"" und damit einen Syntaxfehler — erreichbar durch das
  angetippte #, den ersten Tastendruck jeder Tag-Suche.
- sanitize_query von 26 auf 12 Zeilen: split('"') und split_whitespace statt
  handgeschriebenem Tokenizer. Gleiches Ergebnis fuer alle Testeingaben.
- TerminalConfig bekommt ebenfalls serde flatten. Der Block wird als Ganzes
  mitgeschrieben, ein terminal.fontSize waere also weiterhin verloren gegangen;
  set_terminal_config_in traegt die unbekannten Keys jetzt herueber.
- markdown.test.ts enthielt ein literales NUL-Byte, wodurch git die Datei als
  binaer behandelte. Der Test erzeugt das Zeichen jetzt selbst.
- Kleineres: commands_delete-Bedingung als direkter Vergleich, eine
  Verschachtelungsebene in pool.rs, zwei redundante Kommentarbloecke.
  commands_delete benennt sich in der Doku als Provisorium.
2026-07-19 23:22:25 +02:00
marcusH b127269e89 Bugfix-Runde Panel/Archiv: Datenverlust, Suche, Löschen, Markdown
- ProjectConfig reicht unbekannte Keys durch (serde flatten). Bisher verlor
  jeder read-modify-write die Felder neuerer Versionen; so ging archiveHome
  bei der Pool-Zuweisung durch einen älteren Build verloren.
- Archiv-Suche: Nutzereingabe wird in einen FTS5-Ausdruck übersetzt, der nicht
  scheitern kann. ai-control, C++ oder eine halbe Phrase warfen bisher einen
  Syntaxfehler — bei der Live-Suche in jedem Tippzwischenstand.
- commands_delete: Befehlstext als Identität, Indizes werden geprüft. Bisher
  Panik oder Löschen der falschen Kachel, wenn die Panel-Indizes der Datei
  hinterherhingen.
- Archivieren überschreibt keine Datei mehr: Der Stempel hat Minutenauflösung,
  bei Kollision wird -2, -3, ... angehängt.
- archive_panel prüft erst auf leeres Panel, dann wird das Archiv-Home gesetzt;
  bisher blieb ein umkonfiguriertes Home trotz Meldung "nicht archiviert".
- Kaputte .claude.json eines Pools wird nicht mehr durch eine frische ersetzt;
  nur eine fehlende Datei rechtfertigt das.
- Archiv-Formular leert beim Schließen — sonst galten Ordner und Schlagwörter
  des vorigen Dokuments unbemerkt fürs nächste.
- Markdown fürs Panel entschärft (src/markdown.ts): rohes HTML wird als Text
  ausgegeben, Link- und Bildziele auf harmlose Schemata beschränkt. Das Panel
  teilt sich den Webview mit dem Terminal, dessen term_write in die PTY
  schreibt; ohne CSP war das ein Weg von Fremdinhalt zu Befehlsausführung.

Regressionstests je Fix: 73 Rust-Tests, 35 Frontend-Tests.
2026-07-19 23:04:17 +02:00
marcus hinz 286513def8 Refinement-Runde Panel/Wiki: Bedienung, Themes, Archiv-Wahl, Frontend-Tests
- Slug transliteriert Umlaute/ß (fuer statt f-r); aktiver Tab mit Akzent +
  Unterstrich; kein aktiver Tab bei zugeklapptem Panel (mode.clear)
- Suche: Live-Update auch beim Löschen (<3 Zeichen: Hinweis), #tag-Filter in
  der Query, Treffer öffnen im Dokument-Tab (panel_load, ohne Frontmatter);
  Wiki-Sprung-Button im Dokument; Wiki-Fehler sichtbar als Toast
- Archiv-Formular am Archiv-Button (Ordner/Beschreibung/Schlagwörter);
  panel_archive_cmd nimmt Meta entgegen
- Wiki-Übersicht: Zuletzt-Sektion, Backlink-Zähler, Wurzel-Eyebrow
- Themes: Panel-Farben über CSS-Variablen, applyTheme leitet sie aus dem
  jeweiligen Theme ab (auch helle); gemeinsames themes.ts
- Fenster: Doppelklick maximiert; gelöstes Fenster merkt Größe/Position
  (Window-ACL: set-position/outer-position/inner-size ergänzt);
  open_panel_window async (GTK-Deadlock-Vorgabe); Panel-Fenster spiegelt
  JS-Fehler ins Dev-Log
- Archiv pro Projekt wähl-/abwählbar (Einstellungsdialog, setzt/entfernt
  Permissions); require_archive_home legt den Ordner an; ohne Archiv nur
  Befehle+Dokument im Panel
- Frontend-Tests: vitest + happy-dom, 27 Tests über Modus-, Such-, Wiki-,
  Editor- und Formular-Logik (npm test)
2026-07-19 17:08:05 +02:00
marcus hinz 994d5070f0 Archiv-Wiki im Panel: vier Tabs, FTS5-Suche, strukturierbares Archiv
- Archiv-Home pro Projekt (archiveHome in ai-control.json); archive_panel
  mit Ordner, Beschreibung und Schlagwörtern (Frontmatter + Zeitstempel-Stem)
- Archiv-Index (archive_index.rs): Scan mit Frontmatter, Wikilinks,
  Backlinks; Wiki-Seiten als strukturierte Daten (Übersicht/Tag-Seiten)
- FTS5-Suche (archive_search.rs, rusqlite bundled): in-memory-Index pro
  Anfrage; MCP search_archive und Panel-Suchfeld (search_run) teilen die Engine
- Panel: vier Puffer/Ansichten (Dokument, Befehle, Suche, Wiki) mit Tabs im
  Fenster-Header; gemeinsame Verdrahtung panel-wiring.ts, Kachel-CSS,
  Wiki-View mit Tag-Chips, Ordner-Sektionen und Backlinks
- Archivieren speichert offene Bearbeitung (flush); Tab-Wechsel speichert
  statt zu blockieren; Fehler sichtbar als Panel-Toast
- Abgelöstes Fenster: rahmenlos (Linux), eigene Kopfleiste mit Tabs und
  Fensterknöpfen, Theme-Kopplung über gemeinsames themes.ts
- MCP-Tools show_commands, show_archive; Befehls-History mit Kachel-Löschen
2026-07-19 15:25:40 +02:00
marcus hinz 9a99bca466 Modul-Split: Fachlogik nach domain/, OS-Code nach platform/, Tauri-Verdrahtung in app.rs/commands.rs
- lib.rs nur noch Prozessrollen-Dispatch + Panic-Tracer
- KWin-Script als KDE-Pendant zur GNOME-Extension (Popup ans Zeiger-
  Rechteck), wird von deb/rpm mit ausgeliefert
- SNI-Tray auf ksni (pure Rust), appindicator-Depends entfallen
2026-07-15 20:10:33 +02:00