Files
ClawdDotNet/docs/Roadmap.md
T
RichardandClaude Opus 5.5 6d81693041 Stufe 3 (#764): Avalonia-Fenster entfernt
- Views, ViewModels, Controls, Converters, Styles, Services, Desktop-i18n,
  Schriften und App.axaml raus; Avalonia- und Mvvm-Pakete raus
- ClawdDotNet ohne Schalter: Manager starten (unter systemd ueber den Dienst,
  nie doppelt) und WebUI oeffnen (LauncherRun) - bis die Huelle kommt
- Instanzen laufen immer kopflos; instanceWindows wird gelesen, nicht mehr
  ausgewertet; die Kette 'Fenster nach vorn holen' ist entfernt
- Telegram-Anmeldung nur noch ueber die WebUI (tote Dialog-Rueckrufe raus)
- systemd-Vorlagen im Linux-Paket; Oberflaechen-Leitfaden ins Archiv

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 20:23:12 +02:00

919 lines
56 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ClawdDotNet — Roadmap
**Der Stand steht nicht mehr in dieser Datei.** Er steht im
[Deploymentcenter](https://dc.mhdf.de), seit dem 2026-08-30. Was hier zwischen
den `dc:roadmap`-Markern steht, ist eine **erzeugte Kopie** und darf älter sein
als der echte Stand — sie kommt von `deploy/roadmap/roadmap_block.py --write`
und wird bei jedem Lauf überschrieben. Dort niemals von Hand etwas ändern.
Was diese Datei behält, ist die Hälfte, die eine Tabellenzelle nie getragen
hat: **warum** etwas so entschieden wurde, woran ein Zurückgestelltes wieder
ansteht, und woher die Reihenfolge kommt. Verbunden ist beides über die
Item-Nummer.
| | Wahrheit | Die andere Seite hält |
|---|---|---|
| Status, Reihenfolge, Zielfassung, Bearbeiter | **Deploymentcenter** | eine erzeugte Kopie zwischen Markern |
| Begründung, Auslöser, Herleitung | **diese Datei** | einen Verweis (`doc_anchor`) |
Der Live-Stand kommt aus `dc_roadmap` — **mit `project_slug: "clawddotnet"`**,
solange Item 176 unter `deploymentcenter` offen ist. Ein Vorhaben, das etwas werden
soll, entsteht als Item über `dc_report` und wird mit `dc_roadmap_set`
eingeplant; *danach* schreibt man die Begründung hierher. So kann ein Punkt,
der nur in einer Datei steht, gar nicht erst entstehen.
Wo die alten Papiere geblieben sind, steht in Abschnitt 5.
---
## 0 — Stand
Der Kern trägt. Engine, Taskboard, Audit, Gedächtnis, Budget, Sicherung und die
Oberfläche sind gebaut und getestet, der Build ist fehlerfrei, in den Paketen sind
keine Sicherheitslücken bekannt. Die Sicherheitsbefunde S1–S7 und die Bugs B1–B5, B11,
B12 aus der Bestandsaufnahme sind abgearbeitet — sie stehen als erledigte Items im
Block unten.
> **Die „585 Tests grün" standen hier ohne Plattform — und das war der Fehler.** Sie
> stammen von Windows. Auf der Zielplattform sind es am 2026-08-31 **587 von 591
> grün, drei rot**. Zwei der drei sind mit `[LinuxFact]` markiert und laufen unter
> Windows gar nicht erst; sie decken genau die Symlink-Grenze ab, die #373 aufgemacht
> hat. Eine Zahl ohne die Maschine, auf der sie entstand, sagt hier nichts mehr —
> gemessen wird ab jetzt auf der Test-VM (siehe
> `Deploymentcenter/docs/TESTUMGEBUNG.md`).
**Zielbetrieb (festgelegt am 2026-08-23):** Linux, ausschließlich. Eine Maschine mit
Desktopumgebung (Ubuntu Desktop), 24/7 durchlaufend, die Avalonia-Oberfläche läuft
immer mit — zum Konfigurieren, Überwachen und Freigeben. Windows ist keine Zielplattform
mehr; die vorhandenen Windows-Zweige bleiben vorerst nur als **Migrationspfad** stehen
(siehe #190). Das ändert die Reihenfolge und macht aus einem bekannten Randfall einen
Blocker.
**Davor stehen zwei kritische Befunde** (Bereich `FIX`, Ränge 1 und 2). Sie sind neu
und gehen allem anderen vor: Die Workspace-Grenze hält beim Schreiben nicht, was sie
zusagt (#373), und das eingestellte Log-Verzeichnis ist wirkungslos, weil ein relativer
Pfad gegen das Arbeitsverzeichnis aufgelöst wird (#375). Beide sind auf der
Zielplattform gefunden worden, beide sind unter Windows nicht sichtbar. Die Herleitung
steht in Abschnitt 3.
Danach stehen vier Dinge im Weg:
1. **Auf Linux liegt der Hauptschlüssel im Klartext** (#190). Alles, was **neue**
Zugangsdaten anzieht — MCP-Konnektoren, Browser-Logins —, steht dahinter.
2. **Die Freigabe-Ansicht fehlt** (#191). Staging ist gebaut und greift — aber
niemand kann freigeben. Damit ist der unbeaufsichtigte Betrieb, für den das
ganze Vorhaben da war, nicht möglich.
3. **Die Chat-Frage ist unentschieden** (#181). Rocket.Chat ist gebaut und bedient
denselben Zweck, für den Matrix vorgesehen war. Solange das offen ist, hängen
Streaming, der Notfallkanal und ein Teil des Spiegels in der Luft.
4. **Agenten können sich gegenseitig verklemmen** (#206). `AgentComm.send_message`
hat keine Tiefenbegrenzung; A→B→A blockiert bis zum Timeout. Bekannt seit Juli,
unverändert.
### Der Vergleich mit Grok Bot
Am 2026-08-23 gegen xAIs Grok Bot gehalten (Cloud-VM mit eigenem Browser, Terminal,
MCP, acht Office-Konnektoren, Freigabe-Gates, Mehr-Bot-Betrieb). Ergebnis in einem Satz:
Der Vorsprung liegt ausschließlich in der **Reichweite in die Welt** — Browser, Shell,
MCP, Vision. In allem, was entscheidet, ob man so etwas unbeaufsichtigt laufen lässt,
liegt ClawdDotNet vorn und teilweise dort, wo Grok Bot nichts hat: Audit mit gestempelter
Herkunft, Receipts, Kosten pro Lauf, Budget-Guard, ein Gedächtnis, das man einsehen,
korrigieren und sichern kann, Modellfreiheit über OpenRouter, Workspace-Trennung je Agent
(Grok Bot teilt sich ausdrücklich *einen* Computer über alle Bots), Selbstbetrieb.
Telegram und Rocket.Chat sind als Fernbedienung mehr, als Grok Bot anbietet.
Die vier Lücken sind als #196 (Shell), #197 (MCP), #199 (Vision) und #200 (Browser)
aufgenommen. Die Leitlinie bleibt unverändert: **erst Bremsen, dann PS.** Mehr Reichweite
ohne Freigabe-Ansicht und ohne dichte Schlüsselablage wäre genau der falsche Tausch.
### Der zweite Vergleich: OpenClaw 2.0 und Grok Bot
Am 2026-09-18 erneut gehalten, diesmal gegen OpenClaw 2.0 (30.08.) mit v2026.9.1 und
gegen Grok Bot nach der allgemeinen Freigabe (11.08.). Die vier Reichweiten-Lücken sind
unverändert offen. Neu ist, dass beide **in der Bedienung** vorn liegen: Grok Bot legt
Freigaben als Karte in den Chat und fasst liegengebliebene Arbeit von selbst nach,
OpenClaw hat Selbstdiagnose (`doctor`), Update-Probelauf, sichtbar blockierte Kanäle
und Skills als eigene Sammlung je Agent. Die Warnsignale sind lauter geworden
(ClawHub-Schadskills, Verbot in chinesischen Behörden, Sandbox-Kritik auch an 2.0;
Grok Bot teilt ausdrücklich einen Rechner und dieselben Zugangsdaten über alle Bots) —
die Leitlinie bleibt.
Übernommen, jeweils mit Begründung in Abschnitt 3:
| | Vorbild | Vorhaben |
|---|---|---|
| #644 | Grok Bot: Freigabe-Karten im Chat | Freigabe per Button aus Rocket.Chat und Telegram, über eine **austauschbare Kanal-Schnittstelle** |
| #645 | OpenClaw: blockierte Kanäle mit Behebungshinweis | Kanalzustand sichtbar, unklare Zustellungen ausdrücklich |
| #646 | Grok Bot: „nudge stalled work" | Taskboard fasst nach |
| #647 | Grok Bot: Übergabe zwischen Bots | Delegation an einen oder mehrere Agenten |
| #648 | OpenClaw: `doctor`, Probeantwort vor dem Aktivieren | Selbstdiagnose und Modell-Probeantwort |
| #649 | — (Nutzerwunsch) | Probelauf neuer Agenten für Personalmanager-Agenten |
| #198 | Grok Bot: Skill aus erfolgreichem Ablauf | Zuschnitt erweitert: Skill-Format und Skill-Entwurf nach Freigabe |
| #197 | Composio als Grok-Bot-Plugin | MCP vor Shell gezogen |
Nicht übernommen: offener Skill-Marktplatz, ein gemeinsamer Rechner für alle Agenten,
geteilte Sitzungen zwischen mehreren Menschen (das Bedrohungsmodell ist intern),
Handy-App und Sprache. Streaming (#557) bleibt zurückgestellt — der Vergleich liefert
keinen seiner drei Auslöser.
### Sicherheit: vier Schichten statt eines Wächters
Am 2026-09-19 aus dem Vergleich weitergeführt. Anlass: Agenten sollen eigene Skripte
schreiben dürfen, und heute ist die Workspace-Grenze nur C#-Code im selben Prozess. Die
Grenze macht das Betriebssystem (Sandbox-Runner #654), deterministische Regeln und
Detektoren tragen den Rest (#651–#653, #659), ein Security-Agent (#658) bewertet nur auf Anlass
und mit hartem Budget. Herleitung und Bauplan: [Security-Konzept](Security-Konzept.md).
---
## 1 — Stand aus dem Deploymentcenter
<!-- dc:roadmap stand=2026-09-19T12:03Z items=122 projekt=clawddotnet -->
<!-- ERZEUGT - nicht von Hand aendern. Dieser Block wird bei jedem Lauf von
`php cli/roadmap.php --write` ueberschrieben. Der Zustand wird im
Deploymentcenter gepflegt, nicht hier. Prosa gehoert AUSSERHALB der
Marker - dort bleibt sie unberuehrt. -->
### Als Naechstes
1. **[DEC] #180 — E10 entscheiden: Womit wird der Hauptschluessel unter Linux gebunden?**
2. **[SEC] #190 — L1: Der Hauptschluessel liegt unter Linux im Klartext**
3. **[FIX] #529 — Instanzwechsel haengt die Anwendung auf: Windows beendet sie mit AppHangB1**
4. **[SEC] #191 — Freigabe-Ansicht: gestagte Aufrufe sichtbar machen und freigeben**
### FIX — Kritische Befunde — vor allem anderen
| | Vorhaben | Stand | Ziel |
|---|---|---|---|
| #373 | PathBoundary.Canonicalize bricht bei nicht existierendem Pfadabschnitt ab - Symlink-Schutz greift beim Schreiben nie | ✅ Erledigt | `cffd6f4` |
| #375 | Log-Verzeichnis aus den Einstellungen wird ignoriert - instance.logDirectory './Logs' gewinnt und wird gegen das Arbe... | ✅ Erledigt | `cffd6f4` |
| #529 | Instanzwechsel haengt die Anwendung auf: Windows beendet sie mit AppHangB1 | 📋 Offen | — |
### DEC — Offene Entscheidungen
| | Vorhaben | Stand | Ziel |
|---|---|---|---|
| #180 | E10 entscheiden: Womit wird der Hauptschluessel unter Linux gebunden? | 📋 Offen | — |
| #181 | E1 entscheiden: Matrix oder Rocket.Chat? | 📋 Offen | — |
| #182 | E4 entscheiden: ask_agent behalten oder ersatzlos streichen? | 📋 Offen | — |
| #183 | E2 entscheiden: Nextcloud-Identitaet - Dienstkonto oder Benutzer je Agent? | 📋 Offen | — |
| #184 | E3 entscheiden: Oeffentliche Freigabe-Links erlauben oder hart sperren? | 📋 Offen | — |
| #185 | E5 entscheiden: Notfallkanal-Reihenfolge instanzweit oder je Agent? | 📋 Offen | — |
| #186 | E6 entscheiden: catchUp je Task abschaltbar machen? | 📋 Offen | — |
| #187 | E7 entscheiden: Prioritaet bei mehreren faelligen Tasks - strikt oder gewichtet? | 📋 Offen | — |
| #188 | E8 entscheiden: Aufbewahrungsdauer der Agentenkommunikation | 📋 Offen | — |
| #189 | E9 entscheiden: Automatische Orderausfuehrung - ueberhaupt? | 📋 Offen | — |
### SEC — Kontrolle und Sicherheit
| | Vorhaben | Stand | Ziel |
|---|---|---|---|
| #190 | L1: Der Hauptschluessel liegt unter Linux im Klartext | 📋 Offen | — |
| #191 | Freigabe-Ansicht: gestagte Aufrufe sichtbar machen und freigeben | 📋 Offen | — |
| #651 | Herkunftsregel: Lauf nach Fremdinhalt belastet - danach jede Aktion mit Aussenwirkung freigabepflichtig | 📋 Offen | — |
| #652 | Befunde und Quarantaene mit zwei Stufen: niedrig = Vorschlag per Messenger, hoch = sofort und nur in der Oberflaeche ... | 📋 Offen | — |
| #653 | Regelbasierte Detektoren ueber das Audit und Koederwerte (Canaries) in Workspace und Schluesselbund | 📋 Offen | — |
| #659 | Belastung wandert mit: Gedaechtnis, Skill-Entwuerfe und Tasks aus belasteten Laeufen tragen die Herkunftsmarke weiter... | 📋 Offen | — |
| #192 | Output-Scrubbing: Secret-Werte zentral aus allen Tool-Ergebnissen maskieren | 📋 Offen | — |
| #654 | Sandbox-Runner (bwrap): jede Codeausfuehrung ausserhalb des Hauptprozesses - Voraussetzung fuer Skripte, Shell und MC... | 📋 Offen | — |
| #655 | Netzprofil je Agent: Websuche des Modells, Anbieter-Datennutzung und Sandbox-Netz einzeln einstellbar | 📋 Offen | — |
| #657 | Skriptpruefung: Agenten schreiben eigene Skripte, ausgefuehrt wird nur die freigegebene Fassung (Hash-gebunden, jede ... | 📋 Offen | — |
| #193 | Tool-Ergebnisse als untrusted content rahmen | 📋 Offen | — |
| #194 | Secret-UI: Zugangsdaten setzen und rotieren | 📋 Offen | — |
| #658 | Security-Agent: eingeschraenktes Profil des AgentInspector - Befunde bewerten, Skripte einschaetzen, taegliche Stichp... | 📋 Offen | — |
| #237 | Audit-Log und Receipts (A3, F-A2) | ✅ Erledigt | — |
| #238 | Staging-Kern (A2, F-A1, S4) | ✅ Erledigt | — |
| #249 | S1: SqlGuard statt Teilzeichenketten-Pruefung | ✅ Erledigt | — |
| #250 | S2: YouTubeUrl und ArgumentList gegen Options-Injection | ✅ Erledigt | — |
| #251 | S3: UrlSanitizer gegen API-Key-Leak ins Modell | ✅ Erledigt | — |
| #252 | S5: UrlGuard, Redirects einzeln geprueft | ✅ Erledigt | — |
| #253 | S6: WorkspacePath auf Verzeichnisgrenzen | ✅ Erledigt | — |
| #254 | S7: SecretProtector mit DPAPI | ✅ Erledigt | — |
| #255 | K5: Budget-Guard (F-A3) | ✅ Erledigt | — |
### CAP — Agenten-Faehigkeiten
| | Vorhaben | Stand | Ziel |
|---|---|---|---|
| #195 | FileRW-Papierkorb statt endgueltigem Loeschen | 📋 Offen | — |
| #646 | Taskboard fasst nach: festhaengende und liegengebliebene Tasks erkennen und ueber den Kanal melden | 📋 Offen | — |
| #647 | Delegation an einen oder mehrere Agenten: Task gezielt verteilen, Teilaufgaben je Agent, Sammel-Task wartet auf alle | 📋 Offen | — |
| #197 | L5: MCP-Client fuer stdio- und HTTP-Server | 📋 Offen | — |
| #196 | L4: Shell-Tool mit echter Sandbox | 📋 Offen | — |
| #198 | A4: Skills und Toolsets - dreischichtiger Prompt statt "alles immer" | 📋 Offen | — |
| #199 | L6: Vision - Bild-Content-Blocks im OpenRouterClient | 📋 Offen | — |
| #200 | L7: Browser-Tool mit Live-Ansicht | 📋 Offen | — |
| #201 | Memory-Flush vor der Compaction | 📋 Offen | — |
| #202 | Memory-Auto-Injection relevanter Abstracts | 📋 Offen | — |
| #203 | Die Compaction laeuft nach dem API-Aufruf - der ueberfuellte Prompt ist da schon bezahlt | ✅ Erledigt | `cffd6f4` |
| #204 | AgentInspector: ein Supervisor-Agent, der die anderen beurteilen kann | 📋 Offen | — |
| #205 | AgentEditor haerten: Aenderungen an Identity.md und Soul.md freigabepflichtig | 📋 Offen | — |
| #649 | Probelauf fuer neue Agenten: Werkzeug fuer Personalmanager-Agenten, einen neu angelegten Agenten vor der Inbetriebnah... | 📋 Offen | — |
| #239 | Taskboard (A1, F-A4, F-A5) | ✅ Erledigt | — |
| #240 | Langzeitgedaechtnis (K1) | ✅ Erledigt | — |
| #256 | B1 und B14: Compaction mit sicherem Schnittpunkt, kein doppelter System-Prompt | ✅ Erledigt | — |
| #257 | B2: Chat-Laeufe je Agent serialisiert | ✅ Erledigt | — |
| #258 | B3 und T5: maxCumulativeTokens von maxContextTokens getrennt | ✅ Erledigt | — |
| #259 | B4: Prompt und Completion getrennt erfasst, Preise live vom /models-Endpunkt | ✅ Erledigt | — |
| #260 | B5 und T2: Tool-Ergebnisse zentral gekappt | ✅ Erledigt | — |
| #261 | B6 und B7: gegenstandslos, seit der Scanner die Delay-Schleifen ersetzt | ✅ Erledigt | — |
| #262 | B11 und T8: max_tokens aus LoopGuard.MaxResponseTokens | ✅ Erledigt | — |
| #263 | B12: Retry mit Backoff fuer 429 und 5xx | ✅ Erledigt | — |
| #264 | T1 und T9: Prompt-Caching mit Breakpoints, cached_tokens gemessen | ✅ Erledigt | — |
| #265 | T3: guenstiges Modell fuer die Zusammenfassung | ✅ Erledigt | — |
| #266 | T7: durch die Assignee-Semantik des Taskboards beantwortet | ✅ Erledigt | — |
| #557 | Streaming der Modellantwort (SSE) statt einer Antwort am Stueck | 🧊 Zurueckgestellt — Ausloeser: Wieder anstehend, sobald EINES davon eintritt: (a) ein Lauf scheitert nachweislich an einem Verbindungsabbruch waehre... | — |
### COMM — Kommunikation zwischen Agenten
| | Vorhaben | Stand | Ziel |
|---|---|---|---|
| #644 | Freigabe im Messenger: gestagte Aufrufe per Button aus Rocket.Chat und Telegram freigeben - ueber eine austauschbare ... | 📋 Offen | — |
| #645 | Kanalzustand sichtbar: ausgefallene Kanaele als blockiert zeigen, unklare Zustellungen ausdruecklich melden | 📋 Offen | — |
| #206 | B8: AgentComm.send_message hat keine Tiefenbegrenzung - A nach B nach A verklemmt | ✅ Erledigt | `cffd6f4` |
| #461 | Zwei Delegationsketten ueber Kreuz verklemmen sich - A ruft B, waehrend B A ruft | ✅ Erledigt | `cffd6f4` |
| #207 | Agentenkommunikation Phase 1: ParentRunId und RootRunId | 📋 Offen | — |
| #536 | A2A-Endpunkt liest den Absender per Zeichenoffset aus einem Anzeigetext zurueck | 🔨 In Arbeit | — |
| #208 | Agentenkommunikation Phase 2: Nachrichtenspeicher AgentMessages mit FTS5 | 📋 Offen | — |
| #209 | Agentenkommunikation Phase 3: ask_agent mit Tiefe 1 und Zykluspruefung | 🧊 Zurueckgestellt — Ausloeser: sobald E4 entschieden ist - ask_agent eng gefasst behalten oder ersatzlos streichen | — |
| #210 | Agentenkommunikation Phase 4: Paar-Ansicht an den Datenbestand anschliessen | 🧊 Zurueckgestellt — Ausloeser: sobald Phase 2 steht und die Tabelle AgentMessages Daten fuehrt | — |
| #211 | Agentenkommunikation Phase 5: AgentCommAnalysis | 📋 Offen | — |
### DATA — Daten und Speicher
| | Vorhaben | Stand | Ziel |
|---|---|---|---|
| #212 | Historie-Umzug in die Instanz-DB (loest B10 und K6) | 📋 Offen | — |
| #213 | A6: MySQL-Spiegel als nachgelagerte Kopie | 🧊 Zurueckgestellt — Ausloeser: sobald der Historie-Umzug durch ist und E1 entschieden - der Server kommt gegebenenfalls mit der Chat-Entscheidung | — |
| #241 | Atomares Schreiben nach dem File.Replace-Muster | ✅ Erledigt | — |
| #242 | Speicher-Fundament: WAL, busy_timeout, Pooling, Schreib-Warteschlange | ✅ Erledigt | — |
| #243 | Sicherung und Wiederherstellung | ✅ Erledigt | — |
| #273 | Fruehjahrsputz: die automatische Sicherung war nie gestartet | ✅ Erledigt | — |
| #274 | Fruehjahrsputz: doppelte Sicherungs-Einstellungen ueberschrieben einander | ✅ Erledigt | — |
### OPS — Betrieb und Auslieferung
| | Vorhaben | Stand | Ziel |
|---|---|---|---|
| #537 | Abnahmedurchgang unter Linux: Instanzmanager, Sockets und Mehrinstanzbetrieb auf der Ubuntu-VM pruefen | 📋 Offen | — |
| #214 | L2: 24/7-Betriebsform unter Linux | 📋 Offen | — |
| #648 | Selbstdiagnose (doctor) und Modell-Probeantwort vor dem Aktivieren | 📋 Offen | — |
| #215 | L3: Release-Strecke linux-x64 (DC3) | 📋 Offen | — |
| #216 | DC1: Schaltflaeche "Fehler melden" in der Oberflaeche | 📋 Offen | — |
| #217 | DC2: Bugtracker-Tool fuer Agenten | 📋 Offen | — |
| #218 | Deploymentcenter-SDK von 2.6.0 auf 2.7.0 nachziehen | ✅ Erledigt | `0.1.2` |
| #219 | DC4: SDK als Git-Submodul statt Cross-Repo-Pfad | 📋 Offen | — |
| #220 | DC5: Evaluator-Cron einrichten (Betreiberaufgabe) | 📋 Offen | — |
| #221 | Release-Guard beim Upload: ein frisches Produktverzeichnis steht ohne .htaccess da | 📋 Offen | — |
| #222 | DC8: Die Signaturpflicht laesst sich ueber den empfohlenen Weg nicht einschalten | 🧊 Zurueckgestellt — Ausloeser: sobald LaunchUpdateAgent --require-signature durchreicht; ist unter deploymentcenter gemeldet | — |
| #244 | Zugangsschutz: Lizenzschluessel als Basic-Auth zur Release-Ablage (DC 2.4) | ✅ Erledigt | — |
| #245 | Update anwenden (DC6) | ✅ Erledigt | — |
| #246 | Erstinstallation (DC7) | ✅ Erledigt | — |
| #247 | Linux-Portierung der Bibliotheken | ✅ Erledigt | — |
| #269 | Alt-Scheduler abgeloest - alles ist ein Task | ✅ Erledigt | — |
| #270 | Deploymentcenter ersetzt WatchDog und LicenseLabrador | ✅ Erledigt | — |
| #271 | DC3: Release-Strecke win-x64 | ✅ Erledigt | — |
| #272 | Avalonia-Portierung, WinForms entfernt | ✅ Erledigt | — |
### FIN — Finanz und Analyse
| | Vorhaben | Stand | Ziel |
|---|---|---|---|
| #223 | C1: Marktkalender - Laeufe ausserhalb der Handelszeiten ueberspringen | 📋 Offen | — |
| #224 | C2: Indikatoren im Code rechnen statt im Modell | 📋 Offen | — |
| #225 | C3: dataAsOf wird geliefert, aber von nichts ausgewertet | 📋 Offen | — |
| #226 | C4: Termine und Fundamentaldaten | 📋 Offen | — |
| #227 | C5: Bestandsregister - stock_add ist eine Wissenssammlung, kein Bestand | 📋 Offen | — |
| #228 | C6: Nachrichten-Entdopplung | 📋 Offen | — |
| #229 | C7: Ergebnisregister AgentOutput am Lauf | 📋 Offen | — |
| #230 | C8: Falsifizierbare Aussagen als Leistungsmass | 📋 Offen | — |
| #231 | Leerlaufquote: Laeufe ohne greifbares Ergebnis zaehlen | 📋 Offen | — |
| #232 | stock_add aus FileRW herausloesen | 📋 Offen | — |
### HYG — Hygiene
| | Vorhaben | Stand | Ziel |
|---|---|---|---|
| #233 | B9: index_Count-Race in FileRWTool | ✅ Erledigt | `cffd6f4` |
| #234 | B13: instanceId-Inkonsistenz zwischen RunAsync und SendMessageAsync | ✅ Erledigt | `cffd6f4` |
| #235 | DST-Randfall: eine nicht existierende Ortszeit wird uebersprungen statt verschoben | ✅ Erledigt | `cffd6f4` |
| #236 | 45 Nullable-Build-Warnungen | ✅ Erledigt | `cffd6f4` |
| #248 | Paket-Anhebungen gegen verwundbare transitive Fassungen | ✅ Erledigt | — |
| #267 | K3: Testfundament | ✅ Erledigt | — |
| #268 | Fruehjahrsputz: NU1903 und NU1902 geschlossen | ✅ Erledigt | — |
<!-- /dc:roadmap -->
---
## 2 — Woher die Reihenfolge kommt
Der Rang eines Items ist keine Meinung, sondern das Ergebnis von fünf Regeln. Sie
stehen hier, weil sie sich aus der Zahl allein nicht ablesen lassen.
**Kritische Befunde stehen vor allem anderen** (Bereich `FIX`, seit dem 2026-08-31).
Ein Fehler, der eine zugesicherte Grenze bricht oder den Betrieb auf der Zielplattform
trifft, wird behoben, bevor ein weiteres Feature oder ein kleinerer Fehler angefasst
wird. Der Bereich hat deshalb die Ränge unterhalb von 5 für sich.
Das Aufnahmekriterium ist eng gefasst, damit der Bereich nicht zum zweiten Rücken
für alles Dringliche wird: **entweder** die Software sagt eine Grenze zu, die sie
nicht hält, **oder** der Befund verhindert den Linux-Betrieb, für den das Ganze gebaut
ist. „Wichtig" allein genügt nicht — dafür gibt es den Rang.
**Erst Bremsen, dann PS.** Ein Agent, der unbeaufsichtigt läuft, braucht
Nachvollziehbarkeit und Kontrolle, bevor er mehr können soll. Deshalb stehen
Schlüsselablage, Freigabe, Papierkorb, Tiefenbegrenzung und Scrubbing vor den
Fähigkeiten — und die vier Reichweiten-Punkte #196, #197, #199, #200 dahinter, in
dieser Reihenfolge.
**Was den Betrieb blockiert, geht vor.** #190, #191, #214 und #215 sind zusammen die
Bedingung dafür, dass die Zielmaschine überhaupt unbeaufsichtigt laufen und Updates
bekommen kann.
**Entscheidungen kosten kein Budget und lösen mehrere Punkte auf einmal.** Deshalb
stehen #180 ganz vorn und #181 auf Rang 50 — beide kosten nur eine Festlegung.
**Was nichts blockiert, rückt nach hinten.** Der Marktkalender (#223) und der
Historie-Umzug (#212) waren nie durch die Plattform blockiert und blockieren selbst
nichts. Der ganze Finanzteil ist bewusst nachgelagert: ClawdDotNet soll zuerst als
allgemeiner Agenten-Client felsenfest sein, die handelsspezifischen Werkzeuge kommen
danach.
Zur Mechanik: `roadmap_rank` gilt in diesem Projekt **projektweit**, nicht je Bereich —
die durchgehende Reihenfolge oben hängt daran. Wer einen Eintrag im WebUI innerhalb
seines Bereichs verschiebt, schreibt den ganzen Bereich auf 10/20/30 um und verschiebt
ihn damit auch gegenüber allen anderen Bereichen. Als Item 177 unter `deploymentcenter` gemeldet.
---
## 3 — Begründungen
Nicht jedes Vorhaben braucht eine Herleitung; die meisten sind eine Zeile wert und
mehr nicht — die steht in der Beschreibung des Items. Hier steht, was mehr braucht.
### [FIX] #373 — PathBoundary.Canonicalize fällt offen aus
Gefunden am 2026-08-31 auf der Linux-Test-VM, Stand `7406497`. Zwei `[LinuxFact]`-Tests
schlagen fehl, die unter Windows nie gelaufen sind — die in Abschnitt 0 genannten
grünen Tests stammen von dort.
`Canonicalize` löst jeden Pfadabschnitt einzeln auf und ruft für einen noch nicht
existierenden Abschnitt `File.ResolveLinkTarget`. Der Aufruf gibt für einen fehlenden
Pfad **nicht `null` zurück, sondern wirft `FileNotFoundException`** — eine
`IOException`. Der `catch` darunter verlässt daraufhin die *gesamte* Auflösung mit
`return full`, also mit dem unaufgelösten Pfad.
**Warum das die erste Baustelle ist.** Die Symlink-Hälfte der Workspace-Grenze ist
damit für jeden Pfad wirkungslos, dessen letzter Abschnitt noch nicht existiert — also
für **jeden Schreibvorgang**. Betroffen sind `WorkspacePath` (das ist S6, #253, und das
gilt als erledigt), `FtpTool` und der Zip-Slip-Schutz in `BackupService`. Der
`catch`-Zweig ist im Quelltext ausdrücklich als „weist im Zweifel ab" kommentiert und
verhält sich genau umgekehrt: Der unaufgelöste Pfad besteht die Präfixprüfung gerade
deshalb.
Die Gegenseite desselben Fehlers trifft den Normalbetrieb, nicht nur den Angriffsfall:
Liegt der Workspace selbst hinter einer Verknüpfung, sperrt er sich selbst aus.
Vorgabe für die Umsetzung: den fehlenden Abschnitt vor dem Aufruf abfangen und ihn
unverändert übernehmen, statt die Schleife zu verlassen — das ist es, was der
XML-Kommentar ohnehin zusagt. Der `catch (IOException)` darf den Pfad danach nicht
mehr unaufgelöst durchreichen, sondern muss ihn als unbestimmbar melden. Beide
Linux-Tests müssen grün werden, und der Fall „letzter Abschnitt existiert noch nicht,
davor liegt eine Verknüpfung nach draußen" gehört als eigener Test dazu. Er ist
derjenige, den die vorhandenen Tests nicht abdeckten.
### [FIX] #375 — Log-Verzeichnis wird gegen das Arbeitsverzeichnis aufgelöst
Gefunden am selben Tag, auf derselben Maschine. Zwei Ansichten derselben Anwendung
widersprachen sich: Die Einstellungsseite zeigte
`~/.local/share/clawddotnet/Logs`, die Info-Seite `~/clawddotnet-test/publish/Logs`.
Auf der Platte gewinnt die zweite — die Info-Seite sagt die Wahrheit, das Feld in den
Einstellungen ist wirkungslos.
`InstanceConfig.LogDirectory` ist mit `"./Logs"` vorbelegt, und
`InstanceDirectoryManager` schreibt genau diesen Wert in jede neu angelegte
`InstanceSettings.json`. Der Wert ist damit nie leer, der Zweig auf
`settings.AppSettings.LogDirectory` in `AppHost` ist unerreichbar. `Path.GetFullPath`
löst ohne Basis gegen das **Arbeitsverzeichnis des Prozesses** auf.
**Warum das hierher gehört und nicht in die Hygiene.** Der Zielbetrieb ist ein
durchlaufender Dienst unter `/opt/clawddotnet` mit eigenem Dienstkonto (#214, #215).
Ein systemd-Dienst ohne `WorkingDirectory` startet in `/`; dann zeigt `./Logs` auf
`/Logs`, das ein Dienstkonto nicht anlegen kann. Im jetzigen Zustand schreibt die
Anwendung stattdessen in ihr eigenes Installationsverzeichnis — das ein Update
überschreibt. Der Befund blockiert damit denselben Betrieb, für den #214 und #215 da
sind, und muss vor ihnen weg.
Die Pflichtliste des [Oberflächen-Leitfadens](archiv/Oberflaechen-Leitfaden.md) führt genau
diesen Fall: „Keine relativen Pfade … zeigt unter Linux ins Leere."
Vorgabe für die Umsetzung: Ein relativer Wert wird gegen `instance.WorkingDirectory`
aufgelöst, nicht gegen das Arbeitsverzeichnis — das Feld steht bereits mit absolutem
Pfad in der Datei und war offensichtlich so gemeint. Die Vorbelegung wandert auf einen
absoluten Pfad unter `AppPaths.DataDirectory`, und bestehende `"./Logs"`-Einträge
werden beim Laden migriert. Solange beides offen ist, ist das Feld auf der
Einstellungsseite eine Lüge: Es lässt sich ändern und ändert nichts.
### [DEC] #180 — E10: Womit wird der Hauptschlüssel unter Linux gebunden?
Secret Service (gnome-keyring über D-Bus) oder systemd-creds mit TPM2.
**Empfehlung: Secret Service als Standard**, Backend über `CLAWD_SECRET_BACKEND`
umschaltbar. Der Vorbehalt gehört dazu: Mit Autologin — und den brauchen wir für
#214 — entsperrt sich der Keyring von selbst. Dann schützt er nur noch gegen andere
Benutzer, nicht gegen den Zugang zur Maschine. Wer das nicht will, nimmt TPM2; es
überlebt zudem einen Neustart ohne Menschen.
Steht vor #190, weil die Antwort das Backend bestimmt, das dort gebaut wird.
### [SEC] #190 — L1: Der Hauptschlüssel liegt unter Linux im Klartext
> **Stand 2026-09-10: Die Naht ist gebaut, die Linux-Antwort steht noch aus.**
>
> `SecretKeyStore` hält nicht mehr einen verpackten Schlüssel, sondern einen
> **Schlüsselbund** (`SecretKeyRing`): denselben Hauptschlüssel, mehrfach verpackt.
> Jedes Fach gehört einem `ISecretProvider` — `dpapi` (Windows), `passphrase`
> (Wiederherstellung), `file` (nur Dateirechte, der Zustand *dieses* Befunds, jetzt
> beim Namen genannt).
>
> **Warum mehrere Fächer und nicht ein besseres.** Ein Schlüssel an der Maschine
> überlebt keinen Umzug; einer an einer Passphrase verlangt bei jedem Start jemanden,
> der tippt — und der Dauerbetrieb ohne Menschen ist der Zweck (#214). Der Bund
> entscheidet sich nicht: Im Alltag öffnet das Maschinenfach ohne Rückfrage, nach
> einem Umzug die Passphrase, und beide führen zu **demselben** Schlüssel. Alle
> `enc:v2`-Werte bleiben lesbar, nichts muss neu eingetragen werden.
>
> **Sicherungen laufen seit dem 2026-09-11 nicht mehr über diesen Bund**, sondern über
> den Lizenzschlüssel des Managers (Instanzmanager-Konzept, Abschnitt 9.10). Eine Sicherung
> übersteht den Maschinenwechsel damit ohne Passphrase. Das Wiederherstellungsfach bleibt
> für den selteneren Fall, dass eine laufende Installation ihr Maschinenfach verliert, ohne
> dass eine Sicherung im Spiel ist.
>
> **Was noch fehlt, ist genau #180:** Womit das Maschinenfach unter Linux gefüllt wird.
> Bis dahin greift dort `file` — dieselbe Schutzstufe wie vorher, aber sie steht jetzt
> als Warnung im Protokoll und in `SecretKeyStore.Problems`, statt eine stille Zeile
> `: key` zu sein. Der Befund bleibt deshalb offen.
>
> Zwei Zusagen sind mit Tests festgehalten: Geht **kein** Fach auf, wird abgebrochen
> statt ein neuer Schlüssel erzeugt (der machte jeden bestehenden Wert wortlos
> unlesbar). Und ein Umzug legt den Schlüssel **nicht** im Klartext ab, nur damit der
> nächste Start bequemer wird.
`SecretKeyStore.Wrap` bindet den Schlüssel unter Windows per DPAPI ans Benutzerkonto
und gibt ihn sonst ungewrappt zurück; der einzige Schutz ist dann `0600` aus
`AppPaths.RestrictToOwner`. Auf einer dauerhaft laufenden, netzgebundenen Maschine ist
das die erste Baustelle.
**Der Migrationspfad ist der eigentliche Aufwand, nicht das Backend.** Die bestehenden
Werte sind DPAPI-verschlüsselt und auf Linux nicht lesbar — `SecretProtector.UnprotectV1`
wirft dafür bewusst. Der Weg ist gebaut: Backup **mit Passphrase** auf Windows ziehen
(PBKDF2 + AES-GCM), auf Linux zurückspielen. Ohne Passphrase muss jeder Wert neu
eingetragen werden. **Die Windows-Zweige bleiben deshalb stehen, bis der Umzug durch
ist.**
Vorgabe für die Umsetzung: erst der getestete Migrationspfad, dann das neue Backend.
Ein Test, der beweist, dass ein ungewrappter Schlüssel nicht mehr geschrieben wird,
gehört dazu — der Eingriff ist klein, die Folge eines Fehlers ist es nicht.
### [SEC] #191 — Freigabe-Ansicht
Der einzige Punkt, der echten Betrieb blockiert. Die Dienst-API steht vollständig
(`StagingService.ListPendingAsync/ApproveAsync/RejectAsync`, durchgereicht über
`AppHost.Staging`); es fehlt eine Seite mit Liste und zwei Schaltflächen.
Die dritte Schaltfläche **„Immer erlauben"** gleich mitnehmen: gibt frei *und* setzt
die Policy für dieses Tool auf `auto`. Kostet fast nichts und ist der Unterschied
zwischen einer Liste, die man täglich abarbeitet, und einer, die von selbst leer wird.
Bauplan: [Staging-Konzept](Staging-Konzept.md).
### [SEC] #192 — Output-Scrubbing
Muss **vor** allem stehen, was Tool-Ergebnisse dauerhaft speichert — also vor #208
(Nachrichtenspeicher) und #213 (Spiegel) — und vor #196, #197, #200, deren Ergebnisse
voller Zugangsdaten sind. Schließt die Lücke, die S3 nur für URLs schloss.
### [CAP] #195 — FileRW-Papierkorb
Kleinster Eingriff mit realer Wirkung: `delete` ist heute endgültig, ein Aufruf mit
`path: "."` räumt einen Workspace ab. Danach kann `FileRW.delete` von `approve` auf
`auto` — das entlastet #191 sofort.
Bauplan: [Umsetzungsplan](umsetzungsplaene/UMSETZUNGSPLAN-FileRW-Papierkorb-Cleanup.md).
### [CAP] #196 — L4: Shell-Tool
**Hochgestuft durch die Linux-Festlegung.** Der Punkt stand im Ideenspeicher, weil
„sandboxed" unter Windows ein Versprechen war, das man nicht halten kann — unter Linux
geht es, mit `bwrap` oder `systemd-run`, eigenem Mount-Namespace und Allowlist. Löst
nebenbei die hartverdrahteten yt-dlp/ffmpeg-Aufrufe im `SocialMediaManagerTool` ab.
**Die Sandbox ist die Funktion, nicht das Drumherum.** Erst festlegen, was garantiert
wird (Mount-Namespace, Netz, Zeit, Ausgabe), dann bauen; jede Garantie mit einem Test,
der den Ausbruch versucht.
### [CAP] #197 — L5: MCP-Client
Größter Reichweiten-Hebel pro Aufwand: macht fremde Konnektoren zur Konfigurationssache
statt zum C#-Projekt. Das ist der Großteil von Grok Bots Konnektor-Vorsprung.
stdio-Server (`npx`/`uvx`) laufen auf Linux nebenbei.
**Voreinstellung `approve` für fremde Tools ist eine Invariante, kein Vorschlag** —
sonst importiert man sich eine Policy-Lücke. Fremde Tool-Schemata sind Fremdeingaben:
Namenskollisionen, Schema-Validierung, Ergebniskappung wie bei eigenen Tools.
Nimmt dem `Http`-Tool aus dem Ideenspeicher die Dringlichkeit. Zusammen mit #198 denken —
Toolsets und nachladbare Server sind dasselbe Problem: nicht alles immer im Prompt.
**Seit dem 2026-09-18 vor Shell (#196).** Der zweite Vergleich hat bestätigt, woher der
Vorsprung kommt: Grok Bot bindet über ein einziges Composio-Plugin mehr als 1.000 Apps
mit OAuth an. Ein MCP-Client bringt mehr Reichweite als jedes eigene Werkzeug, und er
braucht keine Sandbox wie die Shell. Hinter den Bremsen (#190, #191, #192) bleibt er
trotzdem.
### [CAP] #198 — A4: Skills und Toolsets
Größter Token-Hebel nach dem Caching — und ohne Toolsets ertrinkt der Prompt in den
Tools, die #197 hereinbringt.
**Agenten dürfen Skills aus Erfahrung selbst schreiben — aber erst nach Freigabe
aktiv**, sonst ist es ein Injection-Kanal in künftige Läufe.
**Erweitert am 2026-09-18** (Vorbild Grok Bot, der aus einem gelungenen Ablauf einen
Skill macht):
- **Ein Skill ist kein Freitext.** Er hat Schritte, Entscheidungsregeln, Anforderungen an
das Ergebnis und **Freigabegrenzen** — ab welcher Aktion er zwingend über Staging
läuft. Die Freigabegrenze steht im Skill, damit sie beim Prüfen sichtbar ist, und
wirkt trotzdem nur über die Policy: Ein Skill kann sie verschärfen, nie lockern.
- **Entwurf aus einem erfolgreichen Lauf.** Nach `done` mit bestandener `acceptance` darf
der Agent einen Skill vorschlagen. Der Entwurf ist ein gestagter Vorschlag, verweist
auf RunId und Receipts des Laufs, aus dem er entstand, und wird erst nach Freigabe
aktiv. So sieht der Prüfer, *was* sich bewährt hat, und nicht nur, was der Agent
darüber behauptet.
- **Skills gehören dem Agenten.** Jeder hat seine eigene Sammlung; einen Skill für die
ganze Instanz freizugeben ist ein eigener, zweiter Schritt (Vorbild OpenClaw: private
Bibliotheken je Nutzer auf einem gemeinsamen Gateway).
- Der **Werkzeugwunsch** aus dem Ideenspeicher gehört in den Prompt-Kern.
### [CAP] #646 — Taskboard fasst nach
Grok Bot wirbt damit, liegengebliebene Arbeit von selbst nachzufassen. Bei uns liegt das
Fundament schon da — Scanner, Status, `blocked_by`, Reopen —, es fehlt nur der Blick auf
Arbeit, die **formal lebt, aber nicht vorankommt**. Das ist etwas anderes als der
Claim-Lease: Der räumt abgestürzte Läufe ab, dieses Vorhaben kümmert sich um Tasks, die
niemand mehr anfasst.
Vier Fälle: `in_progress` ohne Fortschritt, `blocked` mit längst erledigter Vorbedingung,
`@human`-Tasks, die zu lange warten, und `in_review` ohne Abnahme. **Gestuft**: Ein
Agent-Task wird einmal mit einem Nachfass-Kommentar geweckt; bleibt er liegen oder ist
ein Mensch dran, geht eine Nachricht über die Kanal-Schnittstelle (#644). Jede
Nachfassung höchstens einmal je Frist und über das Budget gedeckelt — erneutes Wecken
kostet Tokens, und ein Nachfass-Mechanismus, der selbst Dauerfeuer macht, wäre schlimmer
als keiner.
### [CAP] #647 — Delegation an einen oder mehrere Agenten
Heute trägt ein Task genau einen Assignee. Wer dieselbe Aufgabe an drei Agenten geben
will, legt drei Tasks an und führt die Ergebnisse selbst zusammen.
**Mehrere Ziele werden zu einem Sammel-Task mit je einem Teil-Task pro Agent.** Der
Sammel-Task ist `blocked_by` alle Teile und wird geweckt, wenn sie erledigt sind —
wahlweise wenn *alle*, der *erste* oder die *Mehrheit* fertig ist. Das ist bewusst keine
neue Laufzeitlogik: `blocked_by`, Reopen, `acceptance` und Claim tragen es, und es bleibt
strukturell zyklenfrei, weil Tasks Datensätze sind und keine synchronen Aufrufe (dieselbe
Begründung wie bei #206).
Delegieren können der Mensch (Weboberfläche, Avalonia, Messenger-Befehl über #644) und
der Agent (Taskboard-Tool). Grenzen: eine Höchstzahl von Zielen je Delegation, ein
Budget je Teil-Task, das vorab feststeht, und das Ziel muss existieren — kein Raten, wie
schon bei `@new:<agentId>`. #207 (ParentRunId/RootRunId) verknüpft die Läufe; ohne das
ist ein Fächer aus Teil-Läufen im Audit nicht mehr als ein Ganzes lesbar.
### [CAP] #649 — Probelauf neuer Agenten
Für den Personalmanager-Agenten aus dem
[Erweiterungskonzept](Orchestrator-Erweiterungskonzept-2026.md): Wer über AgentSpawn und
AgentEditor neue Agenten anlegt, soll sie **grob ausprobieren können, bevor sie in
Betrieb gehen** — sonst merkt man ein fehlendes Werkzeug oder ein untaugliches Modell
erst im ersten echten Lauf, nachts.
Zwei Stufen: erst die statischen Prüfungen aus #648 (Konfiguration, Modell-Probeantwort,
Werkzeuge, Workspace, Budget), dann ein kurzer **Trockenlauf** in einem Wegwerf-Kontext.
Im Trockenlauf wird nichts ausgeführt, was etwas verändert: Freigabepflichtige und
schreibende Aufrufe werden nur als „hätte gestagt / hätte geschrieben" protokolliert,
kein Gedächtnis-Schreiben, keine Nachricht nach außen, eigenes kleines Budget.
**Der Probelauf entscheidet nicht über die Inbetriebnahme.** Aktivieren bleibt
freigabepflichtig, auf der Linie von #205. Der Bericht hängt an der Freigabe, damit der
Mensch sieht, was ausprobiert wurde — ein Agent, der sich seinen Nachfolger selbst
abnimmt, wäre genau die Lücke, die #205 schließt.
### [CAP] #200 — L7: Browser-Tool mit Live-Ansicht
Größte Wirkung, größtes Risiko. Erst wenn #190, #191, #192 und #204 stehen.
Der Bauplan gehört **vor** die erste Zeile Code: Umfang, Sitzungshaltung, Live-Ansicht
und die Injection-Rahmung sind zusammen kein Auftrag, sondern ein Dokument. Der Grund,
warum Chromium headed auf einem eigenen X-Display läuft und nicht auf der Sitzung des
Benutzers: Agent und Mensch sollen sich nicht ins Fenster greifen. Der Grund für
`x11vnc`: Es ist zugleich der Weg für Erstanmeldungen — **der Mensch loggt sich einmal
von Hand ein, die Session bleibt im Profilverzeichnis, das Modell sieht die Zugangsdaten
nie.**
**Zwischenstufe mit einem Großteil des Nutzens und einem Bruchteil des Risikos:**
`WebFetch` um gerendertes DOM und Cookie-Sessions erweitern, ohne Klick-Automatik.
### [COMM] #644 — Freigabe im Messenger
Staging greift, und freigeben kann man in der Weboberfläche. Unbeaufsichtigter Betrieb
heißt aber: Niemand sitzt am Rechner. Grok Bot baut seine ganze Bedienung darauf, dass
die Freigabe als Karte dort ankommt, wo der Mensch ohnehin ist. Das ist der größte Hebel
aus dem zweiten Vergleich und der kleinste Aufwand.
**Erst die Schnittstelle, dann die Adapter.** Vorgabe ist, jederzeit weitere
Nachrichtensysteme und Werkzeuge anbinden zu können. Deshalb kommt zuerst eine
Kanal-Schnittstelle in den Core — senden mit Aktionen, eingehende Entscheidungen als
Ereignis, Zustand —, und Rocket.Chat und Telegram sind die ersten beiden Adapter. Die
Freigabe kennt nur die Schnittstelle, nie den Adapter. Das hat eine zweite Wirkung: **Die
Freigabe hängt nicht mehr an #181.** Wie immer die Chat-Frage ausgeht, der Gewinner
bekommt einen Adapter, und an der Freigabe ändert sich nichts. Dieselbe Schnittstelle
tragen #645 und #646.
**Kein zweiter Freigabepfad.** Der Button ruft denselben `StagingService`-Weg wie die
Weboberfläche — Plan-Freeze, Approval-Record, Folge-Task. Wird anderswo entschieden oder
verfällt der Vorschlag (nach 24 h), wird die Nachricht nachgezogen, damit kein toter
Button stehen bleibt.
Sicherheit: Nur hinterlegte Absender je Kanal dürfen entscheiden; die Callback-Daten
tragen eine nicht erratbare Kennung statt der nackten Vorschlagsnummer; jede
Entscheidung steht mit Kanal und Absender im Audit. Die Argument-Vorschau ist gekappt
und läuft durch das Output-Scrubbing (#192) — ein Freigabe-Chat ist genau der Ort, an
dem ein Secret nicht landen darf.
### [COMM] #645 — Kanalzustand sichtbar
Vorbild OpenClaw v2026.9.1: Ein ausgefallener Kanal bleibt als *blockiert* sichtbar, mit
einem Hinweis zur Behebung, und eine unklare Zustellung wird als unklar gemeldet statt
still als Erfolg verbucht.
Sobald Freigaben über den Chat laufen (#644), ist ein stiller Kanalausfall kein
Schönheitsfehler mehr: Der Vorschlag verfällt, und niemand hat ihn gesehen. Deshalb
**drei Ausgänge** für jede Zustellung — zugestellt, fehlgeschlagen, unklar — und ein
Zustand je Adapter (ok, gestört, blockiert) in Weboberfläche, Instanzmanager und
Avalonia. Ist der Kanal einer Freigabe gestört, steht das an der Freigabe.
Bewusst die abgespeckte Fassung des `ChannelRouter` aus dem Ideenspeicher: erst sichtbar
machen. Ausweichen auf einen zweiten Kanal ist der nächste Schritt und hängt an #185.
### [COMM] #206 — B8: `send_message` ohne Tiefenbegrenzung
`AgentComm.send_message` ist ein synchroner Aufruf ohne Tiefenbegrenzung. A→B→A
verklemmt echt: A hält sein Gate, während es auf B wartet — ruft B nun A, wartet B auf
As Gate. Löst nur der Timeout auf.
**Mit Vorsicht**: Der Eingriff sitzt am Agent-Gate, an dem schon einmal ein Deadlock
lauerte. Erst Invarianten festlegen, dann bauen. Test A13 der
[Teststrategie](Teststrategie.md) deckt genau das ab und **fehlt bis heute** — er ist
Teil des Vorhabens, nicht ein Nachtrag.
### [COMM] #209 — Phase 3: `ask_agent` (zurückgestellt)
**Auslöser: sobald #182 (E4) entschieden ist.** Solange offen ist, ob `ask_agent` eng
gefasst bleibt oder alles über Tasks läuft, ist der Zuschnitt von Phase 3 nicht
bestimmbar. Empfehlung im Konzept: behalten, eng gefasst, Tiefe 1 mit Zyklusprüfung.
### [COMM] #210 — Phase 4: Paar-Ansicht (zurückgestellt)
**Auslöser: sobald #208 steht und `AgentMessages` Daten führt.** Auswahl, Filterung und
Darstellung sind fertig — `AgentChatsPageView` steht. Es fehlt genau eine Abfrage in
`AgentChatsPageViewModel.LoadMessages`. Zurückgestellt, nicht offen: Es gibt nichts zu
bauen, solange die Tabelle leer ist.
### [DATA] #212 — Historie-Umzug in die Instanz-DB
Löst zwei Dinge in einem Zug. B10: Heute wird bei **jedem** Chat-Eintrag die
vollständige Historie und der vollständige Kontext als eingerücktes JSON neu geschrieben
— O(n²), bei 500 Nachrichten mehrere MB pro Nachricht. K6: unbegrenzte Historie.
Migration nur nach frischem Backup, alte JSON erst nach verifiziertem Import löschen.
Voraussetzung für #213.
### [DATA] #213 — A6: MySQL-Spiegel (zurückgestellt)
**Auslöser: sobald #212 durch ist und #181 entschieden — der Server kommt
gegebenenfalls mit der Chat-Entscheidung.**
**SQLite bleibt die einzige Wahrheit.** MySQL ist reiner nachgelagerter Spiegel:
empfängt nur vom Replikator, die App liest im Betrieb **nie** daraus. Outbox-Muster an
der vorhandenen Schreib-Warteschlange, idempotente Upserts, nie blockierend. Zeilen
tragen `instance_id`. **Der Restore-Pfad Spiegel → frische SQLite muss existieren und
getestet sein** — gleiche Regel wie beim Backup, und Teil der Definition of Done.
### [OPS] #214 — L2: 24/7-Betriebsform
Ohne systemd-Unit, Autologin und unterbundene Sitzungssperre ist „läuft durch" eine
Behauptung. Klein, aber Voraussetzung für alles Unbeaufsichtigte. **Kein kopfloser
Betrieb**: Die Oberfläche läuft laut Zielbetrieb immer mit.
### [OPS] #215 — L3: Release-Strecke `linux-x64`
Ohne sie gibt es auf der Zielmaschine kein Update. `deploy/publish.py` nimmt `--rid`
schon entgegen, die Vorgabe steht noch auf `win-x64`. Der `win-x64`-Zweig bleibt vorerst
als Ausweichweg.
Dazu gehört die Linux-CI: **bis dahin sind die 585 grünen Tests eine Windows-Aussage.**
### [OPS] #648 — Selbstdiagnose und Modell-Probeantwort
Vorbild OpenClaw (`openclaw doctor`, Update-Probelauf, „verifies a real response before
making the new model active"). Die Befunde aus dem Testbetrieb auf der Linux-VM waren fast alle
von der Art, die eine Diagnose beim Start gefunden hätte: Rechte, Pfade, ungültige
Cron-Ausdrücke, liegengebliebene Werkzeugaufrufe. Für eine Maschine, die 24/7 ohne
Aufsicht läuft (#214), ist „beim Start sagen, was nicht stimmt" die billigste Aufsicht.
Die Diagnose **meldet, sie repariert nicht von selbst** — sichere Reparaturen nur auf
ausdrückliche Anforderung. Die Modell-Probeantwort ist der zweite Teil: Ein neues Modell
wird erst aktiv, wenn eine echte Anfrage über OpenRouter geantwortet hat, Tool-Calls
kann und einen Preis trägt. Sonst bleibt das alte Modell stehen.
Die Prüfungen sind Bausteine im Core, weil #649 sie für neue Agenten wiederverwendet.
### [OPS] #218 — Deploymentcenter-SDK von 2.6.0 auf 2.7.0 nachziehen
Zwei brechende Änderungen im Changelog: Der Befundzustand aus
`/api/supervisor/v1/observe` und `/status` heißt jetzt `finding_status`, und die
Nachprüfungs-Status aus 2.6.1 müssen in eigenen Auswertungen eingeordnet werden —
`awaiting_verification` und `in_verification` zählen **nicht** als offener Fehler,
`fix_insufficient` schon.
Danach die Fassungszeile in [CLAUDE.md](../CLAUDE.md) hochsetzen und `dc_link_project`
aufrufen. Der Grund für beides: Ohne die Angabe muss beim nächsten Mal die gesamte
Historie gelesen werden.
### [OPS] #222 — DC8: Signaturpflicht (zurückgestellt)
**Auslöser: sobald `UpdateClient.LaunchUpdateAgent` `--require-signature` durchreicht.**
Ist unter `deploymentcenter` gemeldet.
Der Schlüssel steht, ab 0.1.2 wird signiert, die Prüfung ist beidseitig getestet.
`--require-signature` gibt es aber nur als Kommandozeilenschalter, und der empfohlene
Weg reicht ihn nicht durch. Selbst nachbauen hieße `--restart`, `--wait-for-pid` und
`--wait-timeout` verlieren — dafür ist der Gewinn zu klein.
### [FIN] #223 — C1: Marktkalender
Spart ab dem ersten Tag Geld: Ein `*/30`-Cron läuft heute auch Sonntag um 3 Uhr.
Zwei Bausteine, und der erste ist der wichtige: `onlyWhenMarketOpen: "NYSE"` im
Task-Frontmatter wirkt **ohne Zutun des Modells** — der Lauf wird schlicht übersprungen.
Das Tool für Fragen des Agenten ist die Zugabe. Handelskalender ändern sich selten;
eine gepflegte Datei reicht, keine externe Abhängigkeit. Der Haken im Scanner ist schon
da (`IMarketCalendar`).
### [FIN] #230 — C8: Falsifizierbare Aussagen
Das eigentliche Leistungsmaß. Der Agent legt sich fest (Subjekt, Aussage, Horizont,
Konfidenz); ein Auflösungs-Task prüft gegen die tatsächlichen Kurse — kein Mensch muss
bewerten.
Der **Brier-Score** ist der Grund, warum es nicht bei der Trefferquote bleibt: Er misst,
ob die Konfidenz ehrlich war. Ein Agent, der bei 0,9 nur in 60 % der Fälle recht hat,
ist überheblich — bei reiner Trefferquote bleibt das unsichtbar.
**Unter 30 aufgelösten Aussagen keine Rangliste, nur Rohzahlen** — sonst optimiert man
Rauschen. Braucht #227 und #229.
---
## 4 — Ideenspeicher
Nicht beschlossen und **bewusst keine Items**: Wer etwas nicht übernehmen kann, hat kein
Vorhaben. Steht hier, damit es nicht verlorengeht — nicht, weil es demnächst gebaut wird.
### Tool-Kandidaten
| Tool | Nutzen | Bemerkung |
|---|---|---|
| **WebSearch** | Agenten können heute nur bekannte Domains abrufen, aber nichts *finden*. Brave/Tavily/SearXNG | Bauplan liegt vor: [Umsetzungsplan](umsetzungsplaene/UMSETZUNGSPLAN-WebSearch-Tool.md). **Spät** — großer Sicherheitshebel, deshalb erst nach Papierkorb, Inspector und AgentEditor-Härtung. Gehört zwischen #199 und #200 |
| **Nextcloud** | Ort, an dem Agenten Ergebnisse ablegen. Datei lokal erzeugen → hochladen → Link zurück in den Chat | Nextcloud hat keine API, die Inhalte *erzeugt*. Für PDF/XLSX kann Collabora als Konverter dienen. Bauplan: [RocketChat-Nextcloud-Konzept §5](RocketChat-Nextcloud-Konzept.md). Lohnt sich unabhängig vom Ausgang von #181 |
| **Http** | Generisches REST-Tool mit Allowlist je Agent | `DirectAPI` ist fest auf Finanz-Provider verdrahtet — jede neue API erfordert heute Code. **Weniger dringend seit #197**: Wo es einen MCP-Server gibt, braucht es kein eigenes REST-Tool |
| **Git** | Für den „Senior Developer"-Agenten | Über #197 womöglich ohne eigenen Code zu haben |
| **CollectionStore** | Schematisierte JSON/SQLite-Dokumenten-DB für Agenten | Ermöglicht strukturierte Tabellen/Sammlungen (z. B. Aktienanalysen, Kundenprofile) mit Schema-Validierung, Revisionshistorie und reinen Soft-Deletes. Bauplan: [Orchestrator-Erweiterungskonzept 2026 §3](Orchestrator-Erweiterungskonzept-2026.md) |
| **ask_supervisor** | Erste Klärungsstufe vor `ask_human` | Agent befragt den leitenden Supervisor bei Unklarheiten. Erst bei Dissens Eskalation an den Menschen via Telegram/Rocket.Chat. Bauplan: [Orchestrator-Erweiterungskonzept 2026 §5](Orchestrator-Erweiterungskonzept-2026.md) |
| ~~Shell~~ | — | **Beschlossen als #196** — unter Linux ist die Sandbox baubar |
| ~~Vision~~ | — | **Beschlossen als #199** |
| ~~Browser~~ | — | **Beschlossen als #200** — ganz hinten |
| ~~Notify~~ | — | **Gestrichen**, geht in der Chat-Anbindung auf |
### Weitere Ideen
| Idee | Bemerkung |
|---|---|
| Audit-Export als JSONL | Für externe Auswertung. Passt zum Spiegel #213 |
| Memory-Verfall & Task-Flush | Alte, unwichtige Beobachtungen nach einer Frist entfallen lassen; bei Task-Abschluss selektiver Memory-Commit und Kontext-Reset. [Orchestrator-Erweiterungskonzept 2026 §3](Orchestrator-Erweiterungskonzept-2026.md) |
| Scratchpad-Lifecycle | `scratch/t-<id>.md` bei `done`/`canceled` atomar nach `archive/` verschieben und nach Frist bereinigen |
| Hybride State-Graphs | Deterministische Pflichtschritte mit agentischer Autonomie über deklarative YAML-Pipelines kombinieren |
| Multi-Agenten-Debatten & Judge-Agent | Arbeiter-Kritiker-Zyklen mit maximal 3 Runden und Schiedsrichter-Entscheidung durch den Supervisor |
| Ephemere Worker mit Budget-Cap | Kurzlebige Subagenten für Parallel-Jobs; Budget per CAS vorab reserviert, `RootRunId` vererbt |
| Mid-Execution Priority Injects | Eilmeldungen von Monitor-Agenten (z. B. Ad-hoc-Zahlen) vor dem nächsten Step in den Kontext einspeisen |
| 5-Stufen Schutz vor Amoklauf | Soft-Deletes, Rate-Limits, Quarantäne-Circuit-Breaker und 1-Klick-Rollback via RunId-Audit |
| Multi-LLM Fallback & Evals | Primär- und Fallback-Modell je Agent; Test-Runner zum quantitativen Modell- und Prompt-Vergleich |
| Dynamische Prompt-Templates | Scriban/Liquid-Variablen (`{{team_roster}}`) in `Identity.md`/`Soul.md` für dynamische Teamerkennung |
| `ext_clitools/` Struktur | Einheitliche Ablage externer Binaries (`ffmpeg`, `yt-dlp`, `typst`) im Build-Prozess |
| Task-Archivierung | `done`/`canceled` nach einer Frist archivieren, damit `tasks/` nicht zuwächst |
| Werkzeugwunsch | Agenten bekommen in den Kern-Prompt den Hinweis, sich zu melden, wenn ihnen ein Werkzeug fehlt. Der Weg ist da — ein Task an `@human`. **Seit 2026-09-18 Teil von #198** |
| `@human`-Tasks mitschreiben | Gäbe die Paar-Ansicht auch für Mensch↔Agent, fast ohne Zusatzaufwand. Nach #210 |
| MySQL-Gedächtnis | Zweite `IMemoryRepository`-Implementierung, wenn mehrere Rechner dazukommen |
| Kern als Dienst, Oberfläche als Client | Heute hostet `ClawdDotNet.Desktop` den `AppHost` **in-process**; damit leben die Agenten im UI-Prozess — ein Absturz der Oberfläche nimmt sie mit, und genau die Oberfläche hat keine Testabdeckung. Der Schichtschnitt gäbe die Trennung her, der `AppHost` ist die Naht. **Notiert, nicht beschlossen** — lohnt sich, sobald der erste UI-Absturz eine Nacht Agentenarbeit kostet. Bis dahin trägt #214 |
| Rocket.Chat Realtime/DDP statt Polling | Antwortzeit ~1 s statt ~30 s |
| Collabora-Konvertierung | Berichte in Büroformaten. Hängt daran, ob der `convert-to`-Endpunkt freigebbar ist |
| `ChannelRouter` + Eskalation | Erkennt den Ausfall des Chat-Kanals und weicht auf Telegram aus. **Kein Nice-to-have**, sobald der Chat der Hauptweg ist — sonst ist er ein Einzelpunkt, dessen Ausfall niemand meldet. **Sichtbarkeit seit 2026-09-18 als #645**, die Kanal-Schnittstelle kommt mit #644; offen bleibt nur das Ausweichen, hängt an #185 |
| K4 Streaming | Hängt an #181 — Matrix streamt nicht |
| Orderausführung | Siehe #189. Eigene Kategorie, ausdrücklich kein Nebenprodukt |
---
## 5 — Woher das hier kommt
### Modell-Einstufung
Die Entwicklung läuft mit Opus 4.6. Die meisten Vorhaben sind damit gut machbar, sofern
die in Abschnitt 3 notierten Vorgaben mitgegeben werden. Drei Punkte sind markiert:
| Vorhaben | Einstufung | Warum |
|---|---|---|
| #206 Delegationstiefe | ⚠️ **mit Vorsicht** | Fasst das Agent-Gate an, an dem schon ein Deadlock lauerte. Erst Invarianten, dann bauen, Test A13 zwingend |
| #196 Shell | ⚠️ **mit Vorsicht** | Die Sandbox ist die Funktion. Jede Garantie mit einem Test, der den Ausbruch versucht |
| #200 Browser | ⚠️ **eigener Bauplan zuerst** | Nicht als ein Auftrag umsetzbar |
Zwei ursprünglich für ein stärkeres Modell markierte Stellen sind inzwischen gebaut. Die
Begründung bleibt stehen, weil sie erklärt, *warum* es so gebaut ist:
- **Der Scanner-Kern**: At-most-once, Claim-CAS, Zusammenspiel mit den serialisierten
Chat-Läufen — genau die Fehlerklasse, die hier schon einmal schiefging. Gebaut mit
Property-Tests für die Invarianten.
- **Die Fortsetzung nach Freigabe**: **Kein pausierter, im Speicher gehaltener Lauf.**
Der Lauf endet beim Staging regulär, die Freigabe erzeugt einen Folge-Task mit dem
eingefrorenen Aufruf. Echtes Suspend/Resume wäre eine Nummer größer gewesen — und ist
damit unnötig.
Generell: Neue Subsysteme kommen mit Tests nach der [Teststrategie](Teststrategie.md).
Bei den markierten Punkten sind die Invarianten-Tests kein Nice-to-have, sondern die
Absicherung dafür, dass ein schwächeres Modell sie umsetzen darf.
### Weiter gültig — Baupläne
Wer einen Punkt anfasst, liest das zugehörige Dokument zuerst.
| Dokument | Wofür |
|---|---|
| [Taskboard-Konzept](Taskboard-Konzept.md) | Dateiformat, Wahrheitsaufteilung Datei/DB, Scanner-Verhalten, Invarianten |
| [Audit-Konzept](Audit-Konzept.md) | Schema, Provenance-Regeln, Receipts |
| [Staging-Konzept](Staging-Konzept.md) | Policy-Auflösung, Plan-Freeze, Fortsetzung nach Freigabe — **Bauplan für #191** |
| [Security-Konzept](Security-Konzept.md) | Vier Schichten (Sandbox-Runner, Regeln vor dem Aufruf, Detektoren, Security-Agent), Quarantäne-Stufen, Skriptprüfung, Netzprofil — **Bauplan für #651–#659** |
| [Memory-Konzept](Memory-Konzept.md) | Modell, Schlüssel-Semantik, Abrufreihenfolge |
| [Agentenkommunikation-Konzept](Agentenkommunikation-Konzept.md) | Fünf Phasen, Korrelation, Nachrichtenspeicher |
| [RocketChat-Nextcloud-Konzept](RocketChat-Nextcloud-Konzept.md) | Rocket.Chat gebaut; Nextcloud, Rückweg und `ChannelRouter` offen. Enthält die Messung gegen die echte Instanz |
| [Deploymentcenter-Integration](Deploymentcenter-Integration.md) | Wie Heartbeat, Fehler-Stream, Bugtracker und Updates verdrahtet sind |
| [Orchestrator-Erweiterungskonzept-2026](Orchestrator-Erweiterungskonzept-2026.md) | Kollaborationsmuster, Schematisierte DB, Gedächtnis-Hygiene, Amoklauf-Schutz, Fallbacks |
| [umsetzungsplaene/](umsetzungsplaene/) | Vier Detailpläne: FileRW-Papierkorb, AgentInspector, AgentEditor-Härtung, WebSearch |
### Weiter gültig — Handbücher
| Dokument | Wofür |
|---|---|
| [Oberflaechen-Leitfaden](archiv/Oberflaechen-Leitfaden.md) | **Archiv seit #764** (Fenster entfernt). Damals: Arbeiten an `ClawdDotNet.Desktop`: Schichtschnitt, Fäden, Avalonia-12-Fallen, Prüfliste. Die Oberfläche hat **keine** Testabdeckung — Abschnitt 4 ist deshalb Pflichtlektüre vor jeder Abgabe |
| [ToolDevelopmentGuide](ToolDevelopmentGuide.md) | Ein neues Agenten-Tool bauen |
| [InstanceSetupGuide](InstanceSetupGuide.md) | Eine Instanz einrichten |
| [Teststrategie](Teststrategie.md) | Was wie getestet wird, Fallkatalog |
### Archiviert
Vollständig überführt. Sie bleiben als Begründung und Herkunft lesbar, werden aber
**nicht mehr fortgeschrieben** — siehe [docs/archiv/](archiv/).
| Dokument | Was daraus wurde |
|---|---|
| `Bestandsaufnahme-2026-07.md` | S1–S7, B1–B14, K1–K6, T1–T9, F-A1…F-A7 — als Items im Block oben |
| `Konzepte-Backup-Finanz-Analyse.md` | Backup erledigt; Finanzteil als #223–#228, Leistungsanalyse als #229/#230 und Leerlaufquote |
| `Linux-Portierung-Analyse.md` | Die drei Kernstellen und das `linux-x64`-Release. Der teure Teil (WinForms) ist entfallen |
| `Lizenz-HardwareId-v2-Implementierungsvorschlag.md` | **Gegenstandslos** — LicenseLabrador ist durch das Deploymentcenter ersetzt |
| `Deploymentcenter-Anbindung-Review.md` | Befunde behoben |
| `Deploymentcenter-2.4-Integrationsplan.md` | Als #216–#222 |
| `ClawdDotNet_StartPrompt.md` und die drei Prompt-Anhänge | Entwicklungs-Prompts der Anfangszeit. Eine Regel gilt weiter: die Pflichtfelder `fetchedAt`/`dataAsOf`/`source` der Internet-Tools |
### Die frühere Fassung dieser Datei
Bis zum 2026-08-30 führte diese Datei den Zustand selbst: Statustabellen mit den
Markern ✅📋❓❄️💭, eine Reihenfolgetabelle von 0 bis 14 und eine Chronik des Erledigten. Alles
davon liegt jetzt im Deploymentcenter — 95 Items, die alte Kennung steht im Titel
(`S1`, `B8`, `C1`, `L1`, `DC4` …), damit die archivierten Papiere auffindbar bleiben.
Die Übernahme lief über [deploy/roadmap/import_items.py](../deploy/roadmap/import_items.py);
den Zustandsblock oben schreibt
[deploy/roadmap/roadmap_block.py](../deploy/roadmap/roadmap_block.py) `--write`,
den Abgleich fährt dasselbe Skript mit `--check`.