Commit Graph
90 Commits
Author SHA1 Message Date
mhoennigandClaude Opus 5 29a217f892 chore(repo): Umzug nach Gitea — GitHub bleibt Klon, main von Hand gespiegelt (D95)
Deploy to GitHub Pages / build (push) Canceled after 0s
Deploy to GitHub Pages / deploy (push) Canceled after 0s
Zuhause ist künftig git.javagil.de/mi/werkbaum (origin); GitHub bleibt unter
dem Remote `github` ein Klon, den scripts/push-github.sh mit `main` versorgt —
nur vorwärts, nie erzwungen.

Der Klon bleibt aus zwei gemessenen Gründen: Gitea sendet auf raw-Dateien kein
Access-Control-Allow-Origin (nachgemessen an mi/werkdock), die
?sourceUrl=-Beispiellinks der READMEs müssen also auf raw.githubusercontent.com
zeigen; und der Pages-Workflow lässt sich nicht mitnehmen.

Footer, llms.txt und llms.md zeigen jetzt auf Gitea (Repo-Seite ohne Anmeldung
lesbar, HTTP 200 geprüft); beide COMMIT_URL-Stellen (deploy-prod.sh und der
Pages-Workflow) ziehen mit. deploy-prod.sh prüft origin und github getrennt und
erinnert an das Spiegeln, statt selbst zu pushen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 17:26:15 +02:00
mhoennigandClaude Opus 5 2d78baf407 fix(editor): „nur ansehen" gilt jetzt dem Dokument, nicht nur dem Textfeld — auch das Diagramm faltet dort nicht mehr
Nutzer-Einwand, folgerichtig aus dem Vorgänger-Commit: Wenn Falten eine
Änderung ist, muss der Nur-Ansehen-Modus auch das Diagramm stillstellen —
im haltenden Fenster natürlich weiter nicht.

Es war schlimmer als eine fehlende Sperre: `readonly` hielt gar nichts auf.
`replaceTextUndoable` fällt auf `src.value = neu` zurück, wenn `execCommand`
scheitert, und eine Zuweisung an `value` schreibt auch in ein
schreibgeschütztes Feld. Nachgemessen: Ein Klick auf das Falt-Zeichen im
Nur-Ansehen-Fenster setzte `- > Ast A (M)` in Textfeld UND Speicher — der
Modus war nur eine Beschriftung.

Gesperrt wird jetzt an der Schreibstelle: eine Zeile in
`replaceTextUndoable` weist jeden programmatischen Schreibzugriff ab
(Falten, Durchschalter, „aus Taiga übernehmen", früherer Stand,
ID-Kurzform). Dazu ruhen die Gesten selbst, damit nichts still ins Leere
geht — toggleFold und der Durchschalter kehren früh um, Falt-Zeichen und
Knopf treten zurück und nehmen keinen Klick an (body.viewonly), und im
Knoten-Fenster entfallen die Aktionen, die in die Zeile schreiben.
„Nach Taiga schreiben" bleibt: Es fasst den Plan nicht an. Ansicht bleibt
Ansicht — Zoom, Modus, Pfad, Export, Sprünge unverändert bedienbar.

Nachgemessen mit zwei Fenstern: Chip, Tastatur und Durchschalter lassen im
Nur-Ansehen-Fenster Text und Speicher unangetastet; im haltenden Fenster
faltet dieselbe Geste weiter; verlässt es das Dokument, wird das andere von
selbst wieder beschreibbar und faltbar. SPEC §9, D94-Nachtrag 3 und
CHANGELOG nachgezogen; 666 Tests grün.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 20:28:20 +02:00
mhoennigandClaude Opus 5 2a58951138 fix(i18n): die Zwei-Fenster-Warnung nennt die zuletzt gespeicherte Änderung, nicht den letzten Tastendruck
Nutzer-Rückfrage: „Was für ein letzter Tastendruck?" — die Formulierung
liest sich, als zähle nur Tippen. Tut es nicht: Umklappen im Diagramm
schreibt die Faltmarke in den Text (D38-Nachtrag 2) und damit in den
Speicher, nimmt also am selben Wettlauf teil. Nachgemessen mit zwei
Fenstern: A klappt zu, im Speicher steht `- > Ast A (M)`, B's Editor und
Diagramm bleiben unverändert — und B's nächster Tastendruck überschreibt
den Speicher, A's Faltung ist weg.

Beide Texte in allen neun Sprachen umformuliert (tabConflictWarn,
docLockText); der Dialogtext nennt das Falten ausdrücklich. SPEC §9 sagt
jetzt dazu, dass das andere Fenster nichts nachzieht und dass ein
Dokumentwechsel dort nicht mitwandert — `werkbaum-active` entscheidet erst
wieder, was ein Neustart öffnet (auch das eine Nutzer-Rückfrage,
nachgemessen). D94-Nachtrag 2 und CHANGELOG nachgezogen.

Benannt, nicht behoben: Wer „trotzdem hier bearbeiten" gewählt hat, behält
die Warnung, auch wenn das andere Fenster das Dokument längst verlassen
hat — dieser Ausweg fordert die Sperre bewusst nicht mehr an.

666 Tests grün; die neuen Texte im laufenden Editor nachgesehen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 20:21:29 +02:00
mhoennigandClaude Opus 5 7f4c2a3e6a fix(editor): der Sperr-Dialog wählt das andere Dokument im Aufklapp-Feld — die Knopfliste quetschte ihre Beschriftungen ineinander
Gemeldet aus der produktiven Instanz: „die Buttons mit den anderen
Dokumenten überlappen sich und sind unleserlich". Ursache ist eine
Flexbox-Falle, nicht die Zahl der Dokumente: Die Liste war ein
flex-Spaltenkasten mit max-height 9rem, und ihre Knöpfe tragen serienmäßig
flex-shrink 1 — statt zu scrollen, schrumpfte der Kasten sie unter ihre
eigene Textzeile. Nachgemessen bei acht Dokumenten: 14,5 px Kastenhöhe
gegen 32 px Inhalt, 17,5 px Überstand je Knopf bei 4 px Abstand.

Statt der naheliegenden Reparatur (flex-shrink 0, dann scrollt die Liste)
das vom Nutzer gewählte Aufklapp-Feld: eine Zeile hoch, unabhängig von der
Anzahl — der Dialog steckt im Editor-Panel und ist dort ohnehin knapp. Die
Kopfzeile ist jetzt ein echtes <label for>, der Platzhalter ein Strich,
die Auswahl schaltet sofort um (dieselbe Ein-Klick-Geste wie der Knopf).
Kein neuer i18n-Schlüssel.

Nachgemessen: Feld 36 px, kein Überstand, Karte 364 -> 256 px; Auswahl
schaltet um, Dialog schließt, Textfeld wird beschreibbar. D94-Nachtrag und
CHANGELOG nachgezogen; 666 Tests grün.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 20:16:58 +02:00
mhoennigandClaude Opus 5 da872f795c docs(changelog): die Planungszeile zum Mehr-Fenster-Betrieb entfällt — sie stand neben dem gebauten Ergebnis
Der 2026-09-02 trug beide Aussagen zur selben Sache: die vier Zeilen „geht
jetzt" und darunter noch „recorded as planned … before it is built" aus dem
RFC-Commit desselben Tages. Im Neuigkeiten-Popup (D58) liest sich das
widersprüchlich — der Leser sieht ein Feature, das zugleich fertig und
geplant ist. Die Planungszeile geht, weil das Gebaute mehr sagt; die
MCP-Planungszeile daneben bleibt stehen, die ist wirklich noch ungebaut.

Ein Test liest die ausgelieferte Datei (news.test.js), 666 Tests grün.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 20:07:42 +02:00
mhoennigandClaude Opus 5 caaf7c15e1 feat(editor): Mehr-Fenster-Betrieb gebaut — Ablageschema v3, Tombstones, docsync, Sperre je Dokument (RFC 002, D94)
Kein Fenster schreibt mehr den Schlüssel eines anderen: Text, Meta und
frühere Stände liegen je Dokument unter eigenen Schlüsseln, der Index ist
nur noch Reihenfolge-Hinweis und löscht nie, Löschungen hinterlassen einen
Tombstone (7 Tage). Der Voll-Flush weicht dem Dirty-Flush. Damit sind
Befund 2 und 3 des RFC weg — verschiedene Dokumente in zwei Fenstern
kollidieren gar nicht mehr. docsync.js zieht Liste, Namen, Tombstones und
den Stände-Cache aus dem storage-Ereignis nach; am aktiven Dokument die
drei Fälle umbenannt / anderswo gelöscht (behalten, bis getippt wird) /
fremd geschrieben. Der modale D89-Dialog samt Präsenz-Kanal ist ersatzlos
raus; den einen Verlustfall — dasselbe nicht-`live:`-Dokument in beiden
Fenstern vorn — findet eine Sperre per Web Locks, und das zweite Fenster
bekommt drei Auswege statt „trotzdem fortfahren".

Im Browser mit zwei echten Tabs nachgemessen (RFC §10): Fälle 1–8 grün,
Fall 1 im Vor-v3-Build gegengeprüft und dort nachweislich rot. Fall 9
deckte auf, dass reviveGoneDoc() den Index-Hinweis nicht mitschrieb — ein
durch Tippen wiederbelebtes Dokument hing bis zum nächsten Flush allein an
seinen eigenen Schlüsseln und wäre bei einem Rückbau auf einen Build vor
v3 still verlorengegangen; behoben, Gegenprobe per Mutation gezogen.
Headless 666 Tests grün. Offen bleibt die Handarbeit: PWA neben Tab,
Firefox, Safari, ein Browser ohne Locks-API.

SPEC §9, D94, D89-Nachtrag, RFC (Status, §10, Revisionsgeschichte),
CHANGELOG und Plan-Knoten #ed.docs.windows nachgezogen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 20:07:20 +02:00
mhoennigandClaude Fable 5.1 112ada4e58 docs(rfc): Mehr-Fenster-Betrieb (PWA + Tab) — RFC 002, Plan-Knoten #ed.docs.windows, D94 (revidiert D89)
Der modale Zwei-Fenster-Dialog (D89) verbietet den Fall, der funktioniert
(dasselbe geteilte Dokument in App und Tab), und schützt nicht vor dem,
wovor er warnt: Der Voll-Flush löscht Dokumente und Stände des anderen
Fensters. Entschieden: je Dokument eigene Schlüssel, Tombstones, Sperre je
Dokument per Web Locks, Dialog mit drei Auswegen. Nichts gebaut.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-02 12:57:22 +02:00
mhoennigandClaude Fable 5 1f186eddce docs(rfc): MCP-Server nur im Backend, kein Node als Laufzeit — dritte Runde; Hausregel: neue Technologie braucht ausdrückliche Zustimmung
Nutzer-FYI: Node.js einzuführen ist eine Dimension schwerer als eine
Backend-Abhängigkeit und muss dem Entwickler deutlich gemacht werden —
als Regel in CLAUDE.md. Aus den nachgefragten Beweggründen folgt: kein
lokaler Prozess. Der MCP-Server lebt im Backend (Streamable HTTP,
Bearer-Token), führt die Frontend-Module per GraalJS aus, jedes Werkzeug
hat eine text- und eine document-Form; das Node-Paket ist verworfen,
seine Tool-Schicht lebt als frontend/src/inspect.js, guard.js, edit.js.
Backend-Abhängigkeiten GraalJS + Spring-AI-Starter zugestimmt; der
GraalJS-Spike steht vor allem anderen. RFC neu geschrieben (§12 hält die
drei Runden fest), Plan-Teilbaum #ai.mcp neu, D93-Nachtrag.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-02 10:04:11 +02:00
mhoennigandClaude Fable 5 1e9cc93cb9 docs(rfc): MCP-Server für KI-Agenten — RFC 001, Plan-Knoten #ai.mcp, D93 (festgelegt, nichts gebaut)
Ein Node-Paket, das die headless-Module des Frontends unverändert
importiert (kein zweiter Parser, D14), den Plan als Ressource und Tools
anbietet (Baum, Warnungen, günstigster Pfad, Knoten-Verben) und
Änderungen als Zeilen-Diff mit Basisversion schreibt (D76); Leitplanken:
keine beschädigte Notation, kein [^] von einem Agenten. Geteiltes Dokument
und Git zugleich: nach jedem Agenten-Zug committet der Server über
pull-doc --git-commit (D88). Entscheidungen der Multiple-Choice-Runde in
RFC §11 und D93.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-02 09:25:02 +02:00
mhoennigandClaude Fable 5 aa6ca85bdf fix(diagram): umgeklappter Knoten behält seine Position im Bild — Scrollstand zieht nach (D38-Nachtrag 5)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-28 20:21:03 +02:00
mhoennigandClaude Fable 5 0fe4c07851 feat(diagram): Knoten-Fenster öffnet nur noch auf Klick, nicht mehr bei Hover (D92, SPEC §6/§9)
Der einfache Klick toggelt das Fenster überall — wie der Tipp auf Touch
(D52); der Link eines Knotens ist damit auch am Zeiger der ↗-Knopf im
Fenster, Enter und Strg+Klick öffnen die URL weiterhin direkt. Tastatur-
fokus öffnet nur noch echten (:focus-visible), focusout schließt nicht in
das Fenster hinein, und die Fokus-Rückgabe nach dem Falten ruft das
Fenster ausdrücklich nie.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-28 16:43:01 +02:00
mhoennigandClaude Opus 5 a223e6af57 fix(taiga): Knoten-Fenster-Knöpfe in einer Zeile — tipwide, Öffnen-Knopf in der Aktions-Zeile (D91-Nachtrag 12)
Eine gemeinsame flex-wrap-Aktions-Zeile für Schreiben/Übernehmen/Öffnen in
der Ticket-Box; mit Taiga-Knöpfen wird das Fenster auf 31rem breiter
(gemessen an den deutschen Labels), umgebrochen wird nur bei echtem
Platzmangel. Der Öffnen-Knopf heißt nur noch «{ref} öffnen» — «in Taiga»
sagen die Nachbarknöpfe.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-28 13:01:25 +02:00
mhoennigandClaude Opus 5 1a33ebdac8 feat(taiga): Ticket verknüpfen — URL/Ref-Feld mit Betreff-Bestätigung (D91-Nachtrag 11)
Ein Knopf im Knoten-Fenster bindet ein bestehendes Taiga-Ticket an den
Knoten: Die eingefügte Ticket-URL trägt Slug, Typ und Nummer selbst; eine
nackte Nummer wird per Probe Story-dann-Task aufgelöst. Verknüpft wird erst
nach Anzeige des Betreffs; geschrieben werden Ref-Token und ggf.
&taiga.<slug> in einem Undo-Schritt, der geholte Stand füllt den
Ticket-Cache. Eine URL einer fremden Instanz wird benannt statt verknüpft.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-28 12:48:32 +02:00
mhoennigandClaude Opus 5 a1e4a3bbab feat(taiga): Bulk-Abfrage und Abweichungs-Marke — das Diagramm zeigt, wo Ticket und Plan auseinanderlaufen (D91-Nachtrag 10, SPEC §9)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-28 11:44:33 +02:00
mhoennigandClaude Opus 5 0ed30e9eae feat(taiga): Anlage-Knöpfe neu geschnitten — ein Story-Knopf mit Dialog, dialogfreie Task unter einem Story-Vorfahren (D91-Nachtrag 9)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-28 11:08:13 +02:00
mhoennigandClaude Fable 5 323e8fe0ba feat(taiga): Status zurückschreiben — zwei Knöpfe, niemand gewinnt von selbst (D91-Nachtrag 8, SPEC §9)
Weicht der Ticket-Status von der Statusbox ab, markiert das Knoten-Fenster
die Abweichung und bietet beide Richtungen ausdrücklich an.

- „nach Taiga schreiben": Spalte des Projekts suchen (Taiga schreibt nach Id,
  die Namen sind je Projekt frei) und mit der zuletzt GELESENEN `version`
  patchen — hat jemand dazwischen geändert, lehnt Taiga ab und der Text steht
  im Fenster, statt dass etwas überschrieben wird.
- „aus Taiga übernehmen": `setStatusBox()` schreibt die Box in die Textzeile,
  undo-fähig wie jede andere Änderung.
- Schreibbar sind nur die fünf abgebildeten Zustände; `[?]`, `[!]`, `[-]` und
  der neutrale Knoten lassen das Ticket unangetastet — mit Begründung im
  Fenster.
- Proxy: zwei Spaltenlisten (`/taiga/{userstory,task}-statuses?slug=`) und
  zwei Schreib-Endpunkte (`PATCH …/{ref}/status?slug=`); die Zielspalte wählt
  der Editor, das Backend parst die Notation nicht (D14).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 22:18:52 +02:00
mhoennigandClaude Fable 5 842e89795a feat(taiga): Ticket-Stand im Knoten-Fenster — gelesen, nie geschrieben (D91-Nachtrag 6, SPEC §9)
Wo eine Ref steht und ein `&taiga.<slug>` gilt, zeigt das Knoten-Fenster
Betreff, Status und Zuständigen des Tickets; Taigas Statusname steht neben
der Statusbox der Notation (`In progress → [~]`).

- Proxy: zwei benannte Lese-Endpunkte (`GET /taiga/userstories/{ref}` und
  `…/tasks/{ref}`, je `?slug=`) — das Präfix der Ref trägt den Typ, Taiga
  hat getrennte `by_ref`-Endpunkte. Erst `/projects/by_slug`, dann `by_ref`
  (eine Ref ist nur je Projekt eindeutig); der Slug wird kodiert angehängt.
- Die Abbildung Status → Statusbox liegt im Editor (`mapTaigaStatus`,
  headless): Statuscodes sind Notation, das Backend parst sie nicht (D14).
  Unbekannte Namen bleiben unabgebildet — Raten hieße, dem Knoten eine
  Aussage zu geben, die niemand gemacht hat.
- Geholt wird erst nach 400 ms Verweilen und je Ticket einmal je Sitzung
  (↻ holt neu); ohne Anmeldung gar nicht — der Knopf meldet erst an.
- Nichts wird geschrieben: kein Text, keine Statusbox (das bleibt
  `#trk.write`).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 20:41:21 +02:00
mhoennigandClaude Fable 5 a22c320909 feat(editor): Strg+Klick öffnet eine Ticket-Ref in Taiga (D91, SPEC §9)
Im Text (freistehendes #US-123/#T-1234, D67-Ausschlüsse) wie auf dem
Knoten; das Knoten-Fenster trägt an Refs einen Öffnen-Knopf — der Weg
auf Touch. Adresse aus taigaWeb (/info) + &taiga.slug-Vererbung; in
einem :#…-Token gewinnt weiter der Abhängigkeits-Sprung.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 17:24:20 +02:00
mhoennigandClaude Fable 5 83eb6ff77f fix(diagram): Ticket-Refs im Label brechen nicht mehr am Bindestrich um (SPEC §9)
Der Browser bricht eine zu breit geratene Zeile an jedem Bindestrich —
aus #US-123 wurde #US-/123 über zwei Zeilen. Eine tref-Spanne mit
white-space:nowrap hält das Token zusammen; labelLines() (Export) misst
ihre Textknoten unverändert mit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 17:14:27 +02:00
mhoennigandClaude Fable 5 d1de8758b1 feat(editor): Taiga-Story und -Tasks aus dem Knoten-Fenster anlegen (D91, #trk.create)
Zwei Aktionen im Knoten-Fenster, nur wo GET /info das Feature meldet
(Lebendprobe-Muster, je Basis einmal gecacht) und nur an Knoten ohne
Ticket-Referenz — die Ref an der Zeile ist der Idempotenz-Marker.
Login-Dialog (type=password, kein window.prompt; nur das Token landet
im Browser, 401 fragt neu), Projekt-Dialog vorbelegt aus dem geerbten
&taiga.<slug>, Häkchen-Dialog nach der D91-Vorbelegung; Refs und ggf.
das Projekt-Schlagwort gehen undo-fähig als Tokens an die Zeilen
(appendToken: vor %% und vor der Fortsetzungsmarke). Regeln headless in
taiga.js (15 neue Tests); Deploy zieht TAIGA_API_URL aus der .env als
WERKBAUM_TAIGA_API_URL in die Server-Umgebung nach (Nutzerwunsch).

E2E im Browser gegen Backend + Taiga-Stub gemessen: Buttons nur ohne
Ref, Vorbelegung Kundenprojekt aus geerbtem Tag, Refs #US-/#T- an den
richtigen Zeilen, Erledigtes uebersprungen, abweichende Projektwahl
schreibt &taiga.mi-intern zurueck, Undo/Redo je Schreibzug, falsches
Passwort bleibt als Taiga-Fehlertext im Dialog.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 16:51:10 +02:00
mhoennigandClaude Fable 5 fd0e730656 feat(backend): Taiga-Proxy — vier schmale Endpunkte, Ziel-URL aus der Server-Konfiguration (D91, #trk.create.proxy)
API First: /taiga/auth, /taiga/projects, /taiga/userstories, /taiga/tasks
in der OpenAPI-Spec; TaigaClient/TaigaProperties in
de.werkbaum.integration.taiga. Die API-URL kommt aus
WERKBAUM_TAIGA_API_URL (nie Request-Parameter — SSRF), das Token je
Aufruf im Header X-Taiga-Token (Authorization muessen OpenAPI-Werkzeuge
als Header-Parameter ignorieren) und geht als Bearer hinaus; der Server
speichert nichts und loggt keine Request-Bodies. Taiga-4xx werden samt
_error_message durchgereicht, 5xx/Netz sind 502, unkonfiguriert 503 —
und GET /info meldet das Feature (taiga). Tests gegen aufgezeichnete
Antwortformen auf einem JDK-HttpServer-Stub (statt WireMock: keine neue
Test-Abhaengigkeit, dieselbe Zusicherung); Gegenprobe: ohne den
type-Durchreich faellt genau der benannte Test. check gruen, 93 %
Coverage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 16:33:35 +02:00
mhoennigandClaude Fable 5 5a18505571 feat(notation): Schlagworte &tag gebaut — taiga.<slug> benennt das Projekt je Teilbaum, vererbt (SPEC §1, D91)
SPEC zuerst: §1 Schritt 5b samt Block und Referenz-Regex, §11 auf
'umgesetzt' umgestellt; llms.md nachgezogen. Parser extrahiert
alleinstehende &-Token als node.marks (Zitier-Konvention gilt),
taigaSlugs() in model.js vererbt das taiga.*-Schlagwort wie die
@-Tags beim Engpass. Sichtbar im Tooltip und aria-label (a11yMarks,
9 Sprachen). Plan-Labels mit &-Erwähnungen eingeklammert; 12 neue
Tests, Gegenprobe: ohne Alleinstehend-Anker fallen genau die zwei
Zitier-Tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 16:20:03 +02:00
mhoennigandClaude Fable 5 c712e81970 docs: Mehrprojekt-Pläne — &taiga.slug erbt je Teilbaum, erster &tag-Konsument (D91-Nachtrag 3, SPEC §11)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 14:48:03 +02:00
mhoennigandClaude Fable 5 4c98ec6603 docs: Ticket-Ref zusätzlich zur Knoten-ID, Präfixe US-/T- festgelegt (D91-Nachtrag 2, SPEC §11)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 14:37:08 +02:00
mhoennigandClaude Fable 5 6bbc91e849 docs: Ticket-Anlage aus Knoten festgelegt — Proxy, zwei Aktionen, Häkchen-Dialog (D91, #trk.create)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 14:16:41 +02:00
mhoennigandClaude Fable 5 e3742feffb feat(diagram): Unassigned-Pille zeigt das Sprach-Kürzel — de N.N., en TBD; Langform im Tooltip (D87-Nachtrag)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 13:52:39 +02:00
mhoennigandClaude Fable 5 e684ac73d3 feat(tools): pull-doc --open öffnet die Datei danach in IntelliJ IDEA (D88-Nachtrag 2)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 13:36:25 +02:00
mhoennigandClaude Fable 5 78e2eeb616 feat(live): Sitzung heilt sich selbst; Verbindungszustand warnfarben am Namens-Chip (D89-Nachtrag)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 13:23:34 +02:00
mhoennigandClaude Fable 5 f45ca44d3c feat(kopf): Dokumentart grau hinter dem Namens-Chip — Mitgeliefert/Lokal/Geteilt samt Host (D90)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 13:03:53 +02:00
mhoennigandClaude Fable 5 408e23f25b feat(live): vier Netze gegen stillen Verlust — Zwei-Fenster-Modal, Wachhund, Rettungs-Sicherungen, lokale Stände für Server-Dokumente (D89)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 12:51:11 +02:00
mhoennigandClaude Fable 5 42d37daf63 feat(tools): pull-doc committet nur noch mit --git-commit (D88-Nachtrag)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 12:00:53 +02:00
mhoennigandClaude Fable 5 887b5c75ee feat(tools): pull-doc holt ein Server-Dokument in ein git-Worktree und committet es datiert (D88)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 11:56:12 +02:00
mhoennigandClaude Fable 5 22769cf3b6 docs: Nutzen je Knoten festgelegt — (M/9) im Größen-Token, lohnendster Pfad (SPEC §11)
Geplant, nicht gebaut: Ziffer 0-9 im Größen-Token (0 = Vorbedingung),
reine Autoren-Aussage ohne Aggregation; der Pfad-Knopf wird ein
Durchschalter aus -> günstigster -> lohnendster. Plan-Knoten
#not.benefit (XOR-Gruppe aufgelöst) und #ed.path.worth.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 11:03:36 +02:00
mhoennigandClaude Fable 5 deec39e82a feat(diagram): Personen-Leiste mit Personen-Linse und Belastungsanzeige (D87)
Je @Person eine Pille mit Anteil an der offenen Pfad-Arbeit (D71-Maß),
dazu ein Eintrag für Unzugewiesenes — die Anteile summieren auf 100 %.
Ein Tipp filtert das Diagramm auf die Knoten der Person: alles andere
faltet, ihre Pakete stehen als ▸ n, die Pillen färben petrol. Die Linse
ist rein Ansicht und Sitzungssache — in den Text wird nichts geschrieben,
in geteilten Dokumenten ginge der persönliche Filter sonst an alle.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 10:38:53 +02:00
mhoennigandClaude Fable 5 1e1a00f794 docs: Changelog-Zeile zur Text-Falten-Idee
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 10:14:27 +02:00
mhoennigandClaude Fable 5 a59bbaa16a fix(diagram): Wurzelknoten-Falt-Chip wie überall, helle Marken nur auf dunkler Wurzel (D64-Nachtrag 2)
Die helle Umkehrung des Chips war für die dunkle Tinte-Wurzel gebaut —
seit D39 ist die Wurzel mit Status aber pastellfarben, und Weiß darauf
unsichtbar. Der Chip ist jetzt überall derselbe; desc-mark und nid
bleiben nur auf der statuslosen (dunklen) Wurzel weiß.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 10:05:19 +02:00
mhoennigandClaude Fable 5 9d1d580166 fix(diagram): Cursor-Zeile lässt zurückgetretene Knoten blass (D25-Nachtrag 4)
Die Ausnahme von der Pfad-Inversion stellte den ganzen Knoten auf volle
Stärke, weil opacity/filter den Ring mitträfen. Jetzt bleibt der Knoten
deckend und die Blässe wird nachgebildet: Papier-Wasch über der Füllung,
gefadete Text-/Rahmenfarbe, Kinder einzeln gedimmt — der Ring steht voll.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 09:54:55 +02:00
mhoennigandClaude Fable 5 53b48bcd42 feat(paket c): Frühere Stände eines geteilten Dokuments kommen vom Server (D86)
Der Verlaufs-Knopf zeigt bei Geteilten die Meilenstein-Historie des
Servers (GET /history, jetzt samt clientId/displayName); Laden ist ein
Server-Rollback (POST /restore, ROLLED_BACK — neue Version für alle,
nichts geht verloren, mit Rückfrage). Die Kamera legt einen
Server-Meilenstein an (pushLive(true), leeres Diff erlaubt); lokale
Momentaufnahmen sammelt snapshotNow() für Server-Dokumente nicht mehr —
sie enthielten fremde Arbeit und überschrieben sie beim Laden als
eigenes Diff. Dazu der Anzeigename: einmal gefragt, im Browser gemerkt,
füllt das 'geändert von' der Historie (Behauptung, kein Nachweis).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 08:21:17 +02:00
mhoennigandClaude Fable 5 fbe9b1fd22 feat(paket b): Umbenennen erreicht alle — PATCH /title und RENAMED im Feed (D85)
Backend: PATCH /documents/{id}/title mit expectedVersion (409 bei
veralteter Version, 400 bei leerem/zu langem Titel), neuer ChangeType
RENAMED (strukturell, immer Meilenstein), der Feed stellt den neuen Titel
im Klartext zu (ChangeEvent.title). Unter derselben Stripe-Sperre wie die
Inhalts-Patches; Owner-Vormerkung in der API-Beschreibung. Vier neue
Cucumber-Szenarien, zwei Unit-Tests.

Frontend: Der Zeilen-Stift eines Server-Dokuments benennt über den Server
um (optimistisch, 409-Retry, Rücknahme + Warnung bei Fehlschlag); fremde
Umbenennungen kommen als RENAMED über den Feed in Chip und Menü.
URL-Dokumente verlieren den Stift — ihr Name ist die URL.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 08:13:25 +02:00
mhoennigandClaude Fable 5 c438a88344 fix(paket a): URL-Reload ohne Rückfrage, Letztes-Dokument-Hinweis, Fremd-Tab-Warnung (D84)
1. Neu laden fragt bei URL-Dokumenten nicht mehr (F5 verwirft ohnehin
   still, D23); bei Datei-Dokumenten bleibt die Rückfrage. Dabei gefunden
   und behoben: Der Knopf erschien auch bei Server-Dokumenten und hätte
   die JSON-Antwort der API als Text an alle gepusht.
2. Die Rückfrage beim letzten Dokument sagt, dass danach wieder das
   Beispiel dasteht (docDeleteLastConfirm, 9 Sprachen).
3. Ein zweiter Tab, der in dieselbe Ablage schreibt, wird per
   storage-Ereignis erkannt und gemeldet (tabConflict, isDocKey in
   docstore.js) — kein Sync, aber kein stiller Verlust mehr.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 08:02:15 +02:00
mhoennigandClaude Fable 5 83dc329b43 docs(plan): Owner-Passwort für geteilte Pläne als geplant eingetragen (#col.live.owner)
Beim Anlegen einmalig vom Server geliefert, Browser hält eine Kopie, keine
Recovery auf fremdem Browser; Verwaltung bindet künftig daran, ein Admin
mit Master-Passwort kann reclaimen. Nur Plan-Eintrag, noch keine Umsetzung.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 07:44:13 +02:00
mhoennigandClaude Fable 5 5c8fbcde01 feat(menü): Geteilte werden verlassen, nicht gelöscht (D81-Nachtrag 5)
Eigene Aktion für die Geteilt-Gruppe (Server- und URL-Dokumente): Wort
(Verlassen), Icon (Tür mit Pfeil statt Papierkorb), Rückfrage (nur der
eigene Listeneintrag geht, Server bleibt) und normales statt rotem Hover.
Der Link wandert beim Verlassen in die Zwischenablage — der Listeneintrag
ist zugleich das Lesezeichen. Verhalten wie lokales Löschen
(removeDocLocally, gemeinsamer Kern); i18n in neun Sprachen.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 07:28:43 +02:00
mhoennigandClaude Fable 5 a78147e459 feat(menü): Gruppen heißen Mitgeliefert · Lokal · Geteilt (D81-Nachtrag 4)
Nutzer-Wortwahl statt „Eigene"/„Quellen": Lokale leben nur in diesem
Browser, Geteilte (Server- und URL-Dokumente) erreicht man über eine
weitergegebene Adresse. In allen neun Sprachen.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 07:06:00 +02:00
mhoennigandClaude Fable 5 3072f3a9c0 feat(speicher): Dokument-Ablage aufgeteilt — Index + ein Schlüssel je Text (D83)
werkbaum-docs ist nur noch der Index [{id,name,source?}]; der Text jedes
Dokuments liegt unter werkbaum-doc:<id>. Damit trifft eine volle Quota nur
das eine zu große Dokument statt jeden Flush, und ein kaputter Schlüssel
kostet ein Dokument statt aller (vorher: JSON.parse-Fehler -> Rückfall auf
das Beispiel, alle Dokumente unsichtbar). Der Tastendruck schreibt direkt
den Text-Schlüssel; der Voll-Flush vergleicht vor jedem Schreiben und räumt
verwaiste Schlüssel ab. Altformat migriert beim ersten Laden; die
Spiegel-Regel aus D82 gilt nur noch dieser Migration. Schema headless in
docstore.js (+10 Tests).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 06:58:10 +02:00
mhoennigandClaude Fable 5 4f34454075 perf+fix(speicher): Tastendruck schreibt nur den Spiegel; Quota-Fehler werden gemeldet (D82)
saveSrc() serialisierte bei jedem Tastendruck ALLE Dokumente in
werkbaum-docs. Jetzt schreibt der Tastendruck nur noch den Spiegel
werkbaum-src (ein Text); das volle Array schreiben die Flush-Punkte
(Wechseln/Anlegen/Löschen/Umbenennen, pagehide, verborgener Tab). Beim
Laden gewinnt der Spiegel für das aktive Dokument — zwingend VOR dem
Nachziehen mitgelieferter Fassungen, sonst dreht er sie zurück.

Und: persistDocs schluckte Speicherfehler still — bei voller Quota lief
der Editor scheinbar normal weiter, der Verlust fiel erst beim Neuladen
auf. Jetzt meldet die persistente Warnung storeFailed (9 Sprachen),
zuoberst, bis ein Schreiben wieder gelingt.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 06:43:10 +02:00
mhoennigandClaude Fable 5 ca4c6f98d8 fix(menü): mitgelieferte Dokumente sind nicht mehr umbenennbar (D81-Nachtrag 3)
Ihr Name ist Auslieferungsstand: Wiederherstellen stellt ihn mit her, der
Neu-laden-Vergleich prüft ihn, und ein umbenanntes, aber unverändertes
Beispiel bekäme weiter still neue Fassungen nachgezogen (das Nachziehen
hängt an id + Text-Fingerabdruck, nicht am Namen). Kein Stift an
mitgelieferten Zeilen; renameDoc() prüft es selbst. Löschen bleibt.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 05:51:41 +02:00
mhoennigandClaude Fable 5 ed81a2fe41 fix(menü): Wiederherstellen nur noch über den Neu-laden-Knopf der Titelzeile (D81-Nachtrag 2)
Das Zeilen-Symbol im Dokumenten-Menü konnte ein UNGEÖFFNETES mitgeliefertes
Dokument zurücksetzen — ohne zu sehen, was man verwirft (Nutzer-Einwand).
Umbenennen und Löschen bleiben je Zeile; restoreDoc() wirkt nur noch auf das
geöffnete Dokument und prüft das selbst.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 05:33:34 +02:00
mhoennigandClaude Fable 5 67d0ef421b fix(teilen): Basis-Adresse per Lebendprobe prüfen, sonst fragen (D81-Nachtrag)
Auf einer Instanz ohne eigenes Backend (GitHub Pages) endete Teilen mit
HTTP 405: Die Vorgabe "eigene Herkunft" (D76-Nachtrag 8) stimmt nur auf der
produktiven Installation. serverBaseOrAsk() prüft die Vorgabe jetzt mit
GET /api/v1/info (D77), bevor gePOSTet wird, und fragt sonst nach der
Server-Adresse; gemerkt wird nur eine Adresse, die die Probe besteht.
Von Pages aus trägt man werkbaum.javagil.de ein — CORS erlaubt es.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 05:23:19 +02:00
mhoennigandClaude Fable 5 4be6ecb984 feat: Dokumenten-Menü neu — Brotkrume im App-Kopf, Stand-Knöpfe im Editor-Kopf (D81)
Der Dokument-Wähler steht jetzt als gerahmter Chip "Werkbaum › Name" im
App-Kopf und ist damit auch auf dem Telefon aus beiden Bereichen erreichbar;
sein Name übernimmt dort die Untertitel-Zeile. Das Menü gruppiert nach
Dokumentart (docKind, headless getestet), trägt Umbenennen/Löschen/
Wiederherstellen als Symbole je Zeile und scrollt als Ganzes, statt auf
kleinen Bildschirmen abgeschnitten zu werden. Die Editor-Titelzeile heißt
wieder "Text-Editor" und trägt die Stand-Funktionen des aktiven Dokuments:
Speichern (Strg+S), Stand sichern, frühere Stände, Neu laden (Original/URL/
Datei) und den neuen kurzen Teilen-Knopf (vorher "Auf den Server legen" im
Menü). subtitleShort ist ersatzlos ausgebaut.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 22:21:11 +02:00
mhoennigandClaude Opus 5 fdca934cf0 feat: Adresszeile folgt dem Dokument, Live-Sitzung ebenso (D80)
Wer bei offenem `?live=` umschaltet, behielt die alte Adresse — optisch
falsch, und ein Neuladen holte das falsche Dokument zurück. Der Parameter
gehört jetzt zum aktiven Dokument, für `?live=` wie für `?sourceUrl=`;
`?etherpad=` wird nur noch weggeräumt. Fremde Parameter (`?server=`)
bleiben wörtlich stehen, damit die URL lesbar bleibt.

Dabei gefunden: Die Live-Sitzung lief weiter, während ein anderes Dokument
vorn stand — `setLiveText()` schrieb fremde Änderungen in dessen Text. Die
Sitzung gehört jetzt dem sichtbaren Dokument: Umschalten beendet sie,
Umschalten auf ein Server-Dokument nimmt sie auf. Was noch im Debounce
steckt, geht vorher raus, und `pushLive()` hält seine Sitzung fest statt
anzunehmen, dass sich über ein `await` hinweg nichts ändert.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 21:19:29 +02:00