Bugfix-Runde Panel/Archiv: Datenverlust, Suche, Löschen, Markdown

- ProjectConfig reicht unbekannte Keys durch (serde flatten). Bisher verlor
  jeder read-modify-write die Felder neuerer Versionen; so ging archiveHome
  bei der Pool-Zuweisung durch einen älteren Build verloren.
- Archiv-Suche: Nutzereingabe wird in einen FTS5-Ausdruck übersetzt, der nicht
  scheitern kann. ai-control, C++ oder eine halbe Phrase warfen bisher einen
  Syntaxfehler — bei der Live-Suche in jedem Tippzwischenstand.
- commands_delete: Befehlstext als Identität, Indizes werden geprüft. Bisher
  Panik oder Löschen der falschen Kachel, wenn die Panel-Indizes der Datei
  hinterherhingen.
- Archivieren überschreibt keine Datei mehr: Der Stempel hat Minutenauflösung,
  bei Kollision wird -2, -3, ... angehängt.
- archive_panel prüft erst auf leeres Panel, dann wird das Archiv-Home gesetzt;
  bisher blieb ein umkonfiguriertes Home trotz Meldung "nicht archiviert".
- Kaputte .claude.json eines Pools wird nicht mehr durch eine frische ersetzt;
  nur eine fehlende Datei rechtfertigt das.
- Archiv-Formular leert beim Schließen — sonst galten Ordner und Schlagwörter
  des vorigen Dokuments unbemerkt fürs nächste.
- Markdown fürs Panel entschärft (src/markdown.ts): rohes HTML wird als Text
  ausgegeben, Link- und Bildziele auf harmlose Schemata beschränkt. Das Panel
  teilt sich den Webview mit dem Terminal, dessen term_write in die PTY
  schreibt; ohne CSP war das ein Weg von Fremdinhalt zu Befehlsausführung.

Regressionstests je Fix: 73 Rust-Tests, 35 Frontend-Tests.
This commit is contained in:
marcusH
2026-07-19 23:04:17 +02:00
parent 1345ef799c
commit b127269e89
14 changed files with 306 additions and 28 deletions
+2 -2
View File
@@ -1,4 +1,4 @@
import { marked } from "marked";
import { renderMarkdown } from "./markdown";
import { writeText } from "@tauri-apps/plugin-clipboard-manager";
import { flash } from "./commands-view";
@@ -123,7 +123,7 @@ export function initPanelView(opts: {
function draw() {
if (rendered) {
opts.content.className = "md";
opts.content.innerHTML = marked.parse(rawText, { async: false });
opts.content.innerHTML = renderMarkdown(rawText);
if (opts.onWikiLink) linkWikiRefs(opts.content, opts.onWikiLink);
} else {
opts.content.className = "raw";