Files
claude-ai-control/archive/design/2026-07-22_1626-modul-system-fuer-aicentral-entwurf.md
2026-07-24 21:42:30 +02:00

9.7 KiB
Raw Permalink Blame History

title, project, created, source, description, tags
title project created source description tags
Modul-System für aICentral — Entwurf ai-control 2026-07-22T16:26:08Z ai-control Modul-System für aICentral: Deskriptoren, Registry, Enablement, Migration in 5 Schritten, Plugin-Ausblick
design
module
plugin
panel
architektur

Modul-System für aICentral — Entwurf

Stand 2026-07-22. Grundlage: panel-wiring.ts, commands-view.ts, mcp.rs, terminal.rs, app.rs, domain/project.rs (Stand 513e1a7).

1. Ziel und Abgrenzung

Alle Panel-Funktionen werden zu- und abwählbare Module; die anstehenden Features (ToDo-Liste, Commit-Dialog, Archiv-Ausbau, Authoring-Ansicht) entstehen direkt als Module. Ein System für fremde Plugins (zur Laufzeit geladener Code) wird jetzt nicht gebaut — der Entwurf legt aber die Schnittstellen so, dass es später ohne Umbau andockt (Abschnitt 9).

2. Bestandsaufnahme — was schon Modulform hat

Die vier Panel-Ansichten folgen bereits einem einheitlichen Muster, es ist nur nicht als Schnittstelle benannt:

Baustein draft commands search wiki
Pufferdatei (Env an MCP) AI_CONTROL_PANEL …_COMMANDS …_SEARCH …_WIKI
Watcher-Event panel-update commands-update search-update wiki-update
View-Interface set/flush set/empty set/empty set/empty
Read-Command panel_read commands_read search_read wiki_read
MCP-Tools write_panel write/show_commands search_archive show_archive, archive_panel

Der Datenfluss ist überall gleich: MCP-Server oder Command schreibt die Pufferdatei → Datei-Watcher im Terminal-Prozess emittiert <x>-update → View rendert. Es gibt auch schon ein abwählbares Modul: archiveHome: null blendet Wiki-/Suche-Tab und Archiv-Werkzeuge aus (panel-wiring.ts:45). Das Modul-System verallgemeinert genau diese zwei Präzedenzfälle.

3. Modulbegriff

Ein Modul ist ein benannter Funktionsblock mit bis zu vier Beiträgen:

  1. Panel-Tab mit View (Kachel- oder Dokumentansicht)
  2. MCP-Tools (Angebot an claude)
  3. Pufferdatei + Watcher-Event (der Transportweg dazwischen)
  4. optional Fenster/Dialoge (z. B. Commit-Dialog)

Geplanter Zuschnitt:

Modul Tab MCP-Tools abwählbar
draft (Entwurf) ja write_panel nein — Kern
commands ja write_commands, show_commands ja
archive Wiki + Suche archive_panel, show_archive, search_archive ja (heute: archiveHome)
todo (neu) ja write_todos, show_todos ja
commit (neu) nein, eigener Dialog ja
authoring (später) ja ja

draft bleibt Kern: Titel, Editier-Modus, flush und das Archivieren hängen daran; ohne Entwurf ist das Panel leer. Alles andere ist abschaltbar.

4. Backend: Deskriptoren und eine Durchsetzungsstelle

Neu domain/modules.rs:

pub(crate) struct ModuleDesc {
  pub id: &'static str,               // "commands", "todo", ...
  pub default_enabled: bool,
  /// Modul setzt ein konfiguriertes archiveHome voraus.
  pub requires_archive: bool,
  pub mcp_tools: &'static [&'static str],
  /// Pufferdatei-Name im Projekt-Runtime-Ordner, None = kein Puffer.
  pub buffer: Option<&'static str>,
}
pub(crate) const MODULES: &[ModuleDesc] = &[ /* draft, commands, archive, todo, … */ ];

/// Die eine Quelle für „was ist in diesem Projekt an?“.
pub(crate) fn enabled_modules_in(paths: &Paths, project: &str)
  -> Result<Vec<&'static str>, String>

enabled_modules_in = MODULES, gefiltert durch Projekt-Config und requires_archive (Archiv-Module fallen ohne archiveHome automatisch weg — das ersetzt die heutige Sonderbehandlung, statt eine zweite daneben zu stellen). Genau drei Aufrufer:

  1. Tauri-Command enabled_modules(project) — das Frontend fragt einmal beim Verdrahten.
  2. mcp.rs tools/list — die Tool-Liste wird aus MODULES[…].mcp_tools der aktiven Module gebaut (Projekt kommt wie heute über AI_CONTROL_PROJECT). claude sieht Tools abgeschalteter Module gar nicht erst.
  3. mcp.rs tools/call — Guard vor dem Dispatch: Tool eines inaktiven Moduls → Fehler „Modul X ist in diesem Projekt abgeschaltet". Nötig, weil eine laufende claude-Session die Tool-Liste vom Start behält.

Verallgemeinert wird außerdem:

  • terminal.rs: die vier spawn_file_watcher-Zeilen werden eine Schleife über die aktiven Module mit Puffer; Event-Name per Konvention <id>-update, Env-Name AI_CONTROL_<ID>.
  • Read-Commands: panel_read/commands_read/search_read/wiki_read verschmelzen zu module_read(project, module) (alle vier sind „Pufferdatei als String"). panel_set bleibt eigenständig, es ist der einzige Rückkanal.

Statisch bleiben: generate_handler! (Commands aller Module sind kompiliert registriert; Abwahl wirkt auf Sichtbarkeit und Tools, nicht auf die IPC-Registrierung), die Capability-Manifeste pro Fenster und die CSP. Die Modul-Abwahl ist Konfiguration, keine Sicherheitsgrenze — dieselbe Linie wie bei den Pools (Konfiguration trennen, nicht Zugriff).

5. Frontend: Registry statt Verdrahtung von Hand

Neu src/modules/ mit einem Deskriptor pro Modul:

export interface PanelModule {
  id: string;
  tabLabelKey: string;          // i18n-Key
  order: number;                // Tab-Reihenfolge
  init(container: HTMLElement, ctx: ModuleCtx): ModuleView;
  /// Kopfzeilen-Werkzeuge des Moduls (z. B. Archivieren-Button).
  headerTools?(ctx: ModuleCtx): HTMLElement[];
}
export interface ModuleView { set(text: string): void; empty(): boolean; }
export interface ModuleCtx {
  project: string;
  toast(msg: string): void;
  openDoc(path: string): void;  // Dokument in den Entwurfs-Tab laden
  openWiki(name: string): void;
}

panel-wiring.ts wird generisch: enabled_modules abfragen, pro Modul Tab + Container erzeugen, module_read laden, <id>-update abonnieren, initPanelMode über die Modulliste statt über vier feste Felder. Die PanelMode-Union und die archiveHome-Ausblendelogik entfallen. Die HTML-Dateien verlieren die fest verdrahteten Tab-/Container-Elemente; beide Panel-Markups (angedockt/abgelöst) entstehen aus derselben Registry.

Kachel-Renderer als gemeinsamer Baustein: commands-view.ts wird in einen deklarativen Tile-Renderer zerlegt (Titel/Text/Note, Zeitmarke, Aktionen kopieren/löschen/öffnen, optionales Badge). Commands, ToDo (Due-Date-Ampel = Badge) und Suchtreffer rendern darüber — die ToDo-Ansicht „analog commandlist" ist dann im Wesentlichen ein Puffer-Format plus Badge-Logik. Das Sanitizing (stripInvisibles, kein innerHTML) liegt damit an einer Stelle.

6. Konfiguration

Projekt-Config (.ai-control/config.json) bekommt:

{ "modules": { "commands": false, "todo": true } }

Nur Abweichungen vom Default werden gespeichert; fehlender Key = alle Defaults (bestehende Configs bleiben unverändert gültig, kein Migrationsschritt). archiveHome bleibt eigenständiges Feld — es ist Pfad-Konfiguration, das Archiv-Modul hängt über requires_archive daran. Ein Eintrag "archive": false schaltet das Modul trotz gesetztem archiveHome ab.

Settings-UI: im Projekt-Dialog eine Checkbox-Gruppe „Module" aus MODULES generiert; Archiv-Zeile kombiniert Checkbox + Pfadwahl (heutige Archiv-Einstellung wandert dorthin). Änderungen wirken beim nächsten Panel-Aufbau; eine laufende claude-Session behält ihre Tool-Liste, der tools/call-Guard fängt das ab.

7. Migration in Schritten

  1. domain/modules.rs + enabled_modules + tools/list/call aus MODULES speisen — reine Umformung, Verhalten identisch.
  2. Frontend-Registry: die vier Bestands-Views als Deskriptoren, panel-wiring generisch, archiveHome-Sonderlogik durch requires_archive ersetzen. Bestehende vitest-Tests laufen gegen die Deskriptoren weiter.
  3. Kachel-Renderer aus commands-view extrahieren, Suche darauf umstellen.
  4. Settings-UI mit Modul-Checkboxen + modules-Feld in der Config.
  5. Erstes neues Modul: ToDo — validiert den Schnitt komplett (Deskriptor, Puffer, zwei MCP-Tools, Tile-Renderer mit Badge), ohne eine Zeile Sonderverdrahtung.

Schritte 13 sind Refactoring ohne Funktionsänderung und einzeln committbar; ab Schritt 4 wird das System sichtbar.

8. Auswirkung auf die geplanten Features

  • ToDo: Modul nach Schema F (Schritt 5), Aufwand fast nur Puffer-Format und Badge.
  • Commit-Dialog: Modul ohne Tab — Beitrag ist ein Fenster samt Capability-Datei; die Abwahl blendet den Einstieg (Menü/Button) aus. Zeigt, dass der Modulbegriff nicht am Panel klebt.
  • Archiv-Ausbau: Seitennavigation, Metadaten, Ordnerverwaltung wachsen im Archiv-Modul, dessen Grenze (requires_archive, drei MCP-Tools, zwei Tabs) dann schon gezogen ist.
  • Authoring-Ansicht: bekommt mit der Registry eine definierte Andockstelle statt weiterer Handverdrahtung in zwei HTML-Dateien.

9. Ausblick fremde Plugins — drei Stufen, Empfehlung Stufe 2

  1. Kompilierte Module (dieser Entwurf): Code im Repo, Registry statisch.
  2. Prozess-Plugins: ein externes Programm liefert einen Deskriptor (JSON-Manifest: id, Label, Tile-Schema, MCP-Tool-Definitionen) und schreibt Pufferdateien im Tile-Format; die App rendert deklarativ und reicht Tool-Calls per stdio durch — dasselbe Muster, mit dem claude heute schon angebunden ist. Kein Fremdcode im Webview, Isolation = Prozessgrenze, CSP und ACL bleiben unangetastet.
  3. Geladener UI-Code (JS/WASM im Webview): verworfen — hebelt CSP (style-src 'self' ohne unsafe-inline) und das App-ACL-Manifest aus und schafft genau die Angriffsfläche, die die Sicherheitsrunden geschlossen haben.

Der Entwurf hält Stufe 2 offen, ohne sie zu bauen: Deskriptor, Tile-Format und Puffer/Event-Konvention sind bereits die Plugin-API — später kommt nur ein Loader dazu, der Deskriptoren aus Manifesten statt aus dem Repo bezieht.