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.
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.
write_commands vergibt jedem Eintrag eine UUID; commands_delete löscht
darüber. Doppelklick oder ein zweites Fenster laufen ins 'bereits
entfernt' statt auf verschobene Indizes.
- 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.
- 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).
- 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.
- 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.
- 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)
- 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
- 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
- Archiv pro Projekt: Panel-Button „Archivieren" und MCP-Tool archive_panel
legen den Entwurf als <YYYY-MM-DD_HHMM>-<slug>.md mit Frontmatter im
Archiv-Ordner ab. Ordner in ai-control.json (archiveDir) + als
additionalDirectories/Edit in .claude/settings.json (scanbar). Kein Ordner:
Panel öffnet Ordner-Dialog, Zuruf nutzt Argument dir.
- Panel-Titel zeigt die erste Überschrift des Entwurfs (Inline-Markdown
gestrippt), Fallback „Entwurf"; Bleistift-Button macht ihn editierbar,
schreibt die Überschrift via panel_set zurück.
- Panel-Kopf zweizeilig: Titel + Edit oben, Aktionen rechtsbündig darunter.
- AI_CONTROL_PROJECT als PTY-Env für den MCP-Server.
- Andockbares Panel im Terminal-Fenster: Markdown-Rendering, Copy-Button,
normale Selektion; in eigenes Fenster ablösbar und wieder andockbar
(Splitter, panel-detached/panel-attached).
- MCP-stdio-Server (app --mcp-panel) mit Tool write_panel; schreibt in die
Datei aus AI_CONTROL_PANEL, Watcher zieht sie ins Panel.
- Provisionierung je Pool: Server-Registrierung in .claude.json (alwaysLoad),
Freigabe mcp__text-panel__write_panel in settings.json, Panel-Skill; bei
App-Start (alle Pools) und Pool-Anlage. Alte tee-Freigaben werden entfernt.
- Capability deckt panel-*-Fenster ab.
- Popup als rahmenloses Fenster mit D-Bus-Relay (popup.html/ts, Popup.vue);
GNOME-Extension schiebt es unter den Panel-Button
- Terminal: globale Schriftgröße via settings.json (terminalFontSize),
Zoom mit Ctrl/Cmd +/-/0 im Terminal
- trayLinux-Icon, Capabilities, App.vue/terminal.html angepasst
- Ghostty komplett entfernt: bundle_id/ghostty_running/open_project/start_project
weg, is_running nur noch über terminal_pids; restart_project über das interne
Terminal (kill_terminals + open_terminal) statt osascript-Quit
- Session-Watcher im Tray-Prozess: synct das claude-projects-Repo bei
Session-Ende (Prozess verschwindet, greift auch bei HUP/Kill)
- Sync als Opt-in (~/.config/ai-control/settings.json, default aus) und nur
wenn ein Git-Repo vorhanden ist; Commands sync_setting/set_sync_setting
- Löschen-Button in der Pool-Übersicht gesperrt bei laufendem Projekt, Grund per
CSS-Hover-Pop (WKWebView zeigt keine nativen title-Tooltips)
- Terminal-Einstellungen pro Projekt in ai-control.json: 5 Themes
(Paletten in terminal.ts, Fenster-BG gespiegelt in terminal.rs),
Dock-Icon (PNG/ICNS via NSApplication in RunEvent::Ready),
Fenstertitel mit Fallback Projektname; Zahnrad-Dialog mit Datei-Picker
(tauri-plugin-dialog)
- UI: Catppuccin-Mocha-Token, JetBrains Mono für Namen/Pfade/Chips,
feste Tabellenspalten, Status-Punkt mit Glow, Pool-Projekte als
Hover-Popover, Buttons ausgerichtet (Zahnrad links von Starten/Beenden)
- i18n: vue-i18n, Deutsch/Englisch, Umschalter im Header (localStorage)
- generate_context nur noch einmal expandiert (Release-Build-Fehler)
- Terminal-Fenster als eigener Prozess (--terminal <projekt>) mit eigener PTY,
startet claude-sync im Projektordner
- Projektliste: ein Button pro Zeile — grün Starten (open_terminal) bzw.
rot Beenden (stop_project, SIGTERM auf exakte PID / Ghostty-Quit)
- is_running erfasst Ghostty oder laufenden Terminal-Prozess
- Status-Kreis ohne Prozess unsichtbar