Skip to content

agent: #12 [Agent] Automatische Sicherung als ZIP außerhalb des Projektordners - #25

Draft
leonatwork wants to merge 4 commits into
mainfrom
agent/bearbeite-github-issue-12-vollst-ndig-un-1020-1433
Draft

leonatwork wants to merge 4 commits into
mainfrom
agent/bearbeite-github-issue-12-vollst-ndig-un-1020-1433

Conversation

@leonatwork

Copy link
Copy Markdown
Owner

Zusammenfassung

Autonome Umsetzung von #12: [Agent] Automatische Sicherung als ZIP außerhalb des Projektordners

Verifikation

  • Coder-/Reviewer-Loop: APPROVE nach 4 Runde(n)

  • Tests und Qualitätsprüfungen: siehe Commit und CI-Checks

  • Kein automatischer Merge oder Produktionsdeploy

  • Modell: azure/gpt-6.1-sol; Decision-1 (active): route gpt-5.3-codex, Risiko medium; QS: npm run build && npm test bestanden

  • Art der Änderung (Triage): code; Zweitprüfung: azure/gpt-5.3-codex

  • Kosten (Listenpreis): 6,6 Mio Tokens · 3,82 €

Hinweise der Qualitätsprüfung

  • Review-Hinweis (minor: src-tauri/src/sicherungen.rs:80: Die Zeile return Err(fehler(crate::sprache::t("Ungültiger ZIP-Name", "Invalid ZIP name"))); steht jetzt auf einer Zeile. Sie hat 89 Zeichen, also weniger als max_width 100. Die Argumente von t sind 41 Zeichen breit, weniger als fn_call_width 60. Damit entspricht sie der Ausgabe von rustfmt. Kein Handlungsbedarf.)
  • Review-Hinweis (minor: src-tauri/src/sicherungen.rs:217: .set_title(crate::sprache::t("Sicherungsordner wählen", "Choose Backup Folder")) steht auf einer Zeile mit 88 Zeichen. Die Argumente von t sind 49 Zeichen breit. Das einzige Argument von set_title darf als Aufruf überlaufen, deshalb ist die Zeile rustfmt-konform. Kein Handlungsbedarf.)
  • Review-Hinweis (minor: src-tauri/src/sicherungen.rs:152, :471, :485: Diese drei t(-Aufrufe sind weiter auf mehrere Zeilen verteilt, und das ist richtig so. Bei :152 und :471 sind die Argumente breiter als 60 Zeichen. Bei :485 wäre die Zeile mit etwa 105 Zeichen länger als 100. Kein Handlungsbedarf.)
  • Tests zur Änderung (Hinweis, nicht blockierend): 1 Logikdatei(en) mit 10 Zeilen geändert, aber keine Testdatei
    • src-tauri/src/sicherungen.rs

Closes #12

…bare Lösung.

Lies zuerst den vollständigen Issue-Thread inklusive aller Kommentare, CLAUDE.md und die relevanten Repository-Regeln. Prüfe vorhandene PRs und aktuellen Code, bevor du Änderungen machst. Leite die verbindlichen Akzeptanzkriterien aus dem Issue ab und dokumentiere nicht erfüllbare oder widersprüchliche Kriterien klar.

Arbeite testgetrieben: Erzeuge Regressionstests, verifiziere ihr korrektes Fehlschlagen vor dem Fix und führe danach die relevanten Tests sowie die vorgeschriebenen Qualitätsprüfungen aus. Ändere nur, was für das Issue erforderlich ist. Arbeite ausschließlich auf dem ausgecheckten Stand von origin/main: checke keine Branches fremder offener PRs aus, cherry-picke nichts daraus und baue nicht auf ihnen auf. Hängt die Lösung von einem noch offenen PR ab, liefere nur deinen eigenen Anteil und dokumentiere die Abhängigkeit im Handover. Keine Produktionsdeployments, keine Änderungen an Produktionsdaten oder Produktions-Supabase und kein --prod. Merge den PR nicht.

Issue: #12
Titel: [Agent] Automatische Sicherung als ZIP außerhalb des Projektordners

Beschreibung:
<!-- hermes-agent-form-v1:start -->
## Ziel und Nutzen
Plotwerk sichert das Projekt automatisch als ZIP außerhalb des Projektordners, damit ein Stand bleibt, wenn der Ordner verloren geht, beschädigt wird oder ein Sync-Dienst ihn zerstört.

## Ist-Zustand / Problem
Gesichert wird nur im Projektordner (.versionen/). Der fs_*-Pfadwächter (pfad.rs) erlaubt keine externen Pfade. extern_dateien.rs schreibt nur an Pfade aus dem nativen Dialog. jszip ist bereits Abhängigkeit. Die Frist beim Beenden beträgt 3 s (beenden.rs).

## Umfang (In Scope)
- Paket 1: reine Funktionen in core/ (Dateiauswahl, ZIP-Aufbau, Dateiname, Rotation) und ein enger Rust-Command für .zip im Sicherungsordner
- Paket 2: Einstellungen (an/aus, Ort, mit/ohne .versionen/), tägliche Sicherung beim ersten Öffnen, Menüpunkt 'Ablage → Projekt als Archiv sichern …', Fehlerhinweis in DE/EN, Ausblenden in der Browser-Demo
- Paket 3: Wiederherstellen vom Startbildschirm in einen neuen, leeren Ordner, inklusive Hinweis bei leerer Liste

## Nicht Teil dieses Issues (Out of Scope)
- Sicherung in Cloud oder auf Server
- Verschlüsselung der ZIPs
- Wiederherstellen in den bestehenden Projektordner
- Änderungen an der Schnappschuss-Politik E8
- Erkennen von Sync-Konflikten
- Sicherung beim Beenden (nicht gewählt)
- Änderungen am fs_*-Pfadwächter

## Fachliche und UX-Entscheidungen
- Geklärt (Leon): Aufteilung in 3 Pakete (Kern/Rust, Auslöser/UI, Wiederherstellen)
- Geklärt (Leon): Auslöser ist täglich beim ersten Öffnen
- Geklärt (Leon): Standardort ~/Library/Application Support/app.plotwerk.mac/Sicherungen/<Projekt>/
- Geklärt (Code): .plotwerk/ wird mitgesichert; der SQLite-Index liegt nicht im Projektordner
- Geklärt (Code): Ein Ordner nach Wahl braucht eine eigene, enge Freigabe im neuen Command
- Annahme: Dateiname <Projekt>-<YYYY-MM-DD>-<HHmm>.zip, die Rotation fasst nur dieses Muster an
- Annahme: Aufbewahrung 7 täglich und 4 wöchentlich
- Annahme: Recherche-Bilder werden mitgesichert
- Annahme: Sicherungsfehler blockieren nie das Schreiben, Hinweis mit Grund
- Annahme: In der Browser-Demo entfällt die Sicherung, Menüpunkt und Einstellung sind ausgeblendet

## Prüfbare Akzeptanzkriterien
- AC-1: Wenn ich ein Projekt an einem Tag zum ersten Mal öffne, dann liegt danach eine ZIP-Datei im Sicherungsordner, und der Projektordner bleibt unverändert. (Paket 2)
- AC-2: Die ZIP-Datei enthält alle Projektdateien inklusive .plotwerk/, aber keine Temp-Dateien und kein .DS_Store. .versionen/ fehlt, wenn die Einstellung aus ist. (Paket 1)
- AC-3: Nach mehr als 7 täglichen Sicherungen bleiben die neuesten 7 Tagesstände und je Woche einer für 4 Wochen. Andere Dateien im Ordner bleiben unberührt. (Paket 1)
- AC-4: 'Ablage → Projekt als Archiv sichern …' legt sofort eine Sicherung an, auch wenn es heute schon eine gibt. (Paket 2)
- AC-5: Vom Startbildschirm aus lässt sich eine Sicherung in einen neuen Ordner entpacken und öffnen. Der Inhalt gleicht dem gesicherten Stand. (Paket 3)
- AC-6: Der neue Rust-Command lehnt Pfade außerhalb des Sicherungsordners, '..' und andere Dateiendungen als .zip ab. (Paket 1)
- AC-7: Ist der Ordner nicht beschreibbar, erscheint ein Hinweis mit Grund in DE und EN. Schreiben und Autosave laufen weiter. (Paket 2)
- AC-8: Die automatische Sicherung beim ersten Öffnen verlängert das Beenden nicht über die bestehende Frist von 3 s hinaus. Es gibt keinen Sicherungslauf beim Beenden. (Paket 2)

## QS und Nachweis
- Vitest in core/: Dateiauswahl, ZIP-Aufbau gegen MemoryFs, Rotation mit festen Zeitpunkten
- UI-Tests für Menübefehl, Einstellung und Wiederherstellen-Dialog mit gemocktem Backend (Paket 2 und 3)
- Rust-Unit-Tests für Pfadprüfung und Namensmuster
- npm test, npm run typecheck und npm run build grün; npm run sperrliste vor dem Commit; Commits mit -s
- Manuell auf dem Mac: Tages-Sicherung, Ordner nach Wahl, Wiederherstellen mit Recherche-Bildern, nicht beschreibbarer Ordner

## Offene Fragen
–

_Automatisch nach dem Formular „Agent-Auftrag“ strukturiert (Hermes-Triage). Die ursprüngliche Beschreibung steht unten unverändert._
<!-- hermes-agent-form-v1:end -->

<details><summary>Ursprüngliche Beschreibung</summary>

<!-- hermes-original:start -->
### Ziel und Nutzen

Als Autorin möchte ich, dass Plotwerk mein Projekt regelmäßig als ZIP außerhalb des Projektordners sichert, damit ich auch dann einen Stand habe, wenn der Ordner selbst beschädigt, gelöscht oder von einem Sync-Dienst zerstört wird.

### Ist-Zustand / Problem

- Gesichert wird nur im Projektordner: Autosave und Schnappschüsse in `.versionen/` (`docs/handbuch.md:53,224`, E8). Die Aufbewahrung regeln `isoWoche` und `zuLoeschen` (`core/versionen/index.ts:107-137`) sowie `aufbewahrungAnwenden` (`core/versionen/index.ts:162`).
- Geht der Projektordner verloren, sind die Schnappschüsse mit weg. Eine Sicherung an anderem Ort gibt es nicht.
- Alle `fs_*`-Commands arbeiten relativ zum geöffneten Projekt. Der Pfadwächter lehnt absolute Pfade und `..` ab (`src-tauri/src/pfad.rs:1-30`). Dateien außerhalb schreibt nur `extern_dateien.rs`, und nur an Pfade, die der native Dialog in dieser Sitzung geliefert hat (`src-tauri/src/extern_dateien.rs:1-2`).
- `jszip` ist schon eine Abhängigkeit (`package.json:35`) und wird in `core/epub` und `core/docx` genutzt.
- Beim Beenden wartet der Rust-Kern höchstens 3 s auf die Oberfläche (`src-tauri/src/beenden.rs:12`).

### Umfang (In Scope)

- ZIP des ganzen Projekts mit allen Projektdateien inklusive `.plotwerk/` und `recherche/`. Ohne Temp-Dateien und `.DS_Store`. `.versionen/` optional (Einstellung).
- Auslöser: einmal täglich beim ersten Öffnen des Projekts und/oder beim Beenden (siehe Offen).
- Zielordner: Standard `~/Library/Application Support/app.plotwerk.mac/Sicherungen/<Projekt>/`, alternativ ein Ordner nach Wahl. Gespeichert als App-Einstellung (`einstellung_lesen`/`einstellung_schreiben`, `src-tauri/src/projekt.rs:401,411`), nie im Projektordner.
- Rotation, z. B. 7 tägliche und 4 wöchentliche Sicherungen. Logik als reine Funktion in `core/` (wie `zuLoeschen`).
- Menüpunkt „Ablage → Projekt als Archiv sichern …“ (DE/EN) für eine Sicherung von Hand.
- Wiederherstellen vom Startbildschirm (`src/app/Startbildschirm.tsx`): Sicherung wählen, in einen neuen, leeren Ordner entpacken und öffnen.
- Rust: ein neuer, eng begrenzter Command. Er schreibt, listet und löscht nur ZIP-Dateien mit festem Namensmuster im Sicherungsordner. Der Pfadwächter für `fs_*` bleibt unverändert.
- Einstellungen: an/aus, Ort, mit oder ohne `.versionen/`. Texte in `src/i18n/{de,en}`.

### Nicht Teil dieses Issues (Out of Scope)

- Sicherung in Cloud-Dienste oder auf Server.
- Verschlüsselung der ZIP-Dateien.
- Wiederherstellen in den bestehenden Projektordner (Überschreiben).
- Änderungen an der Schnappschuss-Politik E8.
- Erkennen von Sync-Konflikten (siehe Issue zu Konfliktkopien und doppelten Kapitel-IDs).

### Fachliche und UX-Entscheidungen

- Geklärt (Code): `.plotwerk/` ist kein Cache. Dort liegen die bezahlten KI-Ergebnisse (E2, `docs/architektur.md:12`; Pfade in `core/projekt/lesen.ts:81-117`). Es wird deshalb mitgesichert. Der einzige Cache ist der SQLite-Index `plotwerk-index.db` (`src-tauri/src/index.rs:7`), und der liegt nicht im Projektordner.
- Geklärt (Code): Externe Pfade sind heute nur über den Dialog erlaubt. Ein gemerkter Ordner nach Wahl braucht daher eine eigene, enge Freigabe im neuen Command.
- Annahme: Dateiname `<Projekt>-<YYYY-MM-DD>-<HHmm>.zip`. Die Rotation fasst nur Dateien mit diesem Muster an.
- Annahme: Eine Sicherung beim Beenden darf das Beenden nicht über die 3-s-Frist hinaus aufhalten. Reicht die Zeit nicht, entfällt sie, und die nächste tägliche Sicherung holt sie nach.
- Annahme: Fehler beim Sichern blockieren nie das Schreiben. Sie erscheinen als Hinweis mit Grund.
- Annahme: In der Browser-Demo entfällt die Sicherung. Menüpunkt und Einstellung sind dort ausgeblendet.
- Leerer Zustand: Ohne Sicherungen zeigt „Wiederherstellen“ einen Hinweis.
- Offen (Leon): Standardort `~/Library/Application Support/app.plotwerk.mac/Sicherungen/` oder ein sichtbarer Ordner, etwa in `~/Documents`?
- Offen (Leon): Aufbewahrung 7 täglich und 4 wöchentlich, oder anders?
- Offen (Leon): Täglich, beim Beenden oder beides?
- Offen (Leon): Recherche-Bilder (`recherche/dateien/`) mitsichern? Sie können groß werden.

### Prüfbare Akzeptanzkriterien

AC-1: Wenn ich ein Projekt an einem Tag zum ersten Mal öffne, dann liegt danach eine ZIP-Datei im Sicherungsordner, und der Projektordner bleibt unverändert.
AC-2: Die ZIP-Datei enthält alle Projektdateien inklusive `.plotwerk/`, aber keine Temp-Dateien und kein `.DS_Store`. `.versionen/` fehlt, wenn die Einstellung aus ist.
AC-3: Nach mehr als 7 täglichen Sicherungen bleiben die neuesten 7 Tagesstände und je Woche einer für 4 Wochen. Andere Dateien im Ordner bleiben unberührt.
AC-4: „Ablage → Projekt als Archiv sichern …“ legt sofort eine Sicherung an, auch wenn es heute schon eine gibt.
AC-5: Vom Startbildschirm aus lässt sich eine Sicherung in einen neuen Ordner entpacken und öffnen. Der Inhalt gleicht dem gesicherten Stand.
AC-6: Der neue Rust-Command lehnt Pfade außerhalb des Sicherungsordners, `..` und andere Dateiendungen als `.zip` ab.
AC-7: Fehlerfall: Ist der Ordner nicht beschreibbar, erscheint ein Hinweis mit Grund in DE und EN. Schreiben und Autosave laufen weiter.
AC-8: Das Beenden dauert durch die Sicherung nicht länger als die bestehende Frist von 3 s.

### QS und Nachweis

- Agent: Vitest in `core/` für Dateiauswahl (Ausschlüsse), ZIP-Aufbau mit `jszip` gegen `MemoryFs` und Rotation (Zeitpunkte fest vorgegeben). UI-Tests für Menübefehl, Einstellung und Wiederherstellen-Dialog mit gemocktem Backend. Rust-Unit-Tests für den neuen Command (Pfadprüfung, Namensmuster); `cargo test` läuft in der CI auf macOS. `npm test`, `npm run typecheck` und `npm run build` grün.
- Manuell auf dem Mac: tägliche Sicherung, Sicherung beim Beenden, Ordner nach Wahl, Wiederherstellen eines Projekts mit Recherche-Bildern, nicht beschreibbarer Ordner.

### Technischer Kontext und Referenzen

- Relevante Dateien: `core/versionen/index.ts`, `core/projekt/lesen.ts` (`PFADE`), `core/epub/index.ts` (Beispiel für `jszip`), `src-tauri/src/extern_dateien.rs`, `src-tauri/src/pfad.rs`, `src-tauri/src/projekt.rs`, `src-tauri/src/beenden.rs`, `src-tauri/src/menue.rs`, `src/app/Startbildschirm.tsx`, `src/state/funktionen.ts` (Muster für App-Einstellungen).
- Architektur: E2, E8, E9 und „Rust-Kommandos“ in `docs/architektur.md`.
- Verwandt: Issue zu Konfliktkopien von iCloud und OneDrive und doppelten Kapitel-IDs.

### Sicherheits- und Liefergrenzen

- [X] Das Issue enthält keine Secrets, Tokens, Zugangsdaten oder vertraulichen Manuskript- und Kundendaten.
- [X] Der Agent darf Code und Tests ändern sowie einen Draft-PR öffnen, aber nicht selbst mergen, releasen oder deployen.
- [X] Änderungen an produktiver Infrastruktur oder veröffentlichten Releases sind nicht Teil dieses Auftrags.

_Angelegt von Claude Code im Auftrag von @leonatwork auf Basis einer Code-Analyse (Stand 2026-10-20)._
<!-- hermes-original:end -->

</details>

Zusätzliche Repo-Regeln:
Commits tragen ein DCO-Sign-off (das macht dev-loop automatisch). Auf diesem Server gibt es kein Rust/Tauri: nur TypeScript-Teil (core/, src/) mit npm run build und npm test prüfen, src-tauri nicht bauen. Keine Inhalte aus privaten Manuskripten; Beispiele nur aus fixtures/. Farben nur über Tokens in src/theme/tokens.css, UI nach docs/design/screens, core/ bleibt reines TypeScript, core/ki nutzt nur ProjektLeser.

Reviewer verdict: CHANGES_REQUESTED after 3 round(s). Generated by dev-loop (not pushed).

Signed-off-by: leonatwork <leon.11@live.de>
…Durchlauf ist mit offenen Review-Befunden zu Ende gegangen. Behebe ausschließlich diese offenen Befunde vollständig (prüfe zuerst am Code, ob jeder zutrifft), halte dich an CLAUDE.md/AGENTS.md und führe die passenden Tests aus. Lies den Issue-Thread nur, wenn ein Befund ohne ihn nicht klar ist.

Offene Befunde:
- `src-tauri/src/sicherungen.rs:80-83`: rustfmt ist noch nicht vollständig nachgezogen. Die zwei Zeilen aus der vorigen Runde sind behoben (`:467-470` und `:488-490` sind jetzt korrekt im Binärausdruck-Stil umbrochen). Das damals genannte Beispiel `fehler(crate::sprache::t("Ungültiger …` ist aber weiter auf vier Zeilen verteilt. Einzeilig hätte ` return Err(fehler(crate::sprache::t("Ungültiger ZIP-Name", "Invalid ZIP name")));` nur 89 Zeichen. `Err` und `fehler` haben je nur ein Argument, und die Argumente von `t` sind 41 Zeichen breit, also unter `fn_call_width` 60. Deshalb würde rustfmt die Ze
- `src-tauri/src/sicherungen.rs:220-223`: Gleiches Problem in der Kette von `sicherung_ordner_waehlen`. ` .set_title(crate::sprache::t("Sicherungsordner wählen", "Choose Backup Folder"))` hätte nur 88 Zeichen, mit einem Argument für `set_title` und 49 Zeichen Argumentbreite für `t`. rustfmt würde das auf einer Zeile lassen, die aktuelle Aufteilung auf vier Zeilen fällt bei `cargo fmt --check` durch. Fix: auf eine Zeile zusammenziehen bzw. `cargo fmt` übernehmen.

Reviewer verdict: APPROVE after 1 round(s). Generated by dev-loop (not pushed).

Signed-off-by: leonatwork <leon.11@live.de>
Signed-off-by: leonatwork <leonatwork@users.noreply.github.com>
…b-issue-12-vollst-ndig-un-1020-1433

Signed-off-by: leonatwork <leonatwork@users.noreply.github.com>

# Conflicts:
#	src/app/befehle.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Agent] Automatische Sicherung als ZIP außerhalb des Projektordners

1 participant