Commit Graph
14 Commits
Author SHA1 Message Date
RichardandClaude Opus 5.5 f627918729 Lagebild, Stufe 0: Teamuebersicht in der WebUI (#711)
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>
2026-09-24 12:34:46 +02:00
RichardandClaude Opus 5.5 991a901cab WebUI: Cytoscape.js, ELK und cytoscape-elk eingecheckt (#711)
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>
2026-09-24 12:21:25 +02:00
RichardandClaude Opus 5.5 5f3a85595b Budgetende, Stufe 1: Ausfall vermerken, Regel je Agent, mitnehmen statt anrennen (#716)
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>
2026-09-24 12:03:15 +02:00
RichardandClaude Opus 5.5 ad71682c2d i18n: Englisch als Hauptsprache, Sprachpakete fuer Desktop und WebUI (#661)
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>
2026-09-24 09:43:51 +02:00
RichardandClaude Opus 5 5adf4c1ca6 Prompt History und Verbrauchsauswertung (#660), englische Hauptsprache (#661)
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>
2026-09-19 15:33:09 +02:00
RichardandClaude Opus 5 2f0361278b Freigaben buendeln statt Weckflut (#643), Freigabemodell ueber Werkzeugrechte (#641)
#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>
2026-09-19 14:37:44 +02:00
RichardandClaude Opus 5 f5731c50f8 Budgetsperre sichtbar machen (#608), Gedaechtnisabruf kuerzt statt wegzulassen (#607)
#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>
2026-09-15 18:59:14 +02:00
RichardandClaude Opus 5 0b6ea73ec1 Entscheidungen aus dem Testbetrieb umgesetzt (#572): #577 #579 #581 #589 #193 #205 #594 #595 #597 #598 #599 #588
- 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>
2026-09-15 11:23:10 +02:00
RichardandClaude Opus 5 6581fd0187 Befunde aus dem Testbetrieb auf der Linux-VM behoben (#572)
- #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>
2026-09-14 15:40:56 +02:00
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
RichardandClaude Opus 5 dcffcdcff5 Instanzmanager: Weboberflaeche kennt Instanzen, geordnetes Ende, Puls (#528, #531)
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>
2026-09-10 11:15:59 +02:00
RichardandClaude Opus 5 7d4e8b3096 Autostart durch Manager, mit Sicherungsautomat (#528)
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>
2026-09-09 00:01:52 +02:00
RichardandClaude Opus 5 db7abf699f Instanzmanager Stufe 5: Wechseln heisst nach vorn holen (#528, E-M2)
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>
2026-09-08 23:39:50 +02:00
RichardandClaude Opus 5 a511480b77 Instanzmanager Stufe 4: eine Adresse, ein Zugang, alle Instanzen (#528, E-M5)
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>
2026-09-08 23:19:49 +02:00