Unter Linux geprueft: 39 Ausbruchstests, viermal die volle Core-Suite
unter Last auf der Test-VM.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Jede Codeausfuehrung ausserhalb des Hauptprozesses: eigene Namensraeume
(Mount, PID, Netz nur loopback, User ohne verschachtelte), nur der
Arbeitsbereich unter /work beschreibbar, scripts/ darin schreibgeschuetzt,
keine Umgebung und keine Deskriptoren des Hauptprozesses, alle Capabilities
weg, no_new_privs, seccomp-Sperrliste (eigene BPF, x86_64 und arm64),
Grenzen fuer Zeit, Speicher, Prozesse, Dateigroesse und Ausgabe. Unter
Windows oder ohne bwrap: keine Ausfuehrung, mit Grund im Protokoll.
Erster Nutzer: ffmpeg im SocialMediaManager (fremde Mediendateien). yt-dlp
braucht Netz und folgt mit dem Egress-Proxy (#655).
Die Ausbruchstests (SandboxEscapeTests) laufen nur unter Linux mit bwrap.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Eine fremde Laufzeit oder der eigene Claude Code des Menschen spricht per MCP
mit der Instanz. Der Server bietet genau die Werkzeuge des Agenten hinter dem
Token an; jeder Aufruf laeuft durch die Engine wie ein Aufruf des eigenen
Modells (Rechtetor, Vorpruefung, Werkzeugrechte, Staging, Audit mit Quelle
mcp, Rahmung), und der Aufrufer gilt als Leser fremder Inhalte (#715).
Eigener Socket mcp.sock statt manager.sock: ueber den Instanz-Socket antwortet
die Verwaltung ohne Token, ueber mcp.sock gibt es nur /mcp und nur mit
MCP-Token. Lauf-Tokens nur im Speicher, enden mit dem Lauf; persoenliche Tokens
(hoechstens 90 Tage, widerrufbar, nur als SHA-256) in der Agentenansicht.
Transporte: HTTP auf mcp.sock, Weboberflaeche und Manager (/mcp/{instanz}),
stdio ueber ClawdDotNet --mcp-bridge (Token nur aus Umgebung oder 0600-Datei).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Eine Aufgabe, deren eigene Schaetzung (gemessen, Geschwister oder Autor)
ueber der Haelfte der Tageskostengrenze liegt, bekommt zuerst einen
Planungslauf: teilen (Teile unter der Elternaufgabe) oder Sonderbudget
beantragen. Danach wartet sie auf ihre Teile bzw. die Freigabe und laeuft
einmal zum Zusammenfuehren.
Sonderbudget ueber Escalation.request_budget, ausnahmslos freigabepflichtig
(auch gegen Werkzeugkonfiguration und Dauerfreigabe). Laeufe im Baum ziehen
den Topf statt der Tagesgrenzen, tragen BudgetPot in Verbrauch und Beleg und
sind in der Kostenanalyse (nach Budget) und auf der Aufgabenkarte gesondert
sichtbar. Aufgebraucht zaehlen sie wieder gegen den Tag.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Eine einmalige Aufgabe mit fill_by (spaetestens bis) statt Termin laeuft,
wenn der Tag Budget uebrig laesst: nach regulaerer und nachgeholter Arbeit,
nur wenn nichts vom Agenten wartet, bevorzugt ab 18 Uhr, und nur wenn ihre
eigene Schaetzung in den Spielraum aus #716 passt. Kurz vor der Frist wird
einmal ein Mensch gefragt; nach der Frist laeuft sie als regulaere Arbeit.
Ehrliche Schaetzung (TaskCostEstimator): eigene Laeufe, dann Geschwister
unter derselben Elternaufgabe, dann die Angabe des Autors (als Schaetzung
gekennzeichnet), zuletzt das Mittel des Agenten.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Aktionen describe (alle Spalten einer freigegebenen Tabelle, mit dem Satz, dass nicht
Genanntes nicht existiert) und tables (freigegebene Tabellen, vorhanden oder fehlend)
- "Unknown column" / "no such table" usw. werden mit dem Vorhandenen beantwortet -
MySQL, Postgres, SQL Server, SQLite; nur fuer freigegebene Tabellen
- SQLite als Datenbanktyp; die Abfragen schreibt das Werkzeug selbst, PRAGMA bleibt im
Agenten-SQL verboten
- MongoDB: describe nennt die Felder aus den Dokumenten
- describe/tables sind Lesezugriffe (Freigabeschluessel select), Vorpruefung der Tabelle
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- /api/cases (offen/alle), /api/cases/{id}/decide, /api/cases/{id}/statement, /api/decisions
- Ansicht "Vorgaenge": offene Faelle mit Verlauf je Ebene (Lauf-Links), Frist und
"Mensch gerufen"; Reiter Beschluesse mit Reichweite; Zaehler in der Seitenleiste
- Konzept Abschnitt 5: Umsetzung
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Cases/Decisions in der Instanz-DB; CaseDesk fuehrt die Regeln, der Brett-Task traegt
den Vorgang zum jeweiligen Halter
- Eskalation nur nach oben, eine Ebene je Schritt; die Leitung entscheidet (mit Begruendung,
bindet ihren Bereich), erledigt selbst oder reicht mit Einschaetzung weiter
- Erst nachsehen: bindende Beschluesse werden vor dem Eskalieren gezeigt; dieselbe Frage
aus derselben Einheit schliesst sich dem offenen Vorgang an
- Tagesdeckel je Einheit; nach der Frist wird ein Mensch gerufen (Anschluss fuer #644)
- Konflikt: zuerst die Gegenseite, dann Zustellung an die niedrigste gemeinsame Leitung;
Ebenen dazwischen vermerkt, nicht befragt
- Fremdinhalt-Stufe (#715): Eskalation ohne eigenen Text, kein Konflikt mit Position
- Jede Ebene haengt an (#697), beim Halter gerahmt als Daten
- Escalation ist ein implizites Werkzeug jedes Agenten; Briefing nennt den Weg
- Scanner behaelt einen im Lauf gesetzten Status blockiert/abgebrochen
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Werkzeugkontext kennt Lauf und Aufgabe des Laufs (RunId, RunTaskId); die
Delegationskette traegt den Lauf des Aufrufers weiter (RunId, CallerRunId)
- Aufgaben tragen origin_run / origin_task (Datei, DB, Taskboard "Arose from"),
gestempelt, nie vom Agenten behauptet
- Kommentare nennen den Lauf, in dem sie geschrieben wurden
- Laufbeleg: CallerRunId; Laufansicht fuehrt zu "Delegiert von" und "Delegiert an"
- #677: task_update ersetzt den Rumpf nicht mehr, Abnahmekriterien aendert nur der
Ersteller; Kommentare der Fremdinhalt-Stufe auf fremden Aufgaben kommen gerahmt an
- WebUI: Herkunft auf der Aufgabenkarte mit Link zum Lauf
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- IAgentTool.ReadsForeignContent: Werkzeuge mit Aussenkontakt erklaeren sich selbst
(WebFetch, WebMonitor, DirectAPI, Mail, RocketChat, Telegram, TelegramClient,
SocialMediaManager, FTP, Database); AgentConfig.TreatAsForeignReader kann nur verschaerfen
- ReportingLine: Stufe aus den Werkzeugen, "wer steht darueber", Pruefung des Wegs nach oben
(nie Aenderungen an Aufgaben darueber, nur eine Ebene hoch, Fremdinhalt-Stufe gar kein
Freitext) und Rahmung als untrusted_content
- Engine: Nachricht und Spawn nach oben geprueft, Text der Fremdinhalt-Stufe kommt gerahmt an
- Taskboard: task_create/update/comment, reopen und die Dubletten-Notiz folgen dem Berichtsweg
- Dispatcher: Aufgaben von Agenten der Fremdinhalt-Stufe gehen gerahmt in den Lauf
- TaskReports: Erledigt-Signal und Systemmeldung (in Pruefung, blockiert, abgebrochen) an den
Auftraggeber, je Zustand einmal, gesammelt in einer offenen Aufgabe je Empfaenger
- OrgBriefing nennt den Berichtsweg; WebUI zeigt Stufe und Schalter am Agenten
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- TaskTreeWatch findet offene Aufgaben, deren ganzer Teilbaum zur Ruhe
gekommen ist: nichts laeuft, nichts wird gleich gestartet (eine todo an
einen Menschen bewegt sich nicht von selbst). Nur der oberste ruhende Baum
zaehlt. Rein und ohne Instanz pruefbar.
- Erkennen ist Code, Deuten ist Modell: Die Leitung der Einheit, zu der der
Baum gehoert (sonst die darueber, sonst ein Mensch), bekommt eine
Pruefaufgabe mit dem Baum und den typischen Fehlhalten. Sie darf Arbeit
zurueckgeben, nicht selbst nachbessern.
- Einmal je Ruhezustand: Ein Fingerabdruck des Baums im StateStore. Wer den
Stillstand hinnimmt, wird nicht erneut gefragt; erst wenn sich der Baum
bewegt hat und wieder ruht. Die Pruefaufgabe steht neben dem Baum, nicht
darin.
- Der Scanner ruft die Pruefung je Takt, sie schaut alle 30 Minuten.
Erster Baustein von #646 (Erkennen); die uebrigen Muster dort folgen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- TaskItem.ParentId, in der Datei als parent, in der DB als ParentId. Die
Elternaufgabe ist der Zweck ("wofuer"), blocked_by die Voraussetzung
("wann").
- GoalChain: Eltern bis zu acht Stufen, Zyklen brechen den Gang ab und
werden beim Setzen abgelehnt. Oben steht das Ziel der Einheit - der
obersten Aufgabe, die zu einer Einheit gehoert (ein Ziel, das ein Mensch
auf der obersten Ebene setzt, gehoert keiner), sonst der naechsten Einheit
darueber mit Ziel.
- Der Lauf einer Aufgabe bekommt den Absatz "Why this task exists" und die
Bitte, zu melden, wenn die Aufgabe ihrem Zweck nicht mehr dient.
- Taskboard-Tool: parent bei task_create/task_update, geprueft auf Existenz,
Sichtbarkeit (#684) und Zyklen; task_list zeigt "Serves".
- WebUI: Feld im Aufgabendialog, Anzeige auf der Karte; die Verwaltung
prueft wie das Tool.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- TaskBoard: das Brett einer Aufgabe wird nicht gespeichert, es folgt aus
der Organisation - Einheit des Zustaendigen, sonst des Anlegers. Offene
Aufgaben ziehen damit beim Umzug mit. Sichtbar: das eigene Brett, fuer eine
Leitung alle darunter, und was man selbst angelegt hat (nach oben
Gereichtes bleibt im Blick).
- TaskItem.CreatedBy, in der Datei als created_by und in der DB. Ein Import
aus einer Datei ohne das Feld behaelt, was die DB weiss.
- Taskboard-Tool: task_list, task_find und die Dublettenpruefung sehen nur
die eigenen Bretter - eine aehnliche Buchhaltungsaufgabe haelt keine
Marketingaufgabe auf und bekommt keinen Kommentar von dort. task_update und
task_comment antworten auf eine fremde Aufgabe wie auf eine unbekannte.
- TaskboardService.ListAsync mit Sichtfilter: erst filtern, dann kappen.
- WebUI: jede Aufgabe nennt ihr Brett, ein Filter waehlt eines aus.
- Konzept (Abschnitt 3) und Einrichtungshandbuch nachgetragen.
Ohne Einheiten aendert sich nichts - ein Brett fuer alle.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- OrgAdministration: eine neue Einheit bekommt ihren Bereich (Mitglieder:
die Einheit samt Untereinheiten, schreiben); reservierte Namen und belegte
Bereichs-Ids werden als Einheiten-Id abgelehnt. Uebergreifende Bereiche
anlegen (mit Eigentuemer), Name/Zweck/geschuetzte Ordner aendern,
Mitgliederliste ersetzen, nur leere Bereiche loeschen, nie den eigenen
einer Einheit. Eine geloeschte Einheit verlaesst alle Mitgliederlisten;
ihr Bereich geht nur, wenn er leer ist, sonst bleibt er ohne Eigentuemer.
Nachruesten des eigenen Bereichs fuer Einheiten von vor #684. Alles im
AuditLog.
- API unter /api/organisation/workspaces; die Uebersicht liefert je Bereich
Mitglieder, Dateizahl und - von der Instanz berechnet - wer hineinkommt.
- Organisationsseite: Bereiche unter der Struktur, Bearbeitung mit
Mitglieder-Editor, "Wer hineinkommt", Bereichskarte an der Einheit,
Bereiche am Agenten. Sprachschluessel en/de.
- Die Nachschau nach einem Absturz bekommt die Organisation mit, sonst
fände sie einen Aufruf in einem benannten Bereich nicht.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- WorkspaceConfig in der Instanzkonfiguration: Id, Name, Zweck,
Eigentuemer-Einheit, Mitglieder (Einheit oder Agent, Stufe Read/Write/
Manage, Untereinheiten ein/aus), geschuetzte Pfade. Das Recht steht am
Bereich, nicht am Agenten.
- OrgChart: AccessTo, WorkspacesFor, UnitWorkspace; Problems nennt
ungueltige Ids und tote Verweise. WorkspaceLayout: Bereiche liegen unter
Agents/SharedWorkspaces/<id>/, neben dem unveraenderten SharedWorkspace.
- FileRW: workspace ist ein Name - personal, shared (wie bisher ueber
sharedAccessLevel), unit (eigene Einheit) oder eine Bereichs-Id. Ein
unbekannter und ein nicht erlaubter Bereich bekommen dieselbe Antwort.
Loeschen braucht Manage wie frueher Admin. Der #662-Hinweis sucht in allen
erlaubten Bereichen.
- Mit Einheiten ist shared:/tasks/ fuer FileRW gesperrt: Aufgaben laufen
ueber das Brett, sonst umginge eine direkt geschriebene Datei Brett- und
Adressbuchpruefung. Ohne Einheiten unveraendert.
- Organisationsabschnitt im Prompt nennt die Bereiche mit Stufe und Zweck.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rueckmeldung zur Teamuebersicht: wirkte veraltet, und die Verbindungen
zwischen den Einheiten fehlten - zugeklappte Container versteckten ganze
Ebenen, man haette sich bis zum Problem durchklicken muessen.
- Jede Einheit ist immer eine Karte, verbunden als Organisationsbaum
(ELK layered, orthogonale Linien, eckige Anschluesse). Keine Ebene wird
versteckt. Zugeklappt wird nur die Agentenliste grosser Einheiten: sie
zeigt, wer Aufmerksamkeit braucht, und "+n weitere".
- Eine Linie traegt die Farbe des dringlichsten Zustands darunter - eine
rote Linie fuehrt von oben zum Problem.
- Links ein Strukturbaum mit Suche (Agent, Einheit, Modell) und
Zustandsfilter; Treffer werden hervorgehoben, der Weg dorthin geoeffnet,
der Rest abgeblendet. Enter springt zum ersten Treffer.
- Leinwand mit Punktraster, Verschieben und Zoomen, schwebende Leisten
(Live-Verbindungen, Einpassen, Zoom). Live-Verbindungen laufen von Zeile
zu Zeile, gebuendelt mit Zaehler.
- Hausstil bleibt (Radius 0, App-Akzent), hell und dunkel, bis Handybreite.
- Cytoscape und cytoscape-elk entfernt: ein Canvas-Knoten kann keine
Agentenliste, Suche oder den Hausstil tragen. Karten sind jetzt HTML.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- TeamOverview.RollUp: je Einheit die Zustaende aller Agenten darin und
darunter, offene Freigaben und der dringlichste Zustand (Urgency:
haengt > Problem > Freigabe > Budget > arbeitet > frei). Gezaehlt wird in
der Instanz, die Seite zeichnet nur.
- /api/team liefert Einheiten und je Agent Einheit und Leitung.
- team.js: Einheiten als Container, zugeklappt als Kasten mit
Zusammenfassung ("6 agents · ⚠ 1 · ✋ 1 · ▶ 2") in der Farbe des
dringlichsten Zustands. Kanten laufen zum sichtbaren Stellvertreter und
werden gebuendelt (×n); was in einer zugeklappten Einheit bleibt, wird
nicht gezeichnet. Bis 15 Agenten alles offen, darueber nur die oberste
Ebene; der Zustand je Instanz im localStorage.
- Seitenleiste fuer Einheiten: Pfad, Ziel, Mitglieder (Leitung zuerst),
Untereinheiten, Auf-/Zuklappen, Link zur Organisation.
- Layout: rectpacking trifft das Seitenverhaeltnis nur grob; es werden
bis zu vier Vorgaben probiert und die zur Flaeche passendste behalten.
- Sprachschluessel en/de.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Die zufaelligen roten Laeufe der vollen Suite (jedes Mal ein anderer Test,
zuletzt PromptHistoryTests mit einer reinen Funktion) hatten eine Ursache:
Zwanzig Testklassen riefen beim Aufraeumen SqliteConnection.ClearAllPools()
auf. Das ist prozessweit und nahm einem parallel laufenden Test die
Verbindung mitten im Oeffnen weg - ObjectDisposedException in ApplyPragmas.
- SqliteStorage.ReleasePooledConnections(pfad) leert nur die Pools der
Datenbanken unter einer Datei oder einem Verzeichnis.
- BackupService oeffnet die Quelle fuer VACUUM INTO ohne Pool: eine
einmalige Kopie soll die Datei danach nicht offen halten.
- PoolReleaseTests: die freigegebene Datenbank laesst sich loeschen, die
andere arbeitet weiter.
Vier volle Laeufe hintereinander gruen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Verschiedene_Agenten_laufen_wirklich_parallel liess die Attrappe nur mit Text
antworten: Das langsame Werkzeug lief nie, und geprueft wurde, ob drei leere
Laeufe unter 450 ms bleiben. Das bestand auch mit gegenseitig gesperrten
Agenten und schlug unter Last fehl. Nach dem Merge von #683 fiel ein Core-Test
einmal in einem parallelen Volllauf, danach in elf Laeufen nicht mehr; dieser
war der letzte mit einer engen Wanduhr-Schwelle. Jetzt ruft jeder Agent das
Werkzeug auf, und bewiesen wird die Ueberlappung (MaxConcurrent > 1).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- /api/organisation: Baum (Einheiten mit Pfad, Tiefe, eigener und
wirksamer Obergrenze, Vorgaben; Agenten mit Einheit, Leitung, effektiver
Leitung, Werkzeugen, Budget), Probleme der Struktur, bekannte Werkzeuge.
Anlegen, Aendern, Loeschen, Leitung, Umzug von Agent und Einheit,
Obergrenze, Sammelwerte mit Vorschau. Umzug und Obergrenze kennen
preview=true; die Entscheidung trifft allein OrgAdministration.
- Neue Agenten koennen ueber die API gleich in eine Einheit gelegt werden.
- WebUI #/organisation: links der Baum (oberste Ebene, Einheiten, Leitungen
mit Stern, Mitglieder), rechts die Bearbeitung. Eine Begruendung fuer das
Audit gilt fuer jede Aenderung. Wo etwas verloren gehen kann, zuerst die
Vorschau: laufende Agenten und Probleme halten an, wegfallende Werkzeuge
muessen in einem Dialog bestaetigt werden. Sammelwerte als Tabelle mit
Ausreissern markiert und abgewaehlt. Bei aktivierter Begrenzung ist
vorausgewaehlt, was von oben ohnehin erlaubt ist. Sprachpakete en/de.
Geprueft im Browser mit einem Pruefgestell (API durch Attrappe ersetzt):
Baum, Auswahl, Obergrenze mit Bestaetigungsdialog, Sammelwert-Vorschau
mit Ausreisser und das Schreiben nur der gewaehlten Agenten.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
OrgAdministration (App), damit WebUI und Desktop dieselben Regeln anwenden:
- Einheiten anlegen, umbenennen, Ziel setzen, loeschen (nur leer); Leitung
setzen (nur ein Mitglied).
- Agent umziehen: haelt fest, seit wann und woher (UnitSinceUtc,
PreviousUnitId); eine Leitung, die geht, laesst ihre Einheit ohne Leitung.
Einheit umziehen: nie unter sich selbst; die Mitglieder bleiben in ihrer
Einheit, ihre Position aendert sich, und das wird ihnen gesagt.
- Kein Umzug unter einem laufenden Agenten. Das Konzept sagt "bei gestoppter
Instanz", damit niemand mitten im Lauf andere Rechte bekommt. Die Verwaltung
laeuft in der Instanz und kann sie nicht stoppen; sie lehnt ab, solange ein
betroffener Agent laeuft. Das dient demselben Zweck, nur enger.
- Rechte-Obergrenze: beim Schreiben geprueft (SetToolEnabled, SetToolSettings,
und als Sicherheitsnetz Save() fuer den Desktop, der Werkzeuge direkt
umschaltet). Obergrenze senken und in eine Obergrenze umziehen zeigen in
der Vorschau, welche Werkzeuge wegfallen, und brauchen dafuer eine
ausdrueckliche Bestaetigung.
- Sammelwerte (Tagesbudget, Tokens, Modell, whenExhausted) mit Vorschau fuer
die Einheit samt Untereinheiten: ein Wert je Agent oder ein verteilter
Gesamtbetrag im Verhaeltnis der bisherigen Werte. Ausreisser (Faktor 3 zum
Median der anderen) sind markiert und standardmaessig nicht gewaehlt.
Geschrieben wird nur, was gewaehlt ist; die Einheit merkt sich den Wert nur
als Vorgabe fuer neue Mitglieder.
- Ein neuer Agent, der direkt in eine Einheit gelegt wird, bekommt deren
Vorgaben; ein umgezogener behaelt seine Werte.
- Jede Strukturaenderung steht mit Begruendung im Audit (Quelle "admin",
Werkzeug "Organisation").
Der Organisationsabschnitt nennt der Leitung jetzt auch, wer die Einheit
kuerzlich verlassen hat und wohin: Die abgebende Leitung wird unterrichtet,
nicht nur die aufnehmende.
Tests: OrgAdministrationTests (16). 1.333 gruen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Durchgesetzt vom Code, nicht nur im Prompt beschrieben:
- Nachricht und Spawn an einen Agenten ausserhalb des Adressbuchs werden vor
jedem Modellaufruf abgelehnt; die Antwort nennt den offenen Weg (die eigene
Leitung, sonst @human).
- list_agents zeigt nur noch das Adressbuch.
- task_create und task_update pruefen die Zuweisung an einen Agenten gegen
dasselbe Adressbuch; sonst liesse es sich ueber eine Aufgabe umgehen.
- Die Delegationstiefe folgt der Tiefe des Baums (Tiefe + 1), der
eingestellte Wert bleibt Untergrenze.
Unterrichtet werden, wie das Konzept verlangt:
- OrgBriefing erzeugt einen Abschnitt "# Organisation" im Systemprompt:
Einheit mit Pfad und Ziel, seit wann (mit Hinweis, wenn frisch), die
effektive Leitung oder "@human", als Leitung die Untereinheiten und neue
Mitglieder, und wen man sonst erreicht. Er ist immer wahr, weil er aus dem
Baum kommt; ein Umzug aendert ihn von selbst.
- In einem laufenden Chat wird nur dieser Abschnitt ersetzt; der uebrige
Systemprompt bleibt, wie er war (#193).
- Ohne Einheiten gibt es keinen Abschnitt und keine Einschraenkung. Bestehende
Instanzen behalten ihren Prompt und ihren Prompt-Cache.
AppHost setzt den Organisationsbaum als Provider (frisch je Frage, eine
Aenderung gilt ab dem naechsten Lauf) und protokolliert Probleme der Struktur
beim Start.
Tests: AddressBookEnforcementTests (10), AssignmentReachTests (4). 1.317 gruen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- UnitConfig (Id, Name, ParentId, LeaderAgentId, Goal, ToolCeiling, Defaults)
in der Instanzkonfiguration neben den Agenten; AgentConfig.UnitId und
UnitSinceUtc. Bewusst Konfiguration statt Datenbank: Die Werkzeugrechte der
Agenten stehen schon dort, die Wahrheit ueber einen Agenten bleibt an einem
Ort. Strukturaenderungen gehen ins Audit (Stufe 3).
- OrgChart: Pfade, Tiefe, Leitung, effektive Leitung (die naechste Leitung
darueber, wenn die eigene Einheit keine hat oder man sie selbst leitet),
Adressbuch, Delegationstiefe aus dem Baum (Tiefe + 1, der eingestellte Wert
bleibt Untergrenze), Rechte-Obergrenze als Schnittmenge entlang des Pfades,
und eine Liste der Probleme (unbekannte Verweise, Zyklen, Leitung ist kein
Mitglied, Werkzeuge ueber der Obergrenze).
- Adressbuch: eigene Einheit und effektive Leitung; als Leitung die
Leitungen der Untereinheiten (bei leitungslosen Untereinheiten deren
Mitglieder), der Geschwistereinheiten und die eigene Leitung; die oberste
Ebene und die Leitungen der obersten Einheiten sehen sich gegenseitig. Jede
Linie ist in beide Richtungen begehbar. Ohne Einheiten sieht jeder jeden,
wie bisher.
Tests: OrgChartTests (20) am Onlinehandel-Beispiel aus dem Konzept.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Wer arbeitet, wer hat in den letzten Sekunden wen erreicht, und wo klemmt es,
auf einen Blick. Stufe 0 kommt ohne Einheiten aus; mit #683 werden die Agenten
zu aufklappbaren Containern, und die Ansicht faellt mit #688 zusammen.
Kern:
- AgentActivity: fuehrt die laufenden Laeufe (Beginn, Quelle, Aufgabe,
Aufrufer) und die letzten Verbindungen (begrenzt auf 500), meldet Start,
Ende und Verbindung als Ereignis. Vorher war nur ein Lauf ueber ChatAsync
"laufend"; ein frischer Lauf (@new) war unsichtbar, und niemand hielt fest,
wer wen gerufen hatte.
- Die Engine meldet beide Einstiege an; "arbeitet" beginnt hinter dem
Agententor.
Anwendung:
- TeamOverview stellt den Lagebericht zusammen. Die Zustaende entscheidet der
Code aus erfassten Tatsachen: laufender Lauf, offene Freigabe, Status des
letzten Belegs, Laufzeit gegen den Median des Agenten (haengt ab dem
Dreifachen, fruehestens nach 5 Minuten, ohne Verlauf nach 15). Rangfolge:
haengt, wartet auf Freigabe, arbeitet; Problem und Budget nur, solange
nichts Neues laeuft.
Web:
- GET /api/team, Ereignis "activity" (started, finished, link); das Ereignis
"run" traegt jetzt die Agenten-Id.
- Ansicht #/team mit Cytoscape.js und ELK (bei Bedarf geladen): Layout aus
der Struktur statt von Hand, Farbe und Symbol je Zustand, Kanten verblassen
nach 30 s, Klick oeffnet eine Seitenleiste (laufende Laeufe, Freigaben,
letzter Lauf im Wortlaut) mit "Freigaben oeffnen" vorne, danach Chat und
Laeufe. Sprachpakete en/de.
- Ein Layout, das lief, solange die Flaeche noch 0 px breit war, wird neu
gerechnet, sobald sie eine Breite hat (im Pruefgestell gefunden).
Geprueft im Browser mit einem Pruefgestell (API und Ereignisstrom durch
Attrappen ersetzt): sieben Agenten in allen Zustaenden, Seitenleiste,
Live-Kante und Verblassen.
Tests: AgentActivityTests (8), TeamOverviewTests (14). 1.283 gruen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Mit text=auto haette Git die Dateien unter Windows beim Auschecken auf CRLF
umgeschrieben, und die SHA-256-Werte in vendor/README.md stimmten nicht mehr.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fuer die Teamuebersicht (Lagebild, #711), auf Freigabe des Nutzers. Als Dateien
im wwwroot statt ueber ein CDN, weil die Zielmaschine womoeglich kein Internet
hat (WebUI-Leitfaden).
- cytoscape 3.34.3 (MIT), elkjs 0.9.3 (EPL-2.0), cytoscape-elk 2.3.0 (MIT)
- aus der npm-Registry, Tarballs gegen dist.integrity (SHA-512) geprueft
- elkjs bewusst 0.9.3: cytoscape-elk 2.3.0 verlangt ^0.9.3
- Lizenztexte daneben, vendor/README.md mit Version, Herkunft und SHA-256
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Freigegebene_Werkzeuge_laufen_tatsaechlich_gleichzeitig pruefte neben dem
Hoechststand gleichzeitiger Aufrufe auch eine Laufzeit unter 750 ms. Am
2026-09-24 schlug sie nach dem Merge von #716 mit 927 ms fehl, als die
Testprojekte parallel liefen; beim erneuten Lauf war sie gruen. Die Zeit misst
die Last der Maschine, nicht die Engine. Der Hoechststand bleibt als Nachweis.
Vier volle Durchlaeufe danach ohne Fehler.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- TaskSchedule.OccurrenceTimesBetween liefert die Zeitpunkte der restlichen
Laeufe; OccurrencesBetween zaehlt sie nur noch.
- BudgetHeadroom implementiert IBudgetOutlook: Die restlichen geplanten Laeufe
des Tages werden in zeitlicher Reihenfolge durchgegangen, je Agent mit
Grenze und fuer die Instanz, bis zum ersten Lauf, der das Budget verbraucht
vorfaende. Das spiegelt die Pruefung beim Start eines Laufs. Spaetwerk
zaehlt nicht mit, es laeuft ohnehin nur im Spielraum.
- Der Scanner schaut alle 30 Minuten voraus und nennt je Agent und Tag einmal,
wann das Budget ausgeht und wie viele der geplanten Laeufe dann ausfallen,
solange noch Zeit ist, nachzulegen oder zu entscheiden, was wartet.
Die Meldung steht vorerst im Protokoll (Warnung). Der Weg zum Menschen ueber
einen Kanal gehoert zu #646, die Anzeige ins Lagebild (#711).
Tests: 4 neu fuer die Vorschau. 1.261 gruen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- TaskSchedule.OccurrencesBetween zaehlt, wie oft eine Aufgabe bis zu einem
Zeitpunkt noch laeuft, einschliesslich eines jetzt faelligen Laufs.
- BudgetHeadroom (ILateRunGate): Ein mitgenommener oder nachzuholender Lauf
startet nur, wenn er in den Spielraum passt: Grenze minus Verbrauch minus
Reservierung minus Bedarf der restlichen geplanten Laeufe bis Mitternacht
minus 10 % Reserve. Das gilt je Agent und je Instanz, fuer Kosten und Tokens.
Anderes Spaetwerk zaehlt nicht als Bedarf, sonst blockierten sich
mitgenommene Aufgaben gegenseitig.
- Der Scanner fragt den Spielraum nur fuer Spaetwerk und protokolliert, wenn es
warten muss. Die Engine gibt ihren BudgetGuard heraus, damit Scanner und
Engine dieselben Reservierungen sehen.
- Ersetzt den pauschalen 25-%-Anteil aus dem Konzept (dort nachgezogen): Ein
fester Anteil ist an vollen Tagen zu viel, an ruhigen zu wenig.
Drei weitere stille Kappungen bei 500 beseitigt (ListAllAsync, ungekappt):
Kostenprognose (Aufgaben ueber 500 fehlten), Waisenabgleich beim Import und
task_find aus #674, wo Dubletten unter aelteren Aufgaben mit niedriger
Prioritaet unsichtbar wurden.
Tests: BudgetHeadroomTests (9), Scanner-Pforte (1), Dublette hinter 500
Aufgaben (1). 1.257 gruen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Der offene Rest aus #682: Jeder Lauf pruefte das Budget einzeln gegen den
bisher erfassten Verbrauch. Laufende Laeufe waren unsichtbar, gleichzeitig
startende passierten die Pruefung gemeinsam und ueberzogen gemeinsam.
- BudgetGuard.ReserveAsync prueft und reserviert unter einer Sperre. Die
Reservierung ist der Mittelwert der letzten 20 Laeufe des Agenten (Laeufe
ohne Verbrauch zaehlen nicht mit) und gilt, bis der Verbrauch des Laufs
erfasst ist.
- Gegen die Grenze zaehlt: verbraucht + in laufenden Laeufen reserviert. Die
eigene Schaetzung eines Laufs zaehlt bewusst nicht mit; ein einzelner Lauf
wird weiter nur abgelehnt, wenn das Budget schon verbraucht ist. Sonst fiele
eine kleine Aufgabe wegen eines grossen Durchschnitts aus.
- Gilt fuer Kosten- und Tokengrenze, je Agent und je Instanz.
- Die Ablehnungsmeldung nennt den reservierten Anteil, sonst wirkte "0,60 von
1,00 USD verbraucht" als Ablehnungsgrund falsch.
- IUsageRepository.GetRecentForAgentAsync, mit leerer Vorgabe im Interface,
damit bestehende Attrappen unberuehrt bleiben.
Tests: BudgetReservationTests (8 neu), darunter zehn gleichzeitige Starts, von
denen genau vier passieren. 1.246 gruen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bisher teilte sich eine Budgetablehnung den Ausgang NichtGelaufen mit dem
Herunterfahren. Einmalige Aufgaben wurden den Rest des Tages alle 30 Minuten
erneut abgelehnt (jedes Mal ein Beleg) und liefen nach Mitternacht still zu
Lasten des neuen Tages. Wiederkehrende verfielen still.
- TaskLauf.KeinBudget als eigener Ausgang; der Dispatcher bildet
BudgetExceeded darauf ab.
- Vier Felder an der Aufgabe: BudgetMissCount, LastBudgetMissAt,
DeferredUntil, CatchUpPending (Spalten werden fuer bestehende Datenbanken
nachgeruestet).
- Einmalige Aufgaben werden mitgenommen: Der Termin bleibt erhalten, faellig
ist die Aufgabe wieder ab der naechsten lokalen Mitternacht, nicht vorher.
- Wiederkehrende Aufgaben folgen der Regel des Agenten
(budget.whenExhausted): expire vermerkt den Ausfall und laesst den Termin
verfallen; catchUpOnce fasst alle verpassten Termine zu einem Nachholauf am
naechsten Tag zusammen. Ein regulaer faelliger Termin deckt das Nachholen
mit ab, es bleibt bei einem Lauf.
- Der neue Tag hat Vorfahrt: Mitgenommenes und Nachholaeufe kommen nach allem
regulaer Faelligen, unabhaengig von der Prioritaet.
- Beim ersten Takt eines neuen Tages eine Zusammenfassung je Agent im Log.
- Sichtbar: Die Aufgabenkarte der WebUI zeigt Ausfaelle, Mitnahme und
Nachholen; die Regel ist im Desktop je Agent einstellbar. Nebenbei sind
"Next:"/"Last:" auf der Karte ins Sprachpaket gewandert.
Stufen 2 bis 4 (Reservierung, Spielraum statt pauschalem Anteil, Vorbeugen)
folgen.
Tests: BudgetMissTests (9 neu). 1.238 gruen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Festlegung des Nutzers: Einheiten-Einstellungen sind entweder Sammelwerte, die in
die Agenten geschrieben werden (Vorgabe nur fuer neue Mitglieder, Warnung bei
Ausreissern wie Spezialisten), oder Regeln ohne Gegenstueck am Agenten
(Rechte-Obergrenze, beim Schreiben geprueft; Parallelitaet je Einheit).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Zeitlich flexible Arbeit mit Frist statt Termin fuellt ungenutztes Tagesbudget
(Backfilling); ob Platz ist, entscheidet der Code aus Restbudget und Prognose.
Grossaufgaben werden geteilt oder bekommen ein vom Menschen freigegebenes
Sonderbudget als eigenen Topf.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 8a: Was liegen bleibt, wenn das Budget endet. Ist-Zustand nachgesehen
(einmalige Aufgaben werden still nachgeholt, wiederkehrende verfallen still),
Vorschlag expire / catch_up_once / carry_over je Agent, der neue Tag hat
Vorfahrt, Vermerk an der Aufgabe und als Tageszusammenfassung, Vorbeugen
ueber die Prognose aus #608, Budgetreservierung als Rest aus #682.
- 3: Festlegung des Nutzers, dass Einheiten keine eigene Konfiguration
speichern; Einstellungen fuer eine Einheit werden gesammelt in die Agenten
geschrieben. Drei Kollisionen als offen markiert: Rechte-Obergrenze,
Parallelitaet je Einheit, Grenzen der Leitung.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Drei Fehler im Taktgeber des Taskboards, zwei gemeldet, einer beim Bau gefunden:
1. Unbegrenzte Parallelitaet. Jede faellige Aufgabe startete sofort. Bei
Cron-Terminen auf runden Zeiten hiess das: alle Agenten gleichzeitig, und
alle Laeufe passierten die Budgetpruefung gemeinsam, weil sie je Lauf vor
dem Start laeuft. Neu: maxParallelTaskRuns je Instanz (Vorgabe 4). Der Rest
wartet, sortiert nach Prioritaet und dann nach Faelligkeit.
2. Stille Kappung. Die Kandidaten kamen ueber ListAsync mit Limit 500; darueber
fielen Termine lautlos aus dem Takt. Neu: ListRunnableAsync liefert alle
Aufgaben auf todo, ungekappt. Muessen Aufgaben warten, steht das im Log,
allerdings nur, wenn sich die Zahl aendert.
3. Der Takt wartete auf jeden Lauf, den er startete. Ein zehnminuetiger Lauf
hielt damit jeden anderen Termin zehn Minuten an, und mit einem Deckel
haetten die freien Plaetze leer gestanden. Neu: Die Schleife startet und
wartet nicht; DisposeAsync wartet stattdessen auf die laufenden Laeufe.
Beansprucht wird nur, was sofort starten kann. Alles andere bleibt auf todo,
sonst liefe beim Warten der Lease ab und die Aufgabe wuerde ein zweites Mal
beansprucht. Ein Cron-Termin geht dadurch nicht verloren, weil DueOccurrence
bis zum letzten Lauf zuruecksucht. Ein von Hand gestarteter Lauf wartet auf
keinen Platz, belegt aber einen.
Bleibt offen: Bis zu maxParallelTaskRuns Laeufe koennen die Budgetpruefung
weiterhin gemeinsam passieren. Die Luecke ist damit begrenzt, aber nicht
geschlossen; dafuer braeuchte es eine Reservierung vor dem Lauf.
Tests: ScannerCapacityTests (9 neu). 1.229 gruen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 7a Fremde Laufzeiten: Claude Code u. a. als Laufzeit der
Entwicklungsabteilung; gilt als weniger vertrauenswuerdig (Worktree/
Sandbox, Freigabelisten statt Rechte-Umgehung, Ergebnis ist ein Vorschlag,
nach aussen nur ueber den ClawdDotNet-MCP-Server). Vorbehalte Kontingent
und Nutzungsbedingungen als offene Entscheidung.
- 9a Von Paperclip gelernt: Zielkette mit Pruefung ruhender Aufgabenbaeume,
Rueckmeldung nach Vertrauensstufe (fremder Text steigt nicht in der
Hierarchie auf), Courier Pattern; bewusst nicht uebernommen: Rechte-
Umgehung als Voreinstellung, firmenweite Sichtbarkeit.
- 10a Das Lagebild: Teamuebersicht mit Layout aus der Struktur,
aufklappbaren Einheiten, Problemzustaenden aus dem Code und Seitenleiste
vor dem Chat; Stufe 0 ohne Einheiten.
- Reihenfolge, offene Entscheidungen und Itemliste nachgezogen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Umbau durch Gemini Flash, Durchsicht und Nacharbeit durch Claude.
Umfang:
- Desktop: LocalizationManager (JSON-Pakete, Rueckfall auf Englisch,
Umschalten zur Laufzeit), Localize-Markup-Erweiterung, Sprachwahl in den
Einstellungen (AppSettings.Language, Vorgabe "en"); 317 Schluessel je Sprache
- WebUI: alle Ansichten auf t()/data-i18n, 656 Schluessel je Sprache
- Agenten-Werkzeuge: Beschreibungen, Schemata und Meldungen auf Englisch
- Tests an die englischen Meldungen angepasst, keine Pruefung abgeschwaecht
Nacharbeit bei der Durchsicht:
- ~25 Kommentarbloecke mit Begruendungen waren ersatzlos entfallen, darunter
sicherheitsrelevante (NTFS-Datenstrom beim shared:-Praefix, Bremse gegen
Agentenschleifen, doppelter POST beim Anlegen einer Instanz). Wieder
eingesetzt: auf Englisch, wo die Datei umgestellt ist, sonst im Wortlaut.
- Drei WebUI-Schluessel fehlten (logs.paused, instances.instanceOfflineError,
instances.noInstanceActiveError). Weil t() bei fehlendem Schluessel den
Schluessel selbst liefert, griff der "|| err.message"-Rueckfall nie — die
Oberflaeche haette den Schluesselnamen angezeigt.
Geprueft: Schluesselgleichheit en/de, Platzhalter je Schluessel, jeder im
Code benutzte Schluessel vorhanden, node --check fuer alle Module,
1.220 Tests gruen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Aus dem Dauerbetrieb der Testinstanz entstanden, 0.1.11 bis 0.1.15:
Freigaben und Aufgaben
- Freigaben werden gebuendelt statt einzeln geweckt (#643); das Freigabemodell
liegt in den Werkzeugrechten des Agenten (#641), Dauerfreigaben inklusive.
- Sammel-Lesen fuer FileRW (#663) und der Hinweis auf den anderen Workspace
(#662) - beide aus Laeufen, die an der Schrittgrenze starben.
- list sortiert, deckelt und nennt die Gesamtzahl (#673). Die Betriebskontrolle
hatte vorhandene Dateien als fehlend gemeldet, weil 105 Eintraege unsortiert
ankamen. Dabei fiel auf, dass ein Suchmuster aus dem Verzeichnis herausfuehren
konnte (#675).
- task_find und eine Dublettenbremse (#674): derselbe Befund ist keine zweite
Aufgabe.
Sichtbarkeit
- Prompt-History mit Aufbewahrung je Agent und Verbrauchsauswertung (#660).
Sie hat #673 gefunden - erster Nutzen am zweiten Tag.
- Englisch als Hauptsprache neuer Module, Texte ueber Sprachpakete (#661).
Konzepte, noch nicht gebaut
- docs/Organisation-Konzept.md: Einheiten, Eskalation, Konflikt und Beschluss,
Besprechung, Abstimmung, Doctrine, Kostenanalyse je Einheit. Die Regel
"hoechstens fuenf Agenten" ist zurueckgezogen - quadratisch steigen die
Verbindungen, nicht die Agenten.
- docs/Basisagenten-Konzept.md, docs/Werkzeugproben-Konzept.md.
- docs/Security-Konzept.md um die Zugangsdatenverwaltung ergaenzt und erstmals
versioniert.
Offen und vorgemerkt: #682 (Parallelitaet deckeln, stille Kappung), danach die
Einheiten aus dem ORG-Block.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Begruendung zum Vergleich vom 2026-09-18 (OpenClaw 2.0, Grok Bot) lag
unversioniert im Arbeitsbaum, zusammen mit der erzeugten Kopie vom
2026-09-19. Beides gehoert ins Repository - die Begruendung, weil sie von
Hand geschrieben ist und bleibt, die Kopie, weil sie den Stand zeigt.
Der Block zwischen den dc:roadmap-Markern bleibt erzeugt und wird beim
naechsten Lauf ueberschrieben; die heute angelegten Items #673 bis #704 sind
darin noch nicht enthalten.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Agent schickt Platzhalter, ClawdDotNet setzt sie im Werkzeug ein. Der
Ansatz ist richtig, loest aber weniger als er verspricht - die sieben
Luecken dazwischen sind die Arbeit. Die beiden wichtigsten: Ersetzt wird an
benannten Stellen je Werkzeug, nie als Suchen-und-Ersetzen ueber alle
Argumente; und jedes Geheimnis wird an ein Ziel gebunden, sonst schuetzt der
Platzhalter den Wert vor dem Modell und liefert ihn an den Angreifer.
Die Datei lag bisher unversioniert im Arbeitsbaum, obwohl fuenf Items
(#651-#659) ueber doc_anchor auf sie verweisen. Damit war die Begruendung
fuer niemanden ausserhalb dieses Rechners lesbar - genau das, was die
Regeln in CLAUDE.md verhindern sollen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Abstimmung zaehlt keine Meinungen, sondern erzwingt unabhaengige
Pruefungen aus verschiedenen Datenquellen. Daraus folgt die Regel, an der
alles haengt: Es wird BLIND abgestimmt. Sieht ein Stimmberechtigter die
Stimme eines anderen, stimmt ein guenstiges Modell dem zu, was es gerade
gelesen hat - aus vier Pruefungen werden eine und drei Echos. Damit ist die
Abstimmung das Gegenstueck zur Besprechung, wo jeder die Beitraege sieht.
Und eine Kehrtwende bei #700: Vorgeschlagen war eine Frist mit Kehrbesen
fuer Audit und Receipts. Richtig ist das Gegenteil. In einem Buero voller
Menschen geht taeglich verloren, warum etwas so entschieden wurde - hier
nicht. Bei hundert Agenten sind es 3,3 GB im Jahr; dafuer wirft man kein
Wissen weg. Was bleibt, ist ein Archiv: heiss und kalt trennen, verdichtete
Werte immer behalten, Geheimnisse gar nicht erst hineinschreiben, gezielt
loeschen koennen.
Folge: Die 14-Tage-Voreinstellung der Prompt-History gehoert auf unbegrenzt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Ordner SharedWorkspace wird zu SharedWorkspaces: mehrere benannte
Bereiche mit Eigentuemer und Mitgliederliste, je Einheit einer als
Normalfall, abteilungsuebergreifende ausdruecklich. Das Recht steht am
Bereich, nicht am Agenten - Marketing sieht die Ablage der Buchhaltung
nicht, und erfaehrt auch nicht, dass es sie gibt.
Zwei offene Fragen entschieden:
- Budgets bleiben am Agenten. Die Einheit rechnet auf und meldet
Abweichungen vom eigenen Verlauf. Damit entfaellt die Zuteilungsrechnerei,
und ein Umzug aendert keine einzige Grenze.
- Eine Eskalation, die nicht geloest werden kann, darf es nicht geben. Nach
einer Frist wird der Mensch gerufen, der entscheidet oder Stellungnahmen
anfordert. "Bleibt sichtbar liegen" war zu schwach.
Neu: Die Doctrine.md gibt einer Leitung ein Steuermittel neben Identity und
Soul - eine Ebene tief, kurz, gedeckelt, und freigabepflichtig, wenn der
schreibende Lauf fremde Inhalte gelesen hat.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Baum ist beliebig tief schachtelbar, und Einheiten wie Agenten muessen
sich nachtraeglich verschieben lassen - bei gestoppter Instanz, mit
Unterrichtung der Betroffenen und Eintrag im Audit. Das Konzept setzte das
schon voraus ("wer mehr Reichweite geben will, verschiebt im Baum"), ohne es
je zu beschreiben.
Beim Gegenlesen gefunden und aufgeloest:
- "Nur nach oben" gegen "zurueckgeben": Die zweite Antwort der Leitung ist
eine ENTSCHEIDUNG, die den Vorgang schliesst. Verboten ist der ungeloest
zurueckwandernde Vorgang.
- Konflikt gegen "nie ueber Ebenen hinweg": Ein Konflikt klettert nicht, er
wird zugestellt. Die Zustaendigkeit ergibt sich rechnerisch aus dem Baum;
dazwischenliegende Ebenen werden vermerkt, nicht befragt.
- Die Ausnahmen von "ein Agent kennt nur seine Einheit" stehen jetzt
vollstaendig beisammen - vier, alle lesend, keine gibt einen neuen
Gespraechspartner. Verstreute Ausnahmen vermehren sich.
- Stale Verweis "Vorbedingung fuer Stufe 4" auf Stufe 5 berichtigt, die
Kontrollpflicht vor die Oberflaeche gezogen.
Vier Punkte als zu grob markiert und mit Vorschlag versehen: Budget als
Deckel oder Zuteilung, woraus eine Freigabegrenze besteht, wie ein
Beschluss wirksam wird, was die Eskalationsgrenze tut, wenn sie greift.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Eine Meldung, die vier Ebenen durchlaeuft, wird viermal neu formuliert.
Das faellt nicht auf, weil es keinen Fehler gibt, den man finden koennte -
alle arbeiten korrekt, und die Spitze entscheidet ueber eine Nacherzaehlung
der Nacherzaehlung.
Die Regel: Jede Weitergabe haengt an, sie ersetzt nicht. Der Verweis auf
den Ursprung wandert mit, der Inhalt bleibt liegen und wird geholt, wer ihn
braucht. Eine Zusammenfassung darf danebenstehen, nie anstelle. Dieselbe
Festlegung wie beim Aufgabenrumpf (#677), hier fuer den Weg.
Beim Skriptfehler heisst das: Der Sandbox-Runner legt Exit-Code, stderr,
Aufrufparameter, Dauer und RunId unter scripts/<id>/fehler/ ab - nicht der
Agent. Der Zugang folgt dem Skript statt der Abteilung, damit der
Entwickler alle Fehlschlaege seines Werkzeugs sieht, ohne in fremde
Arbeitsbereiche zu duerfen. Durch die Befehlskette geht nur noch der
Verweis.
Nebenbei zwei doc_anchors nachgezogen, die durch fruehere Umnummerierung
ins Leere zeigten (#687, #688).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Korrektur der gestrigen Fassung: Dort stand, der zustaendige Agent schreibe
und pflege sein Skript selbst. Ein Anzeigen-Agent, der programmiert und
beliebigen Code ausfuehrt, hat Rechte, die seine Arbeit nicht braucht.
Die Lieferkette: Bedarfsmeldung mit ausgearbeiteter Beschreibung an die
eigene Leitung, von dort an die Entwicklung, dort schreiben und testen,
Pruefung und Freigabe nach #657, Zuteilung an genau diesen einen Nutzer.
Fehler gehen ueber dieselbe Kette zurueck.
Technisch folgt daraus, dass scripts.run kein Schalter sein darf, sondern
eine Liste benannter Skripte - ein Ja/Nein waere die Hintertuer, die die
Trennung gerade schliesst.
Und ein zweiter Gewinn, der als Entwurfsziel gelten soll: Der Agent, der
fremde Inhalte liest, ist nie der Agent, der ausfuehrbaren Code
hervorbringt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Korrektur der vorigen Fassung: Plattformen werden NICHT angebunden, auch
nicht als MCP-Server je Plattform - das verlagert die Pflege nur nach
aussen. Das Produkt gibt Faehigkeiten (API, Webseite, Datenbank, Mail); was
spezifisch ist, schreibt sich die Instanz selbst. Damit sind Sandbox (#654),
Shell (#196) und Skriptpruefung (#657) nicht nur Sicherheitsvorhaben,
sondern der eigentliche Werkzeugkasten. Die Reihenfolge bleibt zwingend:
erst die Sandbox, dann das Schreiben.
Neu: Eine Leitung delegiert nicht nur, sie prueft stichprobenartig (#693) -
gegen AuditLog und Transkripte, nie gegen die Selbstauskunft, denn ein
Modell hat am 14.09. dreizehn Werkzeugantworten erfunden. Aus einem Befund
folgen abgestufte Mittel: meist ein schaerferer Auftragstext, seltener ein
anderes Modell, zuletzt Stilllegung. Vorgeschlagen von der Leitung,
ausgefuehrt nach Freigabe.
Dazu der A/B-Vergleich im Betrieb (#694), gemessen an Dingen, die das
Modell nicht selbst behauptet.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Das Produkt bringt Baum, Mittel, Werkzeugkasten und Grenzen mit; welche
Abteilungen es gibt, ist eine Zeile in einer Datei. Im Code steht nirgends
das Wort "Einkauf". Daraus folgt die Organisationsvorlage (#691) - ein
ganzes Haus als weitergebbare Datei.
Der Eskalationsfall aus dem Vorschlag zerfaellt in drei Mittel (#689):
Eskalation geht nach oben, ein Konflikt wird bei der niedrigsten gemeinsam
uebergeordneten Stelle entschieden - eine Regel, die fuer jedes Organigramm
gilt, ohne dass jemand Wege konfiguriert -, und ein Beschluss ist dauerhaft,
sonst wird dieselbe Frage naechste Woche erneut durch vier Ebenen getragen.
Die Spitze ist eine Rolle, kein CEO-Agent (#690): Mensch, Agent oder Mensch
mit Frist. Wer entscheidet, fuehrt nicht aus und aendert die Struktur nicht.
Vorbedingung des ganzen Falls: Das Datenbank-Werkzeug kann heute nicht nach
dem Schema fragen (#676). "Ich finde kein Feld dafuer" ist damit eine
Vermutung, und eine Organisation soll keine Einbildungen eskalieren.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Regel im InstanceSetupGuide war in der Beobachtung richtig und in der
Folgerung falsch: quadratisch steigen die Verbindungen, nicht die Agenten.
Ein Agent, der drei Nachbarn und eine Leitung kennt, kostet gleich viel, ob
die Instanz zehn oder hundert Agenten hat.
docs/Organisation-Konzept.md haelt fest, was heute bei 50 Agenten bricht
(flaches Adressbuch, synchrones send_message, Delegationstiefe 3,
unbegrenzte Parallelitaet, Kappung bei 500, zwei Arbeitsbereiche, ein Brett,
zwei Budgetebenen, eine Freigabe-Warteschlange) und schlaegt die fehlende
Ebene vor: die Einheit.
Zwei davon sind schon heute Fehler und gehoeren sofort behoben (#682).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Zwei Nutzervorschlaege aus dem Testbetrieb, beide mit Ankern im Bestand:
Die Aufsicht ist das dritte Profil des AgentInspector (#204), neben dem
Security-Profil (#658); die Werkzeugproben fuellen Stufe 2 des Probelaufs
fuer neue Agenten (#649) und loesen den "Evals-Test-Runner" aus dem
Orchestrator-Konzept ein.
Zwei Entscheidungen tragen die Dokumente:
- Erkennen ist Code (#646), Deuten ist Modell (#680). Wer das verwischt,
bezahlt ein Sprachmodell fuers Zeilenzaehlen.
- Die Eignungsprobe gehoert zum Werkzeug, nicht in eine zentrale Liste,
und wird gegen das Audit geprueft, nie gegen die Selbstauskunft.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Betriebskontrolle im Testbetrieb meldete Stundendateien als fehlend, die
es gab: 105 Eintraege in der Reihenfolge des Dateisystems, vierzeilig als
eingeruecktes JSON. list liefert jetzt die 50 zuletzt geaenderten Eintraege,
neueste zuerst, eine Zeile je Eintrag, mit Gesamtzahl im Kopf; pattern, sort,
order und limit steuern das.
Dabei aufgefallen (#675): Directory.GetFiles wertet Trennzeichen im Muster
aus - pattern "../*" fuehrte an der Pfadpruefung vorbei aus dem Verzeichnis
heraus, in list wie in read_many. Muster mit '/', '\' oder '..' werden jetzt
abgewiesen.
Und derselbe Befund ist keine zweite Aufgabe (#674): task_find beantwortet
die Frage vor dem Anlegen, task_create legt bei gleichbedeutendem Titel einer
offenen Aufgabe keine zweite an, sondern vermerkt das erneute Auftreten an
der bestehenden. force=true geht trotzdem, Erledigtes blockiert nichts.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
#663: Neue Aktion read_many liest mehrere Dateien in einem Aufruf - entweder
paths (Liste) oder path (Verzeichnis) mit pattern. Gedeckelt auf 50 Dateien und
200.000 Zeichen; was nicht mehr hineinpasst, wird namentlich genannt, damit der
Agent gezielt nachholen kann. Anlass: Der Tagesabschluss im Testbetrieb las 24
Stundendateien einzeln und starb zweimal an der Schrittgrenze - die soll
Endlosschleifen abfangen, nicht ehrliche Arbeit.
#662: Schlaegt read oder list fehl, weil der Pfad im anderen Workspace liegt,
sagt die Fehlermeldung das - aber nur, wenn der Agent diesen Workspace auch
benutzen darf. Guenstige Modelle vergassen workspace "shared" regelmaessig und
verbrauchten mit jedem Rateversuch einen Schritt.
Dateipruefung, Endungen und Workspace-Grenze gelten in read_many unveraendert;
eine verbotene Endung wird uebergangen statt den Lauf zu kippen.
Version 0.1.14.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Prompt history: every run records its transcript (task, each model step with
tokens and cost, tool calls and results, engine follow-ups) - bounded in size,
scrubbed of recognisable secrets, system prompts stored once per text.
Retention in days per instance (default 14) and per agent (0 = never, -1 =
forever); an hourly janitor deletes what is past it, "never" also purges.
Usage analysis over run receipts: filter by period, agent, model, event, status,
cost and free text; sort by every column; totals over the whole filter; hourly
or daily series grouped by agent, model or event; markers for budget denials and
model changes; run detail with receipt, transcript, tool calls and approvals.
WebUI: Analysis > Token usage > Runs / Timeline, run detail, Prompt History with
retention settings. New code, comments and texts in English; texts come from
language packs (i18n/en.json, de.json) via modules/i18n.js. CLAUDE.md records
English as the main language.
Version 0.1.12.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
#643: Entscheidungen wecken den Agenten nur noch bei Ablehnung oder gescheiterter
Ausfuehrung, gesammelt in einer Aufgabe je Agent (5 min Ruhefenster), frisch per
@new:agent statt im fortgefuehrten Chatverlauf. Eine einmalige Aufgabe, deren Lauf
wegen Budget oder Herunterfahren gar nicht stattfand, bleibt faellig (Wiedervorlage
nach 30 min) statt mit gesetztem Marker liegenzubleiben.
#641: Rechte stehen in der Werkzeugkonfiguration des Agenten (erlaubt/verboten).
Erlaubtes laeuft, Nicht-Erlaubtes wird einzeln vorgelegt statt verweigert, Verbotenes
gar nicht erst. "Gleichartiges kuenftig erlauben" erteilt eine widerrufbare
Dauerfreigabe je Agent/Werkzeug/Operation; nach drei gleichartigen Freigaben schlaegt
die Oberflaeche sie vor. Aenderungen an Agenten bleiben ausnahmslos freigabepflichtig.
Database: Operation ist das SQL-Schluesselwort; die eigene Zugriffspruefung greift nur
noch ohne Freigabestelle (AgentToolContext.FreigabeGeprueft). WebUI: Rechte-Tabelle je
Werkzeug, Dauerfreigaben mit Widerruf.
Version 0.1.11.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
#631: Derselbe Vorschlag (gleicher Agent, gleiches Werkzeug, gleiche Argumente unabhaengig
von Schluesselreihenfolge) wird nicht erneut angelegt - der Agent erfaehrt die bestehende
Nummer. Offene Vorschlaege verfallen nach 24 h (Status Expired).
#609: Werkzeuge koennen den Freigabeschluessel aus dem Inhalt bestimmen
(IAgentTool.StagingAktion). Database: SELECT/SHOW/DESCRIBE -> query, INSERT/UPDATE/DELETE
-> write, DDL -> schema; write und schema sind freigabepflichtig. Ausgefuehrt wird nach
Statement-Art, schreibende Statements melden die Zeilenzahl.
#579: Database-Vorpruefung (Zugriffsebene, Tabellenfreigabe, SqlGuard) - was das Werkzeug
ablehnen wuerde, kommt nicht mehr in die Freigabeliste.
#610: SqlGuard ueberspringt IF [NOT] EXISTS und erkennt DESCRIBE/DESC <tabelle>.
#632: WebFetch fetch mit filter liefert aus JSON/JSONP nur passende Eintraege; beim
Blaettern durch grosses JSON empfiehlt der Hinweis den filter.
Version 0.1.10.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
#608: Ein wegen erschoepften Budgets abgelehnter Lauf hinterlaesst jetzt einen Beleg
(Status BudgetExceeded) an Aufgabe und Verlauf; die Log-Warnung kommt einmal je Agent,
Grenze und Tag. Die Kostenprognose zaehlt Ablehnungen nicht als Lauf und warnt, wenn die
geplanten Aufgaben eines Agenten sein Tagesbudget uebersteigen (API + Verbrauchsansicht).
#607: Passt schon der erste Treffer nicht in den Abruf, wird er gekuerzt (Anfang und Ende
bleiben) statt ganz zu fehlen. remember weist auf gleichnamige Eintraege ohne Schluessel und
auf Eintraege nahe der Abrufgrenze hin.
Version 0.1.9.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Im Dauerbetrieb lief die Kompaktierung bei jedem Schritt an und blieb wirkungslos:
Stufe 1 pruefte mit der rohen Schaetzung, kompaktierte nur knapp unter die Schwelle
und brach dabei jedes Mal den Prompt-Cache; der Zusammenfassungs-Aufruf fehlte im
Verbrauch. Ziel jetzt min(Schwelle, 55 % des Limits), Usage des Aufrufs geht in den Lauf.
Version 0.1.8.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- HtmlExtraktor (AngleSharp): Selektor > article (>= 40 % des Seitentexts) > main > Textdichte,
Seitenrahmen und Stoerbloecke entfernt, Ueberschriften/Listen/Tabellen/Code als Markdown,
Linkziele nur mit links=true, Metadaten (Titel, Sprache, kanonische URL, Datum)
- WebInhalt: JSON/Text/XML unveraendert, Rueckfall auf Volltext bei zu wenig Hauptinhalt,
mode=full, nextOffset fuer lange Inhalte, JSON kompakt ohne Unicode-Escapes
- RSS: limit, Beschreibungen gekappt; dataAsOf nicht mehr aus dem Date-Header
Gemessen: tagesschau-Artikel 16.000 (abgeschnitten) -> 9.635 Zeichen vollstaendig.
Version 0.1.7.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Engine: leere Antworten nachfassen, Aufgaben enden mit Ergebniszeile (EmptyResponse/Incomplete),
gleiche Fehlschlaege erkennen (RepeatedFailure), Zeitzeile vor Chatnachrichten,
Werkzeugergebnisse gerahmt, Vorpruefung vor dem Staging, Belegkosten wie RunUsage
- Staging: gescheiterte Freigaben als Failed; AgentEditor-Aenderungen freigabepflichtig,
Selbstbearbeitung gesperrt (allowSelfEdit)
- Taskboard: Termine beim Anlegen pruefen, naechster/letzter Lauf, pausieren, Sofortlauf,
Kostenprognose, Hinweis auf wachsenden Kontext; Jobs-Reiter und /api/jobs entfernt
- Release: Instanzmanager samt Weboberflaeche im Paket, setup.json fragt manager.json ab,
Token nicht mehr ins systemd-Journal
Version 0.1.6.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Nachrichten-Digest im Dauerbetrieb der Test-VM lief nie: CronExpression
verstand 'von-bis/schritt' nicht, TaskSchedule verschluckte den Fehler.
Version 0.1.5.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- #578: Abgebrochene Laeufe (Schrittgrenze, Zeitueberschreitung, Abbruch,
Ausnahme) tragen ihre bezahlten Token - vorher 0 in RunUsage, fuer das
Budget unsichtbar.
- #580: WebFetch prueft die aufgeloeste Zieladresse beim Verbinden; ein
erlaubter Name, der auf 127.0.0.1 aufloest, wird gesperrt.
- #575: Dateien entstehen unter Unix mit 0600 (AtomicFile, Protokolle,
FileRW-Anhaengen, state.db), Protokollverzeichnisse mit 0700.
- #576: SIGTERM/SIGINT beenden auch mit Fenster geordnet.
- #593: OpenRouter-Statusdienst wird gestartet.
- #589: Auftragsnachricht nennt aktuelle Zeit, Zeitzone und Termin.
- #581: Unvollstaendiges Argument-JSON erreicht das Werkzeug nicht mehr;
das Modell bekommt eine verstaendliche Rueckmeldung statt Parsertext.
- #591: Weboberflaeche liest die Felder, die API und Ereignisstrom liefern
(Freigaben, Protokoll, Taskboard mit Termin, Werkzeug-Einstellungen,
Tokennutzung); Ereignisstrom in camelCase.
- #592: Chat zeigt Nachrichten nicht mehr doppelt.
- #536 (teilweise): A2A-Antworten tragen Absender und Empfaenger, Parser
wirft nicht mehr; Datums- und Volltextfilter in Agenten-Chats.
- deploy/publish.py: Packager-Pfad net10.0, Schalter --agent-file.
- Version 0.1.4.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
AppHost.StartAsync ruft jetzt CrashRecovery. Ein geordnetes Ende
hinterlaesst nichts; ist etwas da, ist die Instanz gestorben, waehrend
Werkzeuge liefen.
Bewusst nur sichten und protokollieren, nicht ausfuehren. Ob die Wirkung
eines Aufrufs eintrat, weiss auch dieser Dienst nicht - ein automatisches
"dann eben nochmal" versendete im Zweifel die Mail ein zweites Mal.
Scheitert die Sichtung selbst, haelt sie den Start nicht auf. Eine
Instanz, die wegen einer misslungenen Nachschau nicht hochkommt, waere
schlimmer als eine, die mit einer Wissensluecke startet.
Der Aufruf sitzt in StartAsync statt in BuildCore: BuildCore ist synchron,
und die Signatur zu aendern haette durch alle Aufrufer gezogen. Blockendes
Warten in einer Fensteranwendung waere die schlechtere Loesung gewesen.
Build ohne Warnungen, 912 Tests, keine Regression.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
#553 FileRW schreibt atomar. Die Vorkehrung lag seit #241 im selben
Repository und wurde ueberall benutzt - Einstellungen, Sicherungen,
Chat-Zustand, Identity.md - nur der Weg, ueber den Agenten ihre
Arbeitsergebnisse ablegen, ging daran vorbei. Damit stand das Verhaeltnis
auf dem Kopf: geschuetzt war das Eigene, ungeschuetzt das Ergebnis.
append bleibt bewusst nicht atomar; das ginge nur, indem die ganze Datei
neu geschrieben wird, und bei einer grossen Protokolldatei waere das der
falsche Handel.
#554 Wiederaufnahme. Neuer Eintrag AuditStatus.Started, geschrieben VOR
der Wirkung und als einziger nicht "best effort" - auf ihn stuetzt sich
alles Weitere, also laeuft der Aufruf gar nicht erst, wenn er nicht
durchkommt. Neue Kennzeichnung IsRepeatable, getrennt von IsParallelSafe:
Das eine heisst "stoert keinen gleichzeitigen Aufruf", das andere
"richtet zweimal keinen Schaden an". CrashRecovery sichtet beim Start,
was offen blieb, und stuft ein - fuehrt aber nichts aus. Es sichtet und
berichtet; entscheiden soll der Aufrufer.
Dabei kippte eine alte Regel: Bisher wurde ein Abbruch bewusst NICHT
protokolliert. Das war richtig, solange es keinen Eintrag vor dem Aufruf
gab. Jetzt saehe sonst jeder Benutzerabbruch beim naechsten Start aus wie
ein Absturz - bis niemand mehr hinsieht. Deshalb AuditStatus.Cancelled.
#555 Optionale Zustandspruefung IToolStateProbe, umgesetzt in FileRW.
Unknown ist eine vollwertige Antwort, kein Fehlschlag: Ob ein SMTP-Server
angenommen hat, laesst sich nicht feststellen, und ein Werkzeug, das hier
raet, waere schlimmer als eines, das schweigt. Partial gilt ausdruecklich
nicht als geklaert - einen halb angehaengten Text sollte niemand
automatisch geraderuecken.
#556 Auswertung. ListForAgentAsync und SummarizeToolUsageAsync. Die Dauer
wird nur ueber abgeschlossene Aufrufe gemittelt; zaehlten die
Started-Eintraege mit ihrer Dauer 0 mit, saehe jedes Werkzeug doppelt so
schnell aus, wie es ist.
Nebenbei: SqliteStorage kann jetzt Spalten nachruesten. CREATE TABLE IF
NOT EXISTS allein genuegte nicht - bei einer bestehenden Datenbank tut die
Anweisung nichts, und erst das naechste INSERT waere gescheitert, im
Betrieb beim Anwender.
Vier Audit-Tests angepasst: Ein ausgefuehrter Aufruf erzeugt jetzt zwei
Eintraege statt einem. Ein Aufruf, der gar nicht erst laeuft - verweigert,
unbekannt, vorgelegt - hat weiterhin genau einen; der Beginn wird erst
nach Rechtepruefung und Staging geschrieben.
23 neue Tests, 912 gesamt, keine Regression. Build ohne Warnungen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Wurde ein Chat abgebrochen, waehrend ein Werkzeug lief, blieb im Kontext
eine assistant-Nachricht mit tool_calls stehen, auf die keine Antwort
folgte. Diese Folge lehnt die Schnittstelle mit HTTP 400 ab - der Agent
war danach nicht mehr ansprechbar.
Der Schaden wurde dabei dauerhaft gemacht: Jeder catch-Block ruft
AddChatEntry, das ruft PersistChatState, und das schreibt den Kontext
atomar auf die Platte. Das atomare Schreiben war hier keine Rettung,
sondern die Garantie, dass die kaputte Fassung heil ankommt. Ein Neustart
half nicht, weil LoadPersistedChats sie zurueckholte.
Ausloeser war durchweg Normalbetrieb: AbortChat durch den Benutzer,
LoopGuard.Timeout, oder eine Instanz, die waehrend eines Werkzeuglaufs
geordnet herunterfaehrt.
Die Antworten gehen jetzt aus einem finally raus. Auf jedem Ausgangspfad
bekommt jeder Aufruf seine Antwort, bei Abbruch eine Ersatzantwort, die
auch sagt, was passiert ist - eine leere waere formal gueltig, liesse das
Modell aber raetseln.
Zwei Tests: einer auf die Form des Kontexts, einer auf das, worauf es
ankommt - dass ein zweiter Chat danach wieder durchlaeuft. Der erste
schlug vor der Behebung fehl.
543 Tests in Core, keine Regression. Build ohne Warnungen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Fuenf Befunde mit einem gemeinsamen Fehlermodus: Keiner erzeugt eine
Fehlermeldung. Der Lauf wird fertig, das Ergebnis sieht plausibel aus,
und nur die Qualitaet ist schlechter.
#547 Der Begleittext zum Werkzeugaufruf ging verloren. AssistantWithToolCalls
baute eine neue Nachricht aus nur den Aufrufen; der Text, den das Modell
daneben geschrieben hatte, fiel weg. Damit verlor das Modell zwischen zwei
Schritten seinen eigenen Plan, und im Audit stand, dass ein Werkzeug lief,
nicht warum.
#548 finish_reason wurde nirgends gelesen. Eine an der Ausgabegrenze
abgeschnittene Antwort galt als fertiges Ergebnis. Das trifft besonders
Laeufe im Hintergrund, wo niemand zusieht. Neuer Status Truncated: Das
Teilergebnis geht weiter, aber gekennzeichnet.
#549 reasoning_details wurde verworfen. Bei Werkzeugnutzung muss der
Denkverlauf unveraendert zurueck, sonst beginnt ein Thinking-Modell jedes
Mal von vorn. Wird jetzt als rohes JSON durchgereicht - ohne Auslegung,
weil Reihenfolge und Signatur daran haengen.
#550 Die Anfrage verlangt jetzt einen Anbieter, der alle mitgeschickten
Parameter beherrscht. Ohne das durfte ein Anbieter cache_control, reasoning
oder sogar tools stillschweigend uebergehen - der Lauf lieferte dann eine
gewoehnliche Textantwort, wo ein Werkzeugaufruf hingehoert haette. Dazu
usage.include: der abgerechnete Betrag schlaegt die Eigenrechnung, die als
Rueckfallebene bleibt. Denktiefe je Agent einstellbar, Vorgabe off.
#551 Werkzeuge eines Zuges laufen gleichzeitig, sofern sie sich dafuer
freigeben. Die Vorgabe von IsParallelSafe ist false, weil die falsche
Antwort hier nicht auffaellt: Zwei schreibende Aufrufe auf derselben Datei
scheitern nicht zuverlaessig, sondern gelegentlich. Freigegeben ist bisher
nur WebFetch - es liest ausschliesslich. Die Reihenfolge der Ergebnisse
folgt den Aufrufen, nicht der Fertigstellung; daran haengen die
tool_call_id-Zuordnung und der Cache-Praefix.
27 neue Tests, 887 gesamt, keine Regression. Build ohne Warnungen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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>
SecretKeyStore.Wrap band den Hauptschluessel unter Windows per DPAPI ans
Benutzerkonto und gab ihn sonst ungewrappt zurueck - eine Zeile, die man beim
Lesen ueberspringt und die auf dem Zielsystem "im Klartext" bedeutet.
Dahinter steht jetzt ein SecretKeyRing: derselbe Hauptschluessel, mehrfach
verpackt, je Fach ein ISecretProvider (dpapi, passphrase, file). Fuer Aufrufer
aendert sich nichts - GetOrCreateKey gibt weiterhin 32 Byte zurueck. Genau dafuer
war die Naht da.
WARUM MEHRERE FAECHER UND NICHT EIN BESSERES
Ein Schluessel an der Maschine ueberlebt keinen Umzug; einer an einer Passphrase
verlangt bei jedem Start jemanden, der tippt - und Dauerbetrieb ohne Menschen ist
der Zweck (#214). Der Bund entscheidet sich nicht: Im Alltag oeffnet das
Maschinenfach ohne Rueckfrage, nach einem Umzug die Passphrase, und beide fuehren
zu DEMSELBEN Schluessel. Alle enc:v2-Werte bleiben lesbar.
Und deshalb darf die Schluesseldatei jetzt ueberhaupt in eine Sicherung: Sobald
ein Wiederherstellungsfach da ist, steht der Hauptschluessel in keiner Fassung im
Klartext darin.
Nicht zu verwechseln mit der Sicherung mit Passphrase: Die schluesselt jeden WERT
einzeln ins Archiv um, fuer den Transport einer Instanz. Das Wiederherstellungs-
fach schluesselt den HAUPTSCHLUESSEL um, damit eine bestehende Installation
weiterlaeuft - unbeaufsichtigt ueber CLAWD_SECRET_PASSPHRASE. Die Unterscheidung
steht in docs/Roadmap.md bei #190.
Beide Altformate werden uebernommen: 32 rohe Byte werden zum Fach file, ein
DPAPI-Block zum Fach dpapi. Derselbe Schluessel, nur anders verpackt.
Zwei Zusagen, mit Tests festgehalten:
- Geht KEIN Fach auf, wird abgebrochen statt ein neuer Schluessel erzeugt. Ein
neuer Hauptschluessel machte jeden bestehenden Wert wortlos unlesbar.
- Ein Umzug legt den Schluessel NICHT im Klartext ab, nur damit der naechste Start
bequemer wird.
Beim automatischen Weg wird nur hinzugefuegt, nie weggenommen; weggenommen wird
nur in SetRecoveryPassphrase, wo ein Mensch gerade getippt hat.
#190 bleibt offen: Unter Linux greift weiterhin das Fach file. Neu ist, dass es
beim Start als Warnung im Protokoll steht statt unsichtbar zu sein. Womit das
Maschinenfach dort gefuellt wird, ist Entscheidung #180 - diese Schnittstelle ist
die Stelle, an der die Antwort eingesetzt wird.
834 Tests gruen, 0 Warnungen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Mit E-M3 wanderte die Lizenzpruefung in den Manager: Eine gefuehrte Instanz prueft
nicht mehr selbst, weil der Manager es zentral getan hat. Woran sie "gefuehrt"
erkannte, war der Schalter --managed - und ein Schalter ist keine Erkennung.
ClawdDotNet --managed startete damit eine Instanz ganz ohne Lizenzpruefung. Vor
E-M3 gab es die Luecke nicht; sie ist mit der Zentralisierung entstanden.
ManagerHandshake unterschreibt Instanzverzeichnis und Ablauf mit HMAC-SHA256. An
die Signierstelle kommt der Manager nur, wenn seine Lizenzpruefung bestanden hat -
StartInstanceAsync weist vorher mit StartRefusal.NoLicense ab. Dass die
Unterschrift existiert, ist der Beweis.
- Gebunden an das Verzeichnis, und geprueft wird gegen das tatsaechliche, nicht
gegen das behauptete: Sonst unterschriebe man das Argument statt der Sache.
- Fuenf Minuten gueltig, der Ablauf geht in die Unterschrift ein.
- Ueber die Umgebung statt ueber die Befehlszeile: Eine Befehlszeile steht in
jeder Prozessliste.
- Ungueltig heisst "nicht gefuehrt", nicht Abbruch. Dann prueft die Instanz ihre
Lizenz selbst - der Weg von vor E-M3, also kein neuer Fehlerfall.
AppHost.IsManaged ist jetzt der gepruefte Befund. CanSwitchInstance und der
Wechseldialog haengen daran statt am Schalter.
Die Grenze steht ausdruecklich im Konzept (9.9): Der Schluessel liegt in jeder
ausgelieferten Programmdatei. Es geht um den gewoehnlichen Weg an der Lizenz
vorbei, nicht um jemanden mit Werkzeugen und Willen.
Abgenommen an echten Prozessen, Unterschrift fuer den Positivfall unabhaengig in
Python gerechnet: ohne Unterschrift "Lizenz erforderlich"; mit gueltiger kommt die
Instanz hoch; Unterschrift fuer ein fremdes Verzeichnis und hochgedrehter Ablauf
scheitern beide.
820 Tests gruen, 0 Warnungen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Weboberflaeche (#531): X-Instanz an der einen fetch-Stelle, Instanzauswahl in der
Kopfzeile, Verwaltungsansicht mit Anlegen/Starten/Anhalten/Fenster, Herkunft der
Ereignisse, Sicherungs- und Einstellungsansicht. 402/409/502 werden eigen behandelt.
Sicherungen im Manager (#530): Auflisten, Anlegen, Wiederherstellen, Loeschen. Das
Zurueckspielen haelt die Instanz vorher an und startet sie danach wieder.
Geordnetes Ende (Konzept 9.8). Zwei Befunde waren der Anlass:
Der Manager konnte eine Instanz MIT FENSTER nie geordnet beenden.
Control.ShutdownRequested war nur in HeadlessRun verdrahtet, nicht in der
Avalonia-Anwendung - und ein Fenster ist die Vorgabe. Die Bitte wurde mit 202
beantwortet, niemand hoerte zu, und der Manager schoss den Prozess nach Ablauf
seiner Frist jedes Mal ab.
InstanceSupervisor.StopAsync hielt Socket-Schweigen fuer einen Todesnachweis und
meldete "beendet", ohne den Prozess anzufassen. Bei einer verstummten Instanz ist
der Socket von vornherein still - der Neustart haette einen zweiten Prozess auf
dieselbe state.db gesetzt. Genau der Schaden, gegen den #528 gebaut ist.
- ShutdownCoordinator: erst die Tuer schliessen, dann auf offene Arbeiten warten,
Frist zwei Minuten. Vorher brach TaskScanner.DisposeAsync mitten in ProcessAsync
ab, sodass die Aufgabe bis zum Lease-Ablauf auf "running" stehenblieb.
- GET /api/instanz/puls hinter dem Socket-Gate: Phase und offene Arbeiten. Weiter
gefragt statt gemeldet - ein Puls, den die Instanz von sich aus schickt, fehlt
genau dann, wenn sie haengt.
- Eskalationsleiter: drei Durchgaenge ohne Antwort, einmal um ein Ende bitten,
nach 30s beenden und den Vollzug abwarten, gemeldet als Absturz.
- EnsureDeadAsync vor jedem Start.
Weiteres aus dem Review:
- .gitignore verankert: "Instances/" passte auch auf src/ClawdDotNet.Core/Instances/.
InstanceEndpoint.cs und InstanceLayout.cs waren dadurch nie eingecheckt.
- Das WebUI-Token stand im Protokoll des Managers. Konsole ja, Datei nein.
- Ein Klick auf "Instanz anlegen" loeste requestSubmit() zweimal aus.
- [Obsolete] auf WebServerPort wieder entfernt: sechs Warnungen, die niemand
abstellen konnte, solange E-M5 nicht fertig ist.
- Die Wiederherstellung bricht nicht mehr ab, wenn der Browser weggeht.
- Entwicklungspfade zum Instanzmanager aus Segmenten statt mit Rueckstrichen, und
der Port kommt aus manager.json statt fest aus der Zeile.
Offen und gemeldet: --managed hebelt die Lizenzpruefung aus (#535).
806 Tests gruen, 0 Warnungen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der C#-Teil des Instanzmanagers ist fertig; was fehlt, ist die
Oberflaeche. Abschnitt 11 im Konzeptpapier ist die Uebergabe dafuer: der
Auftrag in einem Satz, die harte Grenze (keine .cs-Datei, git status darf
nur wwwroot zeigen), die vollstaendige API mit den Antwortcodes, die eine
eigene Behandlung verdienen, eine Reihenfolge, zwei Fallen und die drei
Punkte, die ausdruecklich liegen bleiben, weil sie C# sind.
Der WebUI-Leitfaden war an vier Stellen ueberholt und haette den naechsten
Agenten in die Irre geschickt: wwwroot liegt nicht mehr in
ClawdDotNet.Web, die Oberflaeche laeuft nicht mehr im Prozess der Instanz,
Port und Token stehen in manager.json statt in InstanceSettings.json, und
es gibt nicht mehr ein /api fuer eine Instanz. Ein Korrekturblock steht
jetzt vorweg und verweist auf Abschnitt 11; der Rest des Leitfadens - kein
innerHTML, kein Paketmanager, Token nur im sessionStorage, Farben aus
app.css - gilt unveraendert.
Die Arbeit selbst ist #531 und steht auf der Roadmap. Was nur in einer
Datei steht, ist keine eingeplante Arbeit.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Entschieden vom Benutzer am 2026-09-08. Der Schalter heisst
autostartByManager und steht in InstanceSettings.json - bei der Instanz,
nicht beim Manager.
ZWEI DINGE IN EINEM SCHALTER, weil es dieselbe Zusage ist: Der Manager
startet diese Instanz, wenn er selbst hochkommt, und er startet sie wieder,
wenn sie abstuerzt. Ohne den Schalter ruehrt er nichts an - ein Manager,
der nach einem Neustart der Maschine alles hochfaehrt, was er findet,
startet auch das, was jemand mit Absicht angehalten hat. Ausgeschaltet
vorbelegt.
DER SICHERUNGSAUTOMAT ist der eigentliche Inhalt. Wieder hochzufahren ist
die einfache Haelfte; die schwierige ist zu erkennen, wann man es lassen
muss. Nach drei Neustarts in zehn Minuten (maxRestartsInWindow,
restartWindowMinutes) setzt der Manager aus und meldet es. Die Instanz
bleibt dann aus, bis jemand sie von Hand startet - und dieser Start raeumt
den Zaehler ab, denn wer von Hand startet, hat entweder etwas geaendert
oder weiss, was er tut. Das Zeitfenster wandert: Eine Instanz, die einmal
im Monat abstuerzt und wieder hochkommt, laeuft nie in die Grenze.
Nur bei einem Absturz, nicht wenn eine Instanz verstummt. Eine stumme
Instanz lebt noch; sie neu zu starten hiesse, sie erst abzuschiessen, und
ob der Manager das von sich aus darf, ist nicht entschieden. Als offene
Frage aufgeschrieben - genau dieser Zustand war der Anlass des Vorhabens.
Der Schalter steht bei der Instanz, weil er eine Eigenschaft dieser Instanz
ist und weil die Instanzdatei dem Instanzprozess gehoert: Sie vom Manager
schreiben zu lassen, waehrend die Instanz laeuft, waeren zwei Schreiber auf
einer Datei. Der Manager liest ihn nur; geaendert wird er auf der
Einstellungsseite der Instanz.
EIN DEFEKT, den erst diese Tests gezeigt haben: StartAsync gab "laeuft
schon" zurueck, wenn die Aufsicht die Instanz fuer laufend hielt - ohne
nachzusehen. Zwischen zwei Aufsichtsdurchgaengen liegen aber Sekunden, und
in denen kann sie wegbrechen. Wer in dieser Luecke "starten" verlangte,
bekam einen Erfolg, hinter dem nichts stand, und der naechste Durchgang
meldete einen Absturz, den niemand mehr erwartete. Jetzt wird gefragt,
bevor zugestimmt wird.
UND EIN TESTDOUBLE, das die Wirklichkeit nicht abbildete: Der falsche
Socket antwortete unabhaengig davon, ob ein Prozess lief. Damit war jeder
Testaufbau, der die Antwort vor dem Hochfahren hinterlegte, stillschweigend
ein anderer Test als beabsichtigt - eine Antwort sagt dem Manager "laeuft
bereits", er uebernimmt, und der Starter wird nie angefasst. Dreimal
passiert. Der falsche Socket haengt jetzt am falschen Starter.
Sicherungen im Manager sind als #530 zurueckgestellt, mit Ausloeser.
Vorab entschieden ist dort nur eines: Zurueckspielen ausschliesslich bei
inaktiver Instanz.
19 neue Tests. Build ohne Warnungen, 793 Tests gruen, 8 uebersprungen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Vorher hiess "Instanz wechseln": Der laufende Prozess faehrt sich herunter
und startet sich mit einer anderen Instanz neu. Wer wechselte, beendete
zwangslaeufig die Instanz, aus der heraus er es tat - und genau dabei hat
sich die Anwendung am 2026-09-08 aufgehaengt (#529). Jetzt laufen alle, und
es kommt eine nach vorn.
Neu: POST /api/instanz/fenster, wieder ausschliesslich ueber den Socket.
Die Instanz holt ihr Fenster SELBST nach vorn; der Manager kennt kein
Fenstersystem und soll keines kennen. Kopflos laeuft die Bitte ins Leere,
und das ist die richtige Antwort. Das letzte Wort hat der Fenstermanager -
Windows laesst einen Hintergrundprozess den Vordergrund nicht einfach an
sich reissen; der kurze Ausflug ueber Topmost half im Versuch, unter Linux
entscheidet der Fenstermanager. Mehr als bitten kann eine Anwendung nicht.
ShutdownSignal ist zu InstanceControl geworden: beenden und Fenster sind
zwei Bitten desselben Absenders ueber denselben Weg. Beenden gilt einmal,
das Fenster beliebig oft - jeder Wechsel auf diese Instanz ist einer.
--managed schaltet den Wechsel im Instanzfenster ab. Der Manager gibt es
jedem Instanzprozess mit; das Fenster graut seinen Instanz-Schalter aus und
erklaert auf Nachfrage, wo gewechselt wird. Zwei Schloesser an derselben
Tuer: Der Knopf ist aus, und der Weg dahinter prueft es noch einmal - denn
hinter ihm wartet ein Selbst-Neustart.
instanceWindows in manager.json, vorbelegt auf true: Jede Instanz behaelt
ihr Fenster. Auf einer Maschine ohne Bildschirmsitzung gehoert false hin.
ABNAHME an echten Fenstern: Instanz ueber den Manager gestartet, PID 18128,
Fenstertitel "ClawdDotNet", Befehlszeile mit --managed. Fenster von aussen
minimiert (IsIconic True), dann POST /instanzen/Instance-Test/fenster:
IsIconic False, im Vordergrund - und PID unveraendert 18128. Nichts neu
gestartet. Das ist die Abnahmebedingung dieser Stufe.
Build ohne Warnungen, 780 Tests gruen, 8 uebersprungen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Managerprozess. ClawdDotNet.Instanzmanager ist eine Konsolenanwendung:
Lizenz pruefen, uebernehmen was laeuft, Weboberflaeche aufhaengen, warten.
Beim Herunterfahren beendet er keine Instanz.
Zwei neue Projekte. ClawdDotNet.Manager.Web traegt die Weboberflaeche -
ohne jeden Verweis auf ClawdDotNet.Web, denn dort haengt App und daran
sechzehn Werkzeugprojekte. ClawdDotNet.ManagerApp ist der Einstiegspunkt.
wwwroot ist aus der Instanz in den Manager gezogen.
DER SCHNITT DER HTTP-FLAECHE: Unter /api/verwaltung steht, was den Manager
angeht - auflisten, anlegen, starten, anhalten. Alles andere unter /api
geht unveraendert an eine Instanz. Er leitet weiter, er implementiert
nicht. Welche Instanz gemeint ist, sagt die Kopfzeile X-Instanz; laeuft
genau eine, ist sie gemeint, und laufen mehrere, wird nachgefragt statt
geraten - eine Anfrage an die falsche Instanz ist schlimmer als eine
abgelehnte.
Der zusammengefuehrte Ereignisstrom haelt je laufender Instanz eine
Zuleitung und schreibt an jedes Ereignis, von wem es kommt. Ergaenzt statt
verpackt: Ein Umschlag waere einfacher gewesen, haette aber jede Ansicht
der Weboberflaeche zum Umschreiben gezwungen.
ABNAHME gegen laufende Prozesse: 401 ohne Token, Oberflaeche ohne Token
200, Instanz ueber den Manager gestartet und angehalten, /api/info und
/api/status unverfaelscht durchgereicht, /events/logs mit
"instanz":"Instance-Test" an jeder Zeile. Manager abgeschossen: Instanz
laeuft weiter. Manager neu gestartet: "1 Instanzen bekannt, 1 laufen
bereits" - uebernommen. E-M6 damit in beide Richtungen belegt.
DREI DEFEKTE, die erst der Lauf gezeigt hat:
1. Der Manager hing an einer Konsolenabfrage nach dem Lizenzschluessel. Ein
Test auf Console.IsInputRedirected reicht dafuer NICHT: Er beantwortet
"ist die Eingabe umgeleitet", nicht "kann jemand antworten" - ein
Prozess ganz ohne Konsole, der gefaehrlichste Fall, ist nicht
umgeleitet. Der Manager fragt jetzt gar nicht.
2. Eine unlesbare manager.json wurde stillschweigend durch Vorgaben
ersetzt: falsches Instanzverzeichnis, anderer Port, Lizenzfrage - und
nichts sagte, woran es lag. LoadProblem meldet den Grund jetzt.
3. Der Instanzprozess erbte CLAWD_CONFIG_DIR vom Manager und legte sich in
dessen Konfigurationsverzeichnis eine eigene Settings.json an. Eine
Umgebungsvariable vererbt sich, ein Argument nicht - der Manager nimmt
sein Verzeichnis jetzt ueber --config.
SharedLoggerProvider ist nach Core gezogen: Es gibt jetzt zwei Webhosts,
die dasselbe brauchen, und sie duerfen einander nicht kennen.
NOCH OFFEN in dieser Stufe: Die Weboberflaeche kennt noch keine Instanzen -
Instanzauswahl, X-Instanz und die Verwaltungsansicht sind Arbeit an
wwwroot. Und webServerPort steht noch in der Instanz.
Build ohne Warnungen, 775 Tests gruen, 8 uebersprungen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>