Files
ClawdDotNet/docs/Roadmap.md
T
RichardandClaude Opus 5 fb185ca84d Sicherungen mit dem Lizenzschluessel verschluesselt, optional per FTP (#530)
Eine Sicherung des Managers ist jetzt als Ganzes mit dem Lizenzschluessel
verschluesselt. Beim Zurueckspielen wird der eigene Schluessel probiert; passt er
nicht, fragt die Oberflaeche nach dem Lizenzschluessel der Quellinstallation.

Der Lizenzschluessel ist der eine Wert, den jede Installation ohnehin hat, und er
liegt im Manager, nicht neben den Archiven. Damit faellt der Grund weg, aus dem die
taegliche Sicherung bisher keine Zugangsdaten enthielt: Eine Passphrase haette
gespeichert werden muessen, und neben den Sicherungen waere sie wirkungslos
gewesen. Jetzt reisen die Zugangsdaten mit, und eine Sicherung uebersteht den
Maschinenwechsel ohne Passphrase.

LicenseBackupCipher: eigener Behaelter .clawdbak. Kopf mit Schluesselprobe, das
Manifest als eigener Abschnitt, das ZIP in 1-MiB-Stuecken mit AES-256-GCM und
Endmarke. PBKDF2 aus Lizenzschluessel und festem Salt, der Schluessel normiert.
Kein RAR (braucht das lizenzpflichtige Herstellerprogramm), kein ZIP mit Kennwort
(kann .NET nicht schreiben, ZipCrypto ist gebrochen, und mit abgeleitetem
Schluessel braechte 7-Zip-Vertraeglichkeit nichts).

Zurueckspielen: Die Schluesselprobe laeuft VOR dem Anhalten der Instanz. Passt
der Schluessel nicht, antwortet der Endpunkt mit 422 und dem Code fremde_lizenz,
und ein Fenster verlangt den Schluessel der Quelle.

ManagerBackups: Gefuehrte Instanzen sichern sich nicht mehr selbst, weil nur der
Manager den Schluessel hat; er liest ihre Einstellungen aus InstanceSettings.json.
Einmal am Tag auch ueber einen Neustart des Managers hinweg. Ohne Lizenzschluessel
wird nichts gesichert, auch nicht ersatzweise unverschluesselt.

FTP (FluentFTP, schon im Loesungsbaum): TLS wo angeboten, requireTls erzwingt es;
Upload unter .part-Namen und danach umbenannt; Aufraeumen auf dem Server je
Instanz; ein gescheiterter Upload laesst die lokale Sicherung stehen. Das
Kennwort liegt verschluesselt in manager.json und geht nie an die Oberflaeche.

Welche Datei zu welcher Instanz gehoert, entscheidet ein Zeitstempel nach dem
Namen und nicht das Praefix - Test und Test_2 werden nicht mehr verwechselt.

Grenze, bewusst und dokumentiert (Konzept 9.10): Wer Lizenzschluessel und Archiv
hat, hat die Zugangsdaten. Der Schluessel ist dem Hersteller bekannt und gilt fuer
alle Instanzen einer Installation.

Nicht ueber die Oberflaeche abgenommen: Fenster fuer die fremde Lizenz und FTP
gegen einen echten Server stehen als Block H in #537.

860 Tests gruen, 0 Warnungen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-11 11:03:25 +02:00

728 lines
43 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.
---
## 1 — Stand aus dem Deploymentcenter
<!-- dc:roadmap stand=2026-08-31T13:27Z items=97 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. **[FIX] #373 — PathBoundary.Canonicalize bricht bei nicht existierendem Pfadabschnitt ab - Symlink-Schutz greift beim Schreiben nie**
2. **[FIX] #375 — Log-Verzeichnis aus den Einstellungen wird ignoriert - instance.logDirectory './Logs' gewinnt und wird gegen das Arbeitsverzeichnis aufgeloest**
3. **[DEC] #180 — E10 entscheiden: Womit wird der Hauptschluessel unter Linux gebunden?**
4. **[SEC] #190 — L1: Der Hauptschluessel liegt unter Linux im Klartext**
### FIX — Kritische Befunde — vor allem anderen
| | Vorhaben | Stand | Ziel |
|---|---|---|---|
| #373 | PathBoundary.Canonicalize bricht bei nicht existierendem Pfadabschnitt ab - Symlink-Schutz greift beim Schreiben nie | 📋 Offen | — |
| #375 | Log-Verzeichnis aus den Einstellungen wird ignoriert - instance.logDirectory './Logs' gewinnt und wird gegen das Arbe... | 📋 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 | — |
| #192 | Output-Scrubbing: Secret-Werte zentral aus allen Tool-Ergebnissen maskieren | 📋 Offen | — |
| #193 | Tool-Ergebnisse als untrusted content rahmen | 📋 Offen | — |
| #194 | Secret-UI: Zugangsdaten setzen und rotieren | 📋 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 | — |
| #196 | L4: Shell-Tool mit echter Sandbox | 📋 Offen | — |
| #197 | L5: MCP-Client fuer stdio- und HTTP-Server | 📋 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 | 📋 Offen | — |
| #204 | AgentInspector: ein Supervisor-Agent, der die anderen beurteilen kann | 📋 Offen | — |
| #205 | AgentEditor haerten: Aenderungen an Identity.md und Soul.md freigabepflichtig | 📋 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 | — |
### COMM — Kommunikation zwischen Agenten
| | Vorhaben | Stand | Ziel |
|---|---|---|---|
| #206 | B8: AgentComm.send_message hat keine Tiefenbegrenzung - A nach B nach A verklemmt | 📋 Offen | — |
| #207 | Agentenkommunikation Phase 1: ParentRunId und RootRunId | 📋 Offen | — |
| #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 |
|---|---|---|---|
| #214 | L2: 24/7-Betriebsform unter Linux | 📋 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 | 📋 Offen | — |
| #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 | 📋 Offen | — |
| #234 | B13: instanceId-Inkonsistenz zwischen RunAsync und SendMessageAsync | 📋 Offen | — |
| #235 | DST-Randfall: eine nicht existierende Ortszeit wird uebersprungen statt verschoben | 📋 Offen | — |
| #236 | 45 Nullable-Build-Warnungen | 📋 Offen | — |
| #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](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.
### [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.
### [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] #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] #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`. Gehört zum Prompt-Kern 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. Hängt an #181 |
| 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** |
| [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](Oberflaechen-Leitfaden.md) | 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`.