Versionierung der Arbeitsbereiche: Verlauf je Datei mit Agent, Lauf und Vorfassung (#719)

Eigene inhaltsadressierte Ablage (Agents/.history/objects, SHA-256) statt Git,
Journal FileHistory in state.db. Jeder Schreibweg - FileRW write/append/copy/
delete/stock_add, FTP- und RocketChat-Downloads - legt die alte Fassung ab und
verbucht die Aenderung mit RunId. Externe Aenderungen findet ein Abgleich beim
Start und stuendlich. Aufbewahrung nach Tagen und Fassungen, verwaiste Objekte
werden entfernt. WebUI: Dateiverlauf mit Filter, Diff und Wiederherstellen nur
durch den Menschen mit Grund.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-09-28 11:12:13 +02:00
co-authored by Claude Opus 5.5
parent 621a83de43
commit e9c39c3c96
21 changed files with 1663 additions and 2 deletions
+13
View File
@@ -601,6 +601,10 @@ public sealed class AppHost : IAsyncDisposable
// #720: which version of a shared file each agent read — a write cannot silently lose another.
engine.Files = new Core.Files.FileLedger(storage);
// #719: the history of the workspaces, next to them in Agents/.history.
var fileHistory = new Core.Files.FileHistory(Path.Combine(instancePath, "Agents"), storage, () => instance.FileHistory);
engine.History = fileHistory;
// #712: Foreign runtimes. The application itself is the launcher inside the sandbox
// (network through the proxy, secrets from a file) and the MCP bridge back to us.
var mcpGrants = new Core.Mcp.McpGrants(storage);
@@ -690,6 +694,15 @@ public sealed class AppHost : IAsyncDisposable
janitor.Start();
host._shutdown.Add(janitor.DisposeAsync);
// #719: changes made outside the tools, and the retention of the history.
var historyKeeper = new Core.Files.FileHistoryKeeper(
fileHistory,
() => Core.Files.FileHistoryKeeper.WorkspacesOf(instance.Agents, Core.Organisation.OrgChart.From(instance)),
() => instance.FileHistory,
loggerFactory.CreateLogger("ClawdDotNet.Core.Files"));
historyKeeper.Start();
host._shutdown.Add(historyKeeper.DisposeAsync);
// #593: Angelegt wurde der Dienst schon immer, gestartet nie — weder kopflos noch
// mit Fenster. Die Kopfzeile der Weboberflaeche stand deshalb dauerhaft auf
// "OpenRouter: —" und /api/status auf "Prüfe…".