Commit Graph
292 Commits
Author SHA1 Message Date
mhoennigandClaude Opus 5 0f3bd8f5b8 feat(backend): Zeilen-Diff als reine Funktionen (Live-Editing, Schritt 1)
Anwenden, Berechnen, Rebasen und Pruefsumme in de.werkbaum.diff — ohne
Spring, damit die Regeln ohne Kontext pruefbar sind. Grundlage fuer
PATCH /content und den Aenderungsfeed (D76).

Beim Bauen entschieden, was das Konzept offenliess: Eine Einfuegung ist ein
Punkt ZWISCHEN den Zeilen und kollidiert nur mit dem Inneren eines fremden
Bereichs (start < index < end). Beide im Konzept genannten Folgen gelten
damit weiter — zwei Einfuegungen an derselben Stelle vertragen sich, eine
Einfuegung in einen geloeschten Bereich nicht —, aber die Raender bleiben
konfliktfrei: Wer eine Zeile ueber einer gerade geaenderten einfuegt,
bekommt keinen 409.

49 Tests. Gegenprobe: Rand-Regel auf halboffen mutiert -> genau die zwei
danach benannten Zusicherungen fallen; fremde Einfuegung an gleicher Stelle
nicht mitgezaehlt -> genau die eine.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 16:41:33 +02:00
mhoennigandClaude Opus 5 9e5f546d76 docs: Speicherzahlen der Zielumgebung berichtigt (D76-Nachtrag 3)
Nachtrag 2 nannte "832 MB frei" - ein Schnappschuss, und dazu mehrdeutig
zwischen `free` und `available`. Nachgemessen: 326-358 MB free, 978-1004 MB
available von 3915 MB, dazu ~1 GB Swap belegt.

Falsch war ausserdem die Annahme, ein Managed Webspace koenne den Verbrauch
nicht zuordnen. `hidepid=invisible` verbirgt zwar fremde Prozesse, aber das
systemd-cgroup-Accounting (`systemctl status pacs-<paket>.slice`, so auch im
Hostsharing-Wiki) und die world-readable atop-Aufzeichnungen unter
/var/log/atop/ geben sie her.

Befund: nicht die Datenbanken. clamav-daemon 988 MB gegen mariadb 150 MB und
postgresql 111 MB; alle zwoelf Webspaces zusammen 100 MB. MariaDB haelt
602 MB im Swap - die DBs sind auf je 25 % des RAM provisioniert und verlieren
gegen den Virenscanner.

Fuers Deployment: pacs-mih00.slice hat MemoryMax=3147M - eine Erlaubnis, keine
Reservierung. `-Xmx` gehoert gegen das Freie bemessen; die JVM-Voreinstellung
(~980 MB) ist genau die Groesse, die MariaDBs Puffer verdraengt hat.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 15:57:06 +02:00
mhoennigandClaude Opus 5 af8a7b74b3 docs: Feed nur im sichtbaren Tab (D76-Nachtrag 1)
Der Zielserver bietet kein HTTP/2, also gilt das Browser-Limit von sechs
Verbindungen je Herkunft - ein dauerhaft offener Long-Poll je Tab engt bei
mehreren Tabs alles andere ein. Der Feed schliesst deshalb bei
visibilitychange und holt beim Zurueckkommen mit dem eigenen since nach.
Ein Hintergrund-Tab braucht keinen Live-Feed; das spart nebenbei
Server-Worker und Akku. Ein SharedWorker waere sauberer, ist aber eine eigene
Baustelle fuer ein Problem, das die einfache Loesung praktisch beseitigt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 15:30:03 +02:00
mhoennigandClaude Opus 5 b6509ae537 test(backend): Kotest-Assertions statt JUnit, CLAUDE.md berichtigt
backend/CLAUDE.md sah Kotest-Assertions vor, der Code benutzte aber die
JUnit-Assertions. Umgestellt bei 25 Aufrufen in zwei Dateien - jetzt billig,
und Test-Abhaengigkeiten sind unkritisch, weil sie in keinem Artefakt landen.
Wo Kotest spezifischer ist, ersetzt es die handgeschriebenen Meldungen:
shouldContain statt assertTrue(contains, "..."), withClue nur noch dort, wo
der Kontext wirklich hilft.

Gegenprobe per Mutation: eine falsche Erwartung im Service-Test und eine im
BDD-Schritt lassen genau die danach benannten Tests fallen.

CLAUDE.md berichtigt: Das Backend ist nicht mehr "noch nicht bootstrapped",
die Konfiguration heisst application.yaml, die Schichten entsprechen dem
tatsaechlichen Aufbau, und die drei Spring-Boot-4-Fallen von heute sind
festgehalten, damit sie niemanden erneut treffen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 15:29:24 +02:00
mhoennigandClaude Opus 5 f3afc8dfa8 refactor(backend): Paketwurzel de.werkbaum, Tests auf RestTestClient
Das Backend-Geruest kam unter der Platzhalter-Wurzel com.example.editor
herein und widersprach backend/CLAUDE.md. Umgezogen nach de.werkbaum: 17
Kotlin-Dateien, Gradle-group, apiPackage/modelPackage der OpenAPI-Generierung,
die jacoco-Ausschluesse und das Cucumber-glue-Paket. Jetzt war es billig, mit
jeder Woche Entwicklung waere es teurer geworden.

Die BDD-Tests nutzen jetzt RestTestClient statt TestRestTemplate, das in
Spring Boot 4 als Auslaufmodell gilt. Weil Cucumber Senden und Pruefen
trennt, wird die fluent API nicht fuer Zusicherungen genutzt, sondern ueber
returnResult das Ergebnis festgehalten.

Nachgemessen: 22 Tests gruen, check inklusive Coverage-Verifikation besteht,
91,7 % Zeilenabdeckung, generierter Code weiterhin ausgeschlossen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 15:21:34 +02:00
mhoennigandClaude Opus 5 7684872a42 docs: Proxy-Weg gemessen, JDK entschieden (D76-Nachtrag 2)
RewriteRule [P] ist in der .htaccess erlaubt - gemessen mit einer temporaeren
Regel auf einen lokalen Testprozess, danach vollstaendig zurueckgebaut.
Sofortige Antwort HTTP 200 nach 0,13 s, absichtlich um 30 s verzoegerte
Antwort HTTP 200 nach 30,1 s: Apache haelt die Verbindung durch und puffert
nichts weg. Long Polling mit wait=25 ist damit gemessen tragfaehig, nicht nur
rechnerisch. Die Regel gehoert nach scripts/prod.htaccess, weil deploy-prod.sh
die Datei mit rsync --delete spiegelt.

JDK: eigenes 21 ins Home statt Toolchain auf die installierte 17 senken.
GraalVM Native Image ist vorgemerkt statt verworfen - es spart den Grossteil
des knappen RAM (nur 832 MB frei auf einem geteilten Server), scheitert aber
vorerst an der glibc-Differenz, an Liquibase/Hibernate-Metadaten und an einem
offenen Boot-4-Fehler fuer genau diese Kombination. Kotlin/Native scheidet
grundsaetzlich aus: Spring, Hibernate und JDBC sind JVM-Bibliotheken.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 15:13:56 +02:00
mhoennigandClaude Opus 5 2540bbf0a7 docs: Live-Editing-Konzept entschieden und eingearbeitet (D76)
Die offenen Punkte der beiden Entwuerfe sind beantwortet und in beide
Dokumente eingearbeitet. Die wichtigsten Aenderungen am Protokoll:

- Der Server rebased selbst; 409 nur noch bei echter Ueberlappung. Reines
  Ablehnen fuehrt zu Starvation - ein Client mit hoeherer Latenz kommt bei
  fleissigen Mitschreibern womoeglich nie durch.
- Der Feed arbeitet auf der Historie statt am Dokument, sonst koennte er
  ausgerechnet das Loeschen nicht melden, das er melden soll.
- Historie in zwei Ebenen: kurzlebige Sync-Versionen und nutzersichtbare
  Meilensteine (nach Schreibpause und auf Knopfdruck, wie D54).
- Pruefsumme als Pflichtfeld, clientId + seq gegen doppelt angewendete
  Patches, Volltext im Feed fuer zu alte Staende, eigener Aenderungstyp fuer
  den Rollback, Titel im Feed-Ereignis.
- Zugriff ueber die unerratbare UUID; GET /documents bekommt ein
  Master-Passwort (Spring Security).

Die Client-Instruktion war fuer ein anderes Frontend geschrieben: Sie nannte
CodeMirror, TypeScript, jsdiff und MSW. Werkbaum hat eine rohe textarea,
Vanilla JS und keine Laufzeit-Abhaengigkeiten - CodeMirror bleibt eine eigene
Entscheidung (gemessen: 120 kB gzip Einstieg, danach nur 18 kB fuer alles
Weitere).

Zielumgebung vermessen: Apache 2.4.68 mit MPM event, 1024 Worker,
Timeout 300 - Long Polling traegt dort. Offen bleiben fehlendes HTTP/2,
nur Java 17 statt 21 und der ungeklaerte Weg vom Apache zum Backend.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 15:04:00 +02:00
mhoennig 40db41531e add gradlew to .gitignore 2026-08-26 13:20:14 +02:00
mhoennig 0446e3d81e initial backend: Dokumente, Historie, API und Persistenz (D76)
- Liquibase-Schema (`document`, `document_history`) + Rollback-scripts
- Spring Boot with JPA-repositories, entities and services
- REST-API (`/documents`, `/documents/{id}`, `/documents/{id}/history`)
- OpenAPI-specifikation for CRUD-Operationen and history
- config files (`application.yaml`, `Liquibase`, H2 im PostgreSQL-Modus)
- preps for future live-editing/delta-updates
- Exceptions for conflikt- and not-found cases (409/404)
- keeping document hostory even after `delete` for RESTORE functionality
2026-08-26 12:56:27 +02:00
mhoennig 4e0ce51820 docs: Werkbaum-Plan — 3 Knoten in Produktion
Beim Deploy der stabilen Instanz gehen diese Knoten live; SPEC §4
unterscheidet [x] fertig von [^] in Produktion (D30):

- #ed.deplink.fold: A hidden endpoint falls to its visible ancestor (S)  %% source and target alike, see D75
- #ed.deplink.toggle: A switch hides the cross links
- #ed.fold.preset: The fold button cycles through four presets (S)  %% M-and-smaller, off-path, all, none — see D44/D75
2026-08-25 17:20:48 +02:00
mhoennigandClaude Fable 5 33443016ce feat: Querverbindungen folgen der Faltung + Schalter; Falt-Knopf mit vier Voreinstellungen (D75)
- Abhängigkeits-Kanten enden am nächsten sichtbaren Vorfahren, für Quelle
  wie Ziel; zusammengefallene Kanten entfallen bzw. werden dedupliziert
  (data-sub-ids/data-sub-deps am eingeklappten Vertreter, SPEC §9)
- Umschalter für die Querverbindungen neben dem Günstigster-Pfad-Knopf,
  Voreinstellung an, persistiert; Export und Druck folgen ihm
- Der Falt-Knopf schaltet durch: M und kleiner zu → alles abseits des
  Pfads zu → alles zu → alles offen; Icon/Tooltip zeigen den nächsten
  Schritt, Handfaltung setzt die Position zurück (presetFoldSet, model.js)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 17:19:32 +02:00
mhoennigandClaude Fable 5 69c9be7a6d feat: Brave-Hinweis nennt die Flag-Adresse zum Einschalten der API (D72-Nachtrag 4)
Nur in Brave (navigator.brave) bekommt das Datei-Banner eine zweite Zeile
mit brave://flags/#file-system-access-api als kopierbarem Code-Text —
verlinken lassen sich interne Schemata nicht. i18n in neun Sprachen, die
Adresse selbst steht einmal im Code.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 16:10:47 +02:00
mhoennigandClaude Fable 5 bf6eceeb9d fix: Hinweis und Legende nennen das Feature statt „Chromium" (D72-Nachtrag 3)
Brave ist Chromium-basiert, schaltet File System Access aber bewusst ab —
die Begründung „Chromium-Browser schreiben direkt zurück" widersprach dort
dem eigenen Erleben. Alle 18 UI-Strings (fsNotice + hint_save, 9 Sprachen)
nennen jetzt die Schnittstelle und Beispiel-Browser (Chrome/Edge).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 16:02:30 +02:00
mhoennigandClaude Fable 5 b16f9954a9 feat: Einmaliger Hinweis in Browsern ohne File System Access (D72-Nachtrag 2)
Firefox/Safari laden Dateien als Kopie und speichern als Download — beim
ersten Öffnen/Speichern erklärt ein Banner die Grenze (i18n in neun
Sprachen, „Verstanden" merkt der localStorage, Reset räumt mit).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 15:53:42 +02:00
mhoennigandClaude Fable 5 731a383345 fix: Speichern-Dialog zeigt auf die Originaldatei statt auf einen „(1)"-Nachbarn (D74-Nachtrag)
Mit bekanntem, aber nicht beschreibbarem Handle bekommt showSaveFilePicker
startIn + den exakten Dateinamen; ohne Handle teilen sich Öffnen und
Speichern eine Picker-id, damit der Dialog im Plan-Ordner aufgeht statt in
Downloads. Der Abbruch-Kreislauf (Dialog schlägt Falsches vor -> Abbruch ->
kein Handle gemerkt -> wieder Dialog) ist damit durchbrochen.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 15:46:07 +02:00
mhoennig 532bbace21 docs: Werkbaum-Plan — 1 Knoten in Produktion
Beim Deploy der stabilen Instanz gehen diese Knoten live; SPEC §4
unterscheidet [x] fertig von [^] in Produktion (D30):

- #ed.files.ctrls: Ctrl+S saves the document as a file (XS)  %% in place with a remembered handle
2026-08-25 15:18:42 +02:00
mhoennigandClaude Fable 5 72ab9746d5 feat: Strg+S speichert das Dokument direkt als Datei (D74)
Die Geste, die jeder zuerst versucht, tat bisher das Falsche (Browser-Dialog
„Seite speichern"). Jetzt ruft sie saveLocalFile(): mit gemerktem Handle
dialogfrei in dieselbe Datei, sichtbar bestätigt durch einen Petrol-Haken am
Dokumentnamen; ohne Handle wie der Menü-Eintrag. Legenden-Zeile hint_save in
neun Sprachen. Nebenbefund behoben: adoptFile() wartet jetzt auf die aus
IndexedDB zurückgeholten Handles — ein Doppelklick unmittelbar nach dem
App-Start legte sonst ein Duplikat an statt dasselbe Dokument zu
aktualisieren.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 15:15:50 +02:00
mhoennig 45a52c15f9 docs: Werkbaum-Plan — 5 Knoten in Produktion
Beim Deploy der stabilen Instanz gehen diese Knoten live; SPEC §4
unterscheidet [x] fertig von [^] in Produktion (D30):

- #bld.pwa: Installable as a progressive web app
- #bld.pwa.manifest: A manifest with name, icons and standalone display
- #bld.pwa.sw: A service worker that serves the app offline (S)  %% network-first, cache as fallback
- #bld.pwa.update: The reload notice stays truthful under the worker (S)  %% see D45/D73
- #bld.pwa.files: Double-click a .werkbaum file, save without any dialog (S) :#ed.files.inplace  %% file_handlers + launchQueue
2026-08-25 15:05:20 +02:00
mhoennigandClaude Fable 5 19053eba1d feat: Als PWA installierbar — Manifest, Offline-Worker (network-first), Dateihandling (D73)
Manifest mit Icons aus der Marke und Standalone-Fenster; ein bewusst dummer
Service Worker beantwortet nur die App-Navigation network-first und hält die
zuletzt gesehene Fassung für den Offline-Fall — die Update-Prüfung (D45)
bleibt dadurch unverändert wahr, der skipWaiting-Lebenszyklus entfällt. Die
installierte App registriert sich für .werkbaum-Dateien (file_handlers +
launchQueue -> adoptFile). Beide Deploy-Wege kopieren die App-Hülle mit;
.htaccess liefert .webmanifest mit MIME-Typ aus.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 15:03:22 +02:00
mhoennigandClaude Fable 5 f6785e3138 docs: PWA-Dateihandling als Plan-Knoten (#bld.pwa.files)
Installierte App registriert sich für .werkbaum (file_handlers), Doppelklick
öffnet mit fertigem Handle aus der launchQueue, Speichern ohne Dialog —
hängt an der vorhandenen Stufe-2-Mechanik (:#ed.files.inplace).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 14:46:24 +02:00
mhoennig c00ff75346 docs: Werkbaum-Plan — 2 Knoten in Produktion
Beim Deploy der stabilen Instanz gehen diese Knoten live; SPEC §4
unterscheidet [x] fertig von [^] in Produktion (D30):

- #ed.files: Open and save .werkbaum files
- #ed.files.inplace: Saving writes back into the opened file (S)  %% File System Access, Chromium
2026-08-25 14:32:01 +02:00
mhoennigandClaude Fable 5 2648d72e45 feat: Speichern schreibt in die geöffnete Datei zurück (D72-Nachtrag, Stufe 2)
File System Access API, wo vorhanden (Chromium): Öffnen merkt sich das
FileSystemFileHandle (IndexedDB, überlebt den Neustart), Speichern schreibt
in dieselbe Datei; dieselbe Datei öffnet per isSameEntry wieder in dasselbe
Dokument. Firefox/Safari behalten den Stufe-1-Download.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 14:31:51 +02:00
mhoennigandClaude Fable 5 defeaf84d0 feat: Lokale Dateien öffnen und als Datei speichern (D72, Stufe 1)
Zwei Einträge im Dokumenten-Menü: „Datei öffnen…" (Datei-Input, neues
Dokument, Dateiname als Name) und „Als Datei speichern" (Blob-Download,
Dateiname aus dem Dokumentnamen via localfile.js). Läuft in jedem Browser;
Stufe 2 (File System Access, Chromium) folgt.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 14:26:31 +02:00
mhoennig ced3507678 docs: Werkbaum-Plan — 1 Knoten in Produktion
Beim Deploy der stabilen Instanz gehen diese Knoten live; SPEC §4
unterscheidet [x] fertig von [^] in Produktion (D30):

- #ed.path.load: Warn when one person is the bottleneck (S)  %% see D71
2026-08-25 11:32:07 +02:00
mhoennigandClaude Fable 5 ea25e87831 docs: Werkbaum-Plan — AI-Integration als Idee notiert (#ai)
LLM oder Agentic AI mit eigenem API-Key anbinden, um den Plan im Dialog
zu bearbeiten; llms.md als Grundlage des System-Prompts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 11:31:46 +02:00
mhoennigandClaude Fable 5 35b72fc178 feat: Zuständigen-Engpass — Warnung, wenn eine Person mehr als die Hälfte des Pfads trägt (D71)
Trägt ein @name mehr als die Hälfte der offenen Arbeit des günstigsten
Pfads (Marginalkosten-Maß, D69) und tragen mindestens zwei Personen Last
auf der offenen Front, meldet die zeilenlose Warnung assigneeOverload die
mögliche Engstelle; die Pillen der Person wechseln an offenen Pfad-Knoten
auf die Warnfarbe. Knoten ohne Tags erben für die Rechnung vom nächsten
getaggten Vorfahren, mehrere Tags teilen sich den Beitrag.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 11:29:52 +02:00
mhoennig d1da6a3529 docs: Werkbaum-Plan — 1 Knoten in Produktion
Beim Deploy der stabilen Instanz gehen diese Knoten live; SPEC §4
unterscheidet [x] fertig von [^] in Produktion (D30):

- #ed.path.cost: Cost model, a size prices its subtree
2026-08-25 11:07:14 +02:00
mhoennigandClaude Fable 5 0de7f5f24e feat: Die geschätzte Größe bepreist den Rest — Erledigtes fällt aus der Schätzung (D70)
Die D66-Schätzung war status-blind: Ein größenloses Paket mit [x] (L) und
[ ] (S) wurde als L geschätzt, obwohl nur S offen ist. Erledigte Kinder
fallen jetzt heraus, eine erledigte realisierte Alternative stellt ihre
Gruppe fertig, und sind alle benannten Kinder erledigt, gilt XS (der eigene
Rest — M-Rückfall erhöhte den Preis beim Fertigwerden). Angegebene Größen
bleiben unangetastet (D69).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 11:04:26 +02:00
mhoennigandClaude Fable 5 4d80feb4e8 fix: Falt-Chip deckend weiß mit Tinte-Glyphe — Kontrast auf den Pastellfarben (D64-Nachtrag)
Die fast transparente Füllung mit mattgrauer Glyphe verschwand auf den
acht Status-Pastelltönen. Nur Farben geändert; line-height und Padding
bleiben (23-px-Geometrie).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 10:50:01 +02:00
mhoennigandClaude Fable 5 4aaa19becd feat: Die Größe bepreist den ganzen Teilbaum — Kinder zählen nicht obendrauf (D69)
Der Preis eines Knotens ist seine angegebene (oder D66-geschätzte) Größe;
die frühere Rekursion (eigene Größe plus Summe/Minimum der Kinder) zählte
doppelt und bestrafte sorgfältig zerlegte Pakete — eine zerlegte
S-Alternative verlor gegen ein grobes L. Das Vereinigungs-Maß der
Closure-Suche (D42) zählt je Knoten nur noch die Marge über seine nötigen
Teilpakete hinaus. Mitgelieferter Plan wählt identisch (per Vergleich
gemessen); SPEC §9 und llms.md nachgezogen.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 10:45:12 +02:00
mhoennigandClaude Fable 5 7278e74393 docs: Werkbaum-Plan — Größen-Regel (letztes Token) in #not.size erwähnt
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 10:20:24 +02:00
mhoennigandClaude Fable 5 59da485af6 feat: Größe ist das letzte alleinstehende (L)-Token der Zeile (D68)
Erkannt nur alleinstehend angesetzt (wie #id und :#…) — damit greifen die
Zitier-Konventionen "(L)" und ((L)) von selbst, und Backend(L) bleibt
Label. Das letzte Token gewinnt statt des ersten: Die Größe steht hinter
dem Titel, frühere Vorkommen sind Text. SPEC §1/§5 und llms.md nachgezogen;
mitgelieferte Beispiele unverändert (Parse-Vergleich alt/neu).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 10:19:52 +02:00
mhoennigandClaude Fable 5 9999c7973e fix: Klick-Erkennung des Abhängigkeits-Sprungs akzeptiert \s wie der Parser (D67)
Vor dem `:#…`-Token prüfte depIdAt nur Space/Tab, der Parser jedes \s —
vor einem geschützten Leerzeichen war das Token damit eine Abhängigkeit,
auf die Strg+Klick nichts tat. Test mit echtem NBSP; Gegenprobe: die alte
Prüfung lässt genau ihn fallen.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 09:54:29 +02:00
mhoennig 7236850f2b docs: Werkbaum-Plan — 1 Knoten in Produktion
Beim Deploy der stabilen Instanz gehen diese Knoten live; SPEC §4
unterscheidet [x] fertig von [^] in Produktion (D30):

- #ed.jump.dep: Ctrl+click follows a dependency to its id
2026-08-25 09:21:15 +02:00
mhoennigandClaude Fable 5 549c12191e feat: Strg+Klick auf :#id springt zur Zeile der referenzierten ID (D67)
Strg/Cmd+Klick auf eine Abhängigkeits-ID im Textfeld — auch jede ID der
Liste und die Kopf-Form #auth:#db — markiert die Zeile, die die ID vergibt;
Tastatur-Pendant Strg+Enter. Erste Vergabe gewinnt (D36/D39), unbekannte IDs
tun still nichts. Headless als depIdAt/idLine in autocomplete.js, 16 Tests;
Legenden-Zeile hint_jump in allen neun Sprachen erweitert.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 08:59:58 +02:00
mhoennig 54e27091ce docs: Werkbaum-Plan — 1 Knoten in Produktion
Beim Deploy der stabilen Instanz gehen diese Knoten live; SPEC §4
unterscheidet [x] fertig von [^] in Produktion (D30):

- #ed.path.est: Missing size estimated from the sub-packages (S)  %% see D66
2026-08-24 20:01:50 +02:00
mhoennigandClaude Fable 5 d95ce21143 docs: Plan-Knoten für die Größenschätzung aus Teilpaketen (D66)
`#ed.path.est` neu als [x]; das überholte „missing size counts as M" aus
Label und Beschreibung von `#ed.path.cost` entfernt. Der neue S-Knoten
kippte die Größenprüfung von `#ed.path` — ehrlich nachgezogen auf (XL).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 20:00:38 +02:00
mhoennigandClaude Fable 5 bb01045488 feat: Fehlende Größe aus den Teilpaketen geschätzt statt pauschal M (D66)
Mindestens die größte Größe der zählenden Kinder, ab drei Kindern dieser
Größe eine Stufe mehr (Deckel XXL); disjunktiv die kleinste Alternative,
rekursiv über größenlose Kinder, Blatt bleibt M. Badge, Tooltip und
aria-label zeigen die geschätzte Größe („mindestens {size} angenommen").

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 19:59:13 +02:00
mhoennigandClaude Fable 5 ebc5be407e feat: Label-Umbruch bei 32 statt 40 Zeichen (D64-Nachtrag 3)
Lange Titel zogen das Diagramm zu breit. Ein Parameter in wrapLabel(),
der 32ch-Rückhalt im CSS und SPEC §9 ziehen mit; Balance-Regel und
Erste-Zeile-Verankerung unverändert.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 18:36:52 +02:00
mhoennigandClaude Fable 5 07e4116bd9 fix: vertikale Sammelleiste erreicht den Eltern-Stub wieder (D65)
Zwei Geometrie-Fehler bei Gruppen mit wenigen Kindern: :only-child schaltete
die Leiste ab, obwohl Stub (50 %) und Abzweig (23 px) seit dem 20-px-
Zusatzabstand nicht mehr zusammenfallen (6,6–15,8 px Lücke); und bei einem
großen Teilbaum im letzten Kind endete die Leiste über dem Stub (bis 98 px).
Fix: CSS-Verbinder 23px→50 % am Einzelkind, alignVRails() + --vrail-ext für
das letzte Kind. Export und Kompakt-Modus waren nie betroffen.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 18:19:19 +02:00
mhoennig 94aa16efbd docs: Werkbaum-Plan — 2 Knoten in Produktion
Beim Deploy der stabilen Instanz gehen diese Knoten live; SPEC §4
unterscheidet [x] fertig von [^] in Produktion (D30):

- #ed.render.wrap: Long titles wrap into balanced lines (S)  %% max ~40 chars, see D64
- #ed.depcomplete: Typing :# suggests the known ids (S)  %% arrows choose, Enter inserts
2026-08-24 17:49:55 +02:00
mhoennigandClaude Fable 5 998fbc9daa docs: Legende vollständig ([!]-Chip, Größen-Prüfung), llms.md-Tabellen ausgerichtet
Der High-Risk-Status fehlte seit Juli in der Chip-Reihe der Legende;
hint_break nennt jetzt die Größen-Prüfung (D62), in allen neun Sprachen.
llms.md: Alignment-Marker an beiden Tabellen, die Größen-Bereiche als eigene
bündige Tabelle statt Prosa — inhaltlich war die Agenten-Fassung auf Stand
(Fortsetzungszeilen, ID-als-Titel, Größen-Konflikt, angefangene Zugaben).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 17:49:47 +02:00
mhoennigandClaude Fable 5 52232f2c20 feat: Labels brechen balanciert um, ID-Zeile über dem Titel, Falt-Chip — D64
Lange Knotentitel brechen bei ~40 Zeichen um, gleichmäßig auf die Zeilen
verteilt — vom Renderer (wrapLabel, headless getestet) statt text-wrap:balance,
damit der Kasten auf die längste balancierte Zeile schrumpft. Der
23-px-Abzweig ankert an der ersten Zeile; der Optional-Kreis sitzt fest auf
der Abzweighöhe. Der Grafikexport misst die gerenderten Zeilen (labelLines)
und gibt je Zeile ein <text> aus. Dazu: die eingeblendete ID (D56) steht in
einer eigenen Zeile über dem Titel, und das Falt-Zeichen ist ein gerahmter
19×16-px-Chip mit gedeckelter Höhe. Plan: #ed.render.wrap, #ed.render M→L
(D62-Prüfung schlug korrekt an).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 17:45:11 +02:00
mhoennigandClaude Fable 5 1debb7d9da feat: ID-Vorschläge beim Tippen von Abhängigkeiten (:#) — D63
Wer :# tippt, bekommt die vergebenen IDs als Liste an der Schreibmarke:
Präfix- vor Teilstring-Treffern, Knotentitel als Kontext, schon gelistete
und die eigene ID ausgenommen. ↑/↓ wählt, Enter/Tab übernimmt (undo-fähig),
Esc schließt; Live-Region für Screenreader. Eingabehilfe wie die Kurzform
(D55) — der Parser sieht nie etwas davon. Regeln headless in autocomplete.js
(20 Tests), app.js verdrahtet Popup, Tasten und Einfügen.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 17:13:18 +02:00
mhoennigandClaude Fable 5 9cb6ec1197 feat: eingeklappter Vorfahr vertritt die Cursor-Zeile im Diagramm (D38-Nachtrag 4)
Liegt der Knoten der Cursor-Zeile in einem eingeklappten Teilbaum, hebt
nodeOfLine() den nächsten sichtbaren Vorfahren hervor — Cursor-Mitlaufen,
Alt+Klick, Alt+Enter und der Mobil-Umschalter erben es über die eine
Auflösungsstelle. Ausgeblendete verworfene Elemente heben weiterhin nichts
hervor (SPEC §9). Zeilen-Map als lineTargets() headless in model.js, 5 neue
Tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 16:20:48 +02:00
mhoennig 6dfcb2b65c docs: Werkbaum-Plan — 1 Knoten in Produktion
Beim Deploy der stabilen Instanz gehen diese Knoten live; SPEC §4
unterscheidet [x] fertig von [^] in Produktion (D30):

- #not.sizes: Size conflict — sub-packages must fit the given size (S)  %% ranges, XXL open-ended, see D62
2026-08-24 16:00:14 +02:00
mhoennigandClaude Fable 5 5b37c117e1 feat: Größen-Konflikt — Teilpakete müssen zur angegebenen Größe passen (D62)
Größen zählen für diese eine Prüfung als Bereiche (Untergrenzen verdoppeln
sich, XXL nach oben offen); Konflikt erst, wenn selbst die günstigste Lesart
der Kinder die großzügigste des Elternknotens erreicht. Warnung sizeConflict
an der Elternzeile, Badge in --warn, Grund in Tooltip und aria-label. Nichts
wird automatisch korrigiert. Nebenbefund behoben: der Grafikexport zeichnete
das Größen-Badge mit festen Farben — das invertierte implizite M stand seit
jeher gefüllt im Bild. Die acht berechtigten Konflikte im eigenen Plan sind
nachgezogen. 372 Tests, 16 neue.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 15:55:16 +02:00
mhoennigandClaude Opus 5 257e1a9c17 chore: Vitest-Ergebnis-Cache aus der Versionsverwaltung nehmen
`node_modules/.vite/vitest/.../results.json` lag seit a8c5e54 versehentlich
im Repo: Die .gitignore deckte nur `frontend/node_modules/` ab, nicht das
`node_modules/` in der Wurzel. Die Datei ändert sich bei jedem Testlauf und
rutschte dadurch still in fremde Commits.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 15:20:08 +02:00
mhoennigandClaude Opus 5 6d58164577 fix: Abhängigkeits-Kanten laufen hinter den Knoten (D41-Nachtrag 2)
Die Basis-Kanten lagen schon richtig; „drüber gemalt" wurde allein die
Hervorhebung des ausgewählten Knotens (`svg.dep-front`, z-index 4). Eine
durchgezogene Linie quer über einen fremden Knoten durchstreicht dessen
Titel — und beim Tippen wechselt die Hervorhebung mit jeder Zeile.

`dep-front` entfällt; hervorgehobene Kanten hängen zuletzt in derselben
hinteren Ebene, liegen damit über den übrigen Kanten und unter jedem
Knoten. Export und Druck waren nie betroffen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 15:19:35 +02:00
mhoennig 6881475193 docs: Werkbaum-Plan — 1 Knoten in Produktion
Beim Deploy der stabilen Instanz gehen diese Knoten live; SPEC §4
unterscheidet [x] fertig von [^] in Produktion (D30):

- #ed.path.started: Started work is on the path, extras included (S)  %% see D61
2026-08-24 14:53:30 +02:00