29d953a5eb8be34beea4faafa781be0332fc1d39
27
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
609298dd7a |
Ablage je Einheit, Stufe 2: Verwaltung und Organisationsseite (#684)
- 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> |
||
|
|
920d3fed64 |
Lagebild, Stufe 1: Einheiten als aufklappbare Container (#711)
- 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>
|
||
|
|
68a432fec6 |
Einheiten, Stufe 3: Verwaltung mit Umzug, Rechte-Obergrenze und Sammelwerten (#683)
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> |
||
|
|
626fc8d593 |
Einheiten, Stufe 2: das Adressbuch durchsetzen und jedem Agenten seinen Platz sagen (#683)
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> |
||
|
|
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> |
||
|
|
32383119da |
Budgetende, Stufe 4: den Engpass melden, bevor er eintritt (#716)
- 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> |
||
|
|
9cf9a2cfc2 |
Budgetende, Stufe 3: Nachholen nur im Spielraum des Tages, keine Kappung bei 500 (#716)
- 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> |
||
|
|
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> |
||
|
|
8df5d004e4 |
Scanner: Laeufe deckeln, stille Kappung bei 500 beseitigen (#682)
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
e2567a466f |
Sichtung offener Werkzeugaufrufe beim Start verdrahtet (#554)
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> |
||
|
|
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> |
||
|
|
99f8a89fd0 |
Schluesselbund: ein Hauptschluessel, mehrfach verpackt (#190)
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> |
||
|
|
e3403087c2 |
Handschlag: --managed hebelt die Lizenzpruefung nicht mehr aus (#535)
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> |
||
|
|
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> |
||
|
|
cb56175d20 |
Instanzmanager: Lizenz und Sub-Token wandern in den Manager (#528, E-M3)
Neues Projekt ClawdDotNet.Licensing. LicenseGate, LicenseWatch, LicenseInfo und ILicensePrompt sind aus ClawdDotNet.App dorthin gezogen, weil zwei Prozesse dieselbe Lizenzpruefung brauchen und keiner von beiden den anderen kennen darf. In Core konnte es nicht landen - dann zoege jedes der sechzehn Werkzeugprojekte das Deploymentcenter-SDK mit. Dabei ist die Kopplung an SettingsManager verschwunden. LicenseGate kennt jetzt nur ILicenseStore: Serveradresse lesen, Schluessel lesen und schreiben, speichern. Die Anwendung fuehrt ihn in Settings.json, der Manager in manager.json. Der Torwaechter prueft Schluessel; Dateien verwaltet er nicht. Auch die Anwendungsversion kommt als Parameter statt aus einem globalen Zugriff - diese Schicht weiss nicht, welche Anwendung sie benutzt. ManagerCore ist die Klammer: eigene Einstellungen, Lizenz, Register, Meldeweg. Drei Regeln: - Ohne gueltige Lizenz startet er keine Instanz. Laufende werden trotzdem in die Liste genommen - man soll sie sehen und anhalten koennen. - Ein Widerruf haelt alle an. Der einzige Fall, in dem der Manager das von sich aus tut. Ein Serverausfall gehoert ausdruecklich nicht dazu; das SDK trennt Urteil und gescheiterten Versuch, und nur das Urteil kommt hier an. Sonst naehme ein Netzproblem saemtliche Installationen mit. - Ohne hinterlegte Lizenzpruefung sperrt er nichts, sonst gaebe es eine Henne-Ei-Sperre, bevor jemand einen Schluessel eintragen kann. Sub-Token je Instanz: Der Manager haelt das Master-Token und tauscht es beim ANLEGEN einer Instanz gegen ein eigenes (watchdog:ping, bugtracker:report, einzeln widerrufbar). Beim Anlegen und nicht beim ersten Start, weil die Instanzdatei dann zweifelsfrei niemandem gehoert - sie spaeter zu schreiben, waehrend der Instanzprozess laeuft, hiesse zwei Schreiber auf einer Datei. Fuer Instanzen, die es vor dem Manager schon gab, wird es vor dem Start nachgeholt. Danach fragt er ueber whoami nach, ob das Token an ein Projekt gebunden ist (SDK 2.8.1). Ein fehlgeschlagener Tokenbezug haelt die Instanz nicht auf. NOCH NICHT VOLLSTAENDIG: Die Instanzen pruefen die Lizenz weiterhin selbst. Das laesst sich erst abschalten, wenn eine Instanz feststellen kann, ob ein Manager da ist - vorher entstuende eine Fassung ganz ohne Durchsetzung. Und ein Testfehler, der zweimal derselbe war: Die Socket-Antwort war hinterlegt, BEVOR der Manager hochfuhr. Damit sagt man "diese Instanz laeuft bereits", der Manager uebernimmt sie, der Starter wird nie angefasst - und der Test prueft etwas anderes, als er behauptet. Es gibt jetzt eine Hilfsmethode, die das ausschliesst. Build ohne Warnungen, 774 Tests gruen, 8 uebersprungen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
72b0764d1a |
Instanzmanager: Register, Einstellungen und stellvertretende Meldung (#528)
Der zweite Teil von Stufe 3. Die Aufsicht ueber eine einzelne Instanz stand schon; jetzt gibt es die Klammer darum und den Weg nach draussen. InstanceRegistry haelt je Instanz eine Aufsicht. Zwei Zusagen, beide aus E-M6: Beim Start wird UEBERNOMMEN, nicht gestartet - ein Manager, der beim Hochkommen alles hochfaehrt, was er findet, startet nach einem Neustart der Maschine auch das, was jemand mit Absicht angehalten hat. Und beim Beenden wird nichts beendet: Wer den Manager schliesst, will den Manager schliessen. Einzige Ausnahme ist StopAllAsync fuer einen Grund, der alle betrifft - und der heisst Lizenzwiderruf. SupervisionReporter macht aus einem Befund eine Bugtracker-Meldung, stellvertretend: mit Prozesskennung, Abschiedscode und dem Ausschnitt aus dem Instanzprotokoll, der noch auf der Platte liegt. Der Idempotenzschluessel ist stabil je Instanz und Art - stuerzt dieselbe Instanz wiederholt ab, zaehlt der Server hoch, statt den Bugtracker mit Zwillingen zu fuellen. Ein leerer Protokollauszug ist dabei die aussagekraeftigste Zeile der Meldung und wird ausdruecklich als solche geschrieben. Genau das war der Zustand am 2026-09-08: Der Prozess wurde erschlagen, bevor sein Schreibpuffer geleert war, und hinterliess nichts. manager.json traegt die Felder aus Abschnitt 6 des Konzepts und sonst nichts. Lizenzschluessel, Master-Token und Web-Token liegen darin verschluesselt und zur Laufzeit im Klartext - dieselbe Bauart wie die Anwendungseinstellungen, mit Absicht. Unsinnige Aufsichtswerte werden eingefangen, weil die Datei von Hand bearbeitbar ist. InstanceLayout ist nach Core gezogen (ResolveLogDirectory, ResolveBackupDirectory). Der Manager braucht das Protokollverzeichnis einer Instanz fuer den Auszug in der Meldung und darf ClawdDotNet.App nicht kennen; dieselbe Rechnung an zwei Stellen zu fuehren waere die schlechtere Antwort. AppHost leitet nur noch weiter. EIN DEFEKT, den erst die eigenen Tests gezeigt haben: Eine angehaltene Instanz erschien im Register als "Instance-Alpha" statt "Alpha". Die Aufsicht kennt den Namen erst, wenn die Instanz einmal geantwortet hat, und eine angehaltene tut das nie - waehrend genau diese Ansicht der Manager anzeigt. Das Register fuehrt den Namen jetzt aus InstanceSettings.json mit. Und ein Testdouble, das zu viel behauptet hat: Der falsche Socket antwortete fuer jedes Verzeichnis dieselbe Instanz. Das laesst Tests gruen werden, die im Betrieb zwei Instanzen verwechseln wuerden; er antwortet jetzt je Verzeichnis. 29 neue Tests. Build ohne Warnungen, 766 Tests gruen, 8 uebersprungen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
b78e5d844f |
InstanceDirectoryManager nach Core verschoben (Vorarbeit #528 Stufe 3)
Reiner Umzug, keine Verhaltensaenderung. Der Instanzmanager braucht die Verzeichnisstruktur einer Instanz - anlegen, auflisten, Konfiguration lesen -, aber er darf ClawdDotNet.App nicht referenzieren: Dort haengen sechzehn Werkzeugprojekte dran (Telegram, Mail, FTP, Rocket.Chat, ...), und der Manager soll ausdruecklich keines davon kennen. Ein Projektverweis wuerde sie nicht ausfuehren, aber laden - und die Zusage "keine Werkzeuge im Manager" waere nur noch eine Absichtserklaerung statt einer Eigenschaft des Bauplans. Das Wissen selbst gehoert ohnehin nach Core: Es beschreibt, wie eine Instanz auf der Platte liegt, und InstanceConfig und AgentConfig liegen dort schon. Verschoben nach Core/Instances: InstanceDirectoryManager, InstanceInfo, TokenUsageRecord/TokenUsageFile, AgentListItem/AgentListFile. In ClawdDotNet.App/Models bleiben JobHistoryEntry und die Werkzeug-Ansichtsmodelle, die dort richtig liegen. Build ohne Warnungen, 717 Tests gruen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
facd21459c |
Instanzmanager Stufe 1: Protokolle und Sicherungen je Instanz (#528)
Mehrere Instanzen sollen unabhaengig voneinander laufen. Heute tun sie das nicht: Sie teilen sich Protokollverzeichnis, Sicherungsordner und Sicherungszeitplan. In einer gemeinsamen Startup.log standen abwechselnd Zeilen zweier Instanzen, ohne Kennzeichnung, welche gerade spricht -- im Mehrinstanzbetrieb ist damit jede Fehlersuche Ratearbeit. Genau in dieser Lage ist der Aufhaenger aus #529 entstanden. Fuenf Schluessel wandern aus AppSettings nach InstanceSettings.json: logDirectory, backupDirectory, backupKeepCount, autoBackupEnabled, autoBackupTime. Leer heisst jetzt <Instanz>/Logs beziehungsweise <Instanz>/Backups; ein relativer Wert zaehlt weiterhin gegen das Instanzverzeichnis, nicht gegen das Arbeitsverzeichnis des Prozesses (#375 bleibt gewahrt). autoBackupEnabled und autoBackupTime standen in der Planung nicht, sind aber mitgegangen: Ein Schalter, der die taegliche Sicherung fuer eine Instanz einschaltet und sie damit fuer alle einschaltet, ist derselbe Fehler wie ein Ordner fuer alle -- und zwei von vier Sicherungsfeldern zu verschieben hinterliesse eine Einstellungsseite, auf der die Haelfte anwendungsweit gilt. Keine Uebernahme der Altwerte, aber eine Ansage: SettingsManager. AbandonedKeys meldet die aufgegebenen Schluessel, solange sie noch in Settings.json stehen, und der Start protokolliert einmal, was nicht mehr gilt und wohin diese Instanz stattdessen schreibt. Ein anwendungsweiter Pfad, in alle Instanzen kopiert, waere wieder ein Ordner fuer alle. webServerPort bleibt vorerst stehen. Es entfaellt mit Stufe 2, sobald Kestrel auf dem Socket hoert; vorher wegzunehmen hiesse, die Weboberflaeche ohne Ersatz abzuschalten. Korrektur an der eigenen Befundlage: "Instanz A wirft die Sicherungen von Instanz B weg" war zu breit. Beide Rotationen filtern bereits nach dem Praefix backup_<Instanzname>_. Der reale Defekt ist enger, und ein Praefix ist keine Grenze: backup_Test_2_*.zip faengt mit backup_Test_ an, also zaehlt Test im gemeinsamen Ordner die Archive von Test_2 mit. Belegt in BackupSchedulerTests, das den alten Zustand eigens wiederherstellt. Nachgeprueft an der laufenden Installation, nicht nur im Test: Nach dem Umbau schreibt Instance-Test nach Instances/Instance-Test/Logs, das alte gemeinsame Verzeichnis bekommt keine Zeile mehr, und die Warnung zu den aufgegebenen Schluesseln erscheint genau einmal. Enthaelt ausserdem, was seit der Weboberflaeche liegengeblieben war: - #526: Instanzgeheimnisse wurden beim Speichern verschluesselt und beim Laden nie entschluesselt. LoadInstanceConfig hatte kein ConfigSecrets.Unprotect; ConfigLoader.LoadAsync macht es richtig, wird zur Laufzeit aber gar nicht aufgerufen. Der OpenRouter-Schluessel ging so verschluesselt an die API. - Ein offener Ereignisstrom hielt das Beenden fuenf Sekunden auf. Die Stroeme hingen nur an RequestAborted, das beim geordneten Herunterfahren nicht feuert; jetzt zusaetzlich an ApplicationStopping. Der Fang in WebUiHost gilt dazu ohne Bedingung auf RequestAborted -- mit ihr waere jeder offene Strom beim Beenden als Fehler im Bugtracker gelandet. - Nach der Anmeldung blieb die Weboberflaeche leer: #anmeldung { display:flex } schlaegt als ID-Selektor das hidden-Attribut. - docs/Instanzmanager-Konzept.md: Befund, die Entscheidungen E-M1 bis E-M6, der Schnitt zwischen Manager und Instanz und die sechs Stufen. Build ohne Warnungen, 709 Tests gruen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
1e9cb789c8 |
Weboberflaeche hinzugefuegt und Fachlogik nach App herausgeloest (#493, #494)
- ClawdDotNet.Web: Kestrel im Prozess der Anwendung, Token-Absicherung (TokenGate mit FixedTimeEquals), Endpunkte unter /api, Ereignisstrom unter /events (Server-Sent Events) und fortlaufendes Log-Streaming. - Weboberflaeche (wwwroot/): Vollstaendiges Single-Page-Frontend mit nativem HTML5, CSS3 und ES-Modulen ohne Buildschritt (strikt textContent, #-Routing, sofortiger Login-Sprung bei fehlendem Token, Light/Dark-Theme, lokale Barlow-Schriften). - ClawdDotNet.App: Fachlogik aus den Avalonia-ViewModels in Dienste herausgeloest (AgentAdministration, JobAdministration, ServiceAdministration, RunCoordinator) und ueber InstanceChange synchronisiert. - Tests: ClawdDotNet.Web.Tests und ClawdDotNet.App.Tests hinzugefuegt, alle 684 Tests erfolgreich. |
||
|
|
cffd6f4b77 |
Bugtracker-Durchgang: 13 Bugs behoben, Build ohne Warnungen
Alle Behebungen auf der Linux-Test-VM gegengeprueft (Ubuntu, .NET 10.0.111): Build 0 Warnungen / 0 Fehler, 637 Tests gruen, 1 uebersprungen (WindowsFact). Sicherheit und Zielplattform #373 PathBoundary.Canonicalize fiel offen aus. File.ResolveLinkTarget wirft fuer einen fehlenden Abschnitt FileNotFoundException; der catch(IOException) verliess daraufhin die GANZE Aufloesung mit dem unaufgeloesten Pfad - und der besteht jede Praefixpruefung. Der Symlink-Schutz war damit bei jedem Schreibvorgang wirkungslos. Jetzt ueber FileSystemInfo.LinkTarget, und TryCanonicalize meldet "nicht bestimmbar", statt fail-open durchzureichen. #374 WorkspacePath weist den Backslash rundheraus ab, wie den Doppelpunkt. Eine Schreibweise statt einer Sonderregel je Windows-Form. #375 Log-Verzeichnis: leer heisst "Anwendungseinstellung"; ein relativer Wert zaehlt gegen das Instanzverzeichnis, nicht gegen das Arbeitsverzeichnis des Prozesses. Ein systemd-Dienst landet nicht mehr auf /Logs. Agentenkommunikation #206 Delegationskette gegen A->B->A (Test A13). Zyklusfrei per Bauart, dazu MaxDelegationDepth gegen die Staffel, die niemand beauftragt hat. #461 Zwei unabhaengige Ketten ueber Kreuz - beim Beheben von #206 gefunden und reproduziert. Ein delegierter Lauf wartet nur noch begrenzt auf ein fremdes Gate; ein Chat vom Menschen reiht sich weiter unbegrenzt ein. #234 Instanz-Id wird durchgereicht statt aus einem nur beilaeufig gesetzten Feld gelesen. Betrieb und Oberflaeche #376 Log-Ansicht chronologisch statt gruppiert je Moduldatei, mit Stacktraces an ihrer Meldung - auch ueber Taktgrenzen hinweg. #377 Info-Tabelle: feste Spaltenbreiten, damit ein langer Aenderungstext den anderen Spalten nicht den Platz nimmt. #378 Sicherung: Mindestabstand zwischen Ueberschrift und Schaltflaechenleiste. #379 Hellmodus: drei von vier gedaempften Textpinseln lagen unter 4,5:1. Die helle Palette ist als Ganzes verschoben, damit die Staffelung sichtbar bleibt statt auf einen Wert zusammenzufallen. Hygiene #233 stock_add: der Indexstand wird innerhalb der Sperre festgehalten. #235 Zeitumstellung: eine nicht existierende Ortszeit wird auf den ersten Zeitpunkt nach der Luecke verschoben statt uebersprungen (R4, R5). #236 45 Nullable-Warnungen und eine CA1416 - nicht unterdrueckt, sondern die Stellen so umgebaut, dass die Zusage nachvollziehbar wird. Mail meldet jetzt, WELCHER Zugangsschluessel fehlt, statt an einer KeyNotFoundException zu scheitern. #203 Kompaktiert wird vor dem API-Aufruf statt danach; die gemessenen Prompt-Groessen kalibrieren die Schaetzung je Modell. Neu: tests/ClawdDotNet.App.Tests - fuer #375 und #376 gab es keinen Ort fuer Tests. Dazu Regressionstests fuer jede Behebung; jeder wurde gegen den alten Stand geprueft, damit belegt ist, dass er den Fehler faengt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
2853541629 |
Fruehjahrsputz: WinForms-Altlast entfernt, Dokumentation nachgezogen
Die Avalonia-Portierung ist abgeschlossen, damit ist die in ClawdDotNet.slnx angekuendigte Aufgabe "WinForms-Oberflaeche entfernen" faellig. Der Stand davor liegt unter dem Tag vor-fruehjahrsputz-2026-08. Entfernt (56 Dateien, seit dem Herausloesen der Anwendungsschicht nicht mehr Teil des Builds): ClawdDotNet.csproj, Program.cs, sieben frm_*-Formulare, UI/, Models/, EmbeddedUI/, Properties/, Resources/, Services/, das alte Anwendungssymbol und Deploy-Build.ps1 (ersetzt durch deploy/publish.py). Dazu configs/*.json - Beispielkonfigurationen aus der Zeit vor dem Instanzverzeichnis, auf die nur noch die alten Prompts verwiesen. Die vier Entwicklungs-Prompts der Anfangszeit ziehen nach docs/archiv/ um, mit README, das ihren Stand einordnet. Eine Regel darin gilt weiter - die Pflichtfelder fetchedAt/dataAsOf/source der Internet-Tools -, deshalb Archiv statt Loeschen; der WebSearch-Plan verweist auf den neuen Pfad. Toter Code - PlaceholderPageViewModel samt Ansicht: Es gibt keinen Platzhalter-Bereich mehr, seit alle neun Seiten portiert sind. - Snappier als direkter Paketverweis: MongoDB.Driver loest es ohnehin auf dieselbe Fassung auf, der Verweis hob nichts an. Zwei Fehler, die dabei sichtbar wurden - Die taegliche Sicherung lief ins Leere. Die Oberflaeche bot sie an und schrieb Uhrzeit, Zielordner und Anzahl in die Einstellungen, aber der BackupScheduler wurde nirgends erzeugt. Jetzt am AppHost verdrahtet und in den geordneten Abbau aufgenommen. - SettingsPageViewModel hielt die vier Sicherungs-Einstellungen doppelt. Aus der Ansicht waren sie laengst verschwunden, gelesen und beim Speichern zurueckgeschrieben wurden sie weiter: Wer die Uhrzeit auf der Sicherungs-Seite aenderte und danach die Einstellungen speicherte, bekam den alten Wert zurueck. Pakete: keine bekannten Sicherheitsluecken mehr - SQLitePCLRaw.bundle_e_sqlite3 auf 2.1.13 angehoben. Microsoft.Data.Sqlite bringt 2.1.11 mit, darin steckt GHSA-2m69-gcr7-jv3q (NU1903, hoch). - SharpCompress bleibt als direkter Verweis stehen. Beim Aufraeumen erst als ungenutzt entfernt - dabei kam die von MongoDB.Driver gezogene Fassung 0.30.1 mit GHSA-6c8g-7p36-r338 zurueck. Der Verweis ist eine Anhebung, kein Ballast; das steht jetzt als Kommentar dabei. Dokumentation - Roadmap mit Statusblock: A1 und A3 erledigt, A2 nur zur Haelfte - Gate, Policy und Dienst greifen, aber keine Ansicht ruft ApproveAsync auf, ein gestagter Aufruf liegt unbeantwortet. Das ist jetzt Punkt 1 der Reihung. Rocket.Chat steht und kollidiert mit A5 (Matrix) - Entscheidung faellig. - Avalonia-Portierungsleitfaden -> Oberflaechen-Leitfaden: kein Auftrag mehr, sondern Beschreibung des Stands. - Bestandsaufnahme und Linux-Analyse als datierte Befunde gekennzeichnet; der teure Teil der Linux-Analyse (8.900 Zeilen WinForms) ist hinfaellig. - Verweise auf frm_*, WebView2 und ClawdDotNet.csproj in den lebenden Dokumenten richtiggestellt. Build fehlerfrei, 585 Tests gruen (6 uebersprungen). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
33d95a6c3f |
UI-Entwurf umgesetzt, Rocket.Chat-Tool, Deploymentcenter 2.4
Sicherungspunkt vor dem Aufraeumen. Buendelt die Arbeit, die seit dem Abschluss der Avalonia-Portierung im Arbeitsverzeichnis lag. Oberflaeche - Entwurf aus Mockup/ umgesetzt: Theme.axaml (Farben je Thema, Barlow als mitgelieferte Schrift), Icons.axaml (Symbolgeometrien), Shell.axaml (eigene ControlThemes statt Fluent umzufaerben). - Neue Steuerelemente StrokeIcon und BlueprintFrame, Seiten fuer Token-Verbrauch und Agenten-Chats, Werkzeug-Einstellungen als Seite statt eigenem Fenster, Texteditor-Fenster. - ThemeManager mit hellem und dunklem Thema; die beiden Pinsel-Konverter entfallen, weil ein fester Farbwert den Themenwechsel nicht ueberlebt. Rocket.Chat - Neues Tool-Projekt (Client, Konfiguration, Workspace-Dateien) nach der Bauform des Telegram-Tools: rocketchat_poll als Tool-Job, geweckt wird nur, wenn wirklich etwas anliegt. - send_file ist freigabepflichtig, send_message bewusst nicht: Der Raum ist Arbeitsraum, der Schutz sitzt an der Raum-Allowlist. - Konzept-Doc um die Messung gegen die echte Instanz 8.7 ergaenzt; drei Annahmen waren falsch und sind korrigiert. Deploymentcenter - DC6 (Update anwenden) und DC7 (Erstinstallation ueber setup.json) erledigt, DC3 fuer win-x64/dev; deploy/publish.py als Release-Strecke. - AppHost.DisposeAsync gegen doppeltes Herunterfahren gesperrt - sonst ueberschreibt eine zweite Abmeldung den Wartungszustand am Watchdog. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
b5bf97ae74 | feat(ui): complete Avalonia UI port with 7 main pages, tool settings & top MenuBar |