Files
mhoennigandClaude Fable 5.1 2e408d956c
Deploy to GitHub Pages / build (push) Canceled after 0s
Deploy to GitHub Pages / deploy (push) Canceled after 0s
feat(tools): mirror-docs — Liste geteilter Dokumente per Timer nach git spiegeln (D88-Nachtrag 3)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 09:52:02 +02:00

14 KiB
Raw Permalink Blame History

Werkbaum-Logo

Werkbaum

English · Deutsch

▶ Live ausprobieren: https://werkbaum.javagil.de (stabil) · https://mhoennig.github.io/werkbaum/ (jeweils neuester Build 🚧)

Eine textuelle, Markdown-artige Notation für Projektstrukturpläne (Work Breakdown Structure) mit Und/Oder-Zerlegung — und ein Live-Editor, der sie als Diagramm rendert.

[~] Werkbaum (XL) https://wiki.example.de/relaunch
  - [~] Dokumentenspeicher
    | [x] Textdatei mit Copy+Paste im Frontend (S)
        - [x] Parser
        - [x] Texteingabefeld im Frontend
    | [ ] Backend
  - [~] Darstellung/Rendern (XL)
    - [/] H (S) @anna
    - [ ] CMS-Anbindung (M)
      | [ ] WordPress
      | [?] Headless CMS

- = Pflicht-Teilpaket (all of, im Diagramm nebeneinander) · | = Alternative (any of, untereinander) · […] = Status · (M) = T-Shirt-Aufwand · @name = Zuständigkeit · %% = Kommentar.

Nutzung

Werkbaum-Editor: Live-Diagramm oben, Textnotation darunter, mit Statusfarben, T-Shirt-Größen, Tags und Export-Schaltflächen

Den gehosteten Editor öffnen — links Text bearbeiten, rechts entsteht das Diagramm live. Toggles: transponierte (schmale) Darstellung, verworfene Elemente einblenden.

Zwischen Diagramm und Text springen

Diagramm und Editor sind in beide Richtungen verknüpft:

  • Alt+Klick auf einen Knoten (Tastatur: Alt+Enter, Touch: langer Druck) markiert seine Zeile im Texteditor — ein zugeklapptes Editor-Panel öffnet sich dabei zuerst.
  • Cursor im Text bewegen hebt den zugehörigen Knoten im Diagramm hervor.

Der einfache Klick behält seine bisherige Bedeutung: Ein Knoten mit URL öffnet sie weiterhin.

Diagramm aus einer URL laden

Der Editor kann seinen Notationstext über den Query-Parameter sourceUrl aus einer externen Textdatei beziehen — praktisch zum Teilen eines Plans oder wenn die Quelle in Git oder einem Wiki gepflegt wird:

https://werkbaum.javagil.de/?sourceUrl=https://git.javagil.de/mi/werkbaum/raw/branch/main/docs/examples/example-plan-0.werkbaum

Fertige Beispiele in docs/examples/nacheinander öffnen: Jedes wird ein eigenes Dokument, danach lässt sich in der Editor-Titelzeile zwischen allen umschalten:

Beispiel Zeigt
0 · Online-Shop-Relaunch ein Softwareprojekt mit allen acht Status
1 · Neue Küche ein Plan ohne Software, viele Alternativen — gut für den Günstigster-Pfad-Schalter
2 · Community-Konferenz ein breiter Plan mit vielen Beteiligten; horizontal vs. kompakt vergleichen
3 · Drei Arbeitsstränge mehrere Wurzeln = mehrere Bäume nebeneinander
Werkbaum selbst Bestand und mögliche Weiterentwicklung

Der geladene Text wird als eigenes Dokument geführt, dessen Name die URL ist — eigene Dokumente bleiben unberührt, und derselbe Link aktualisiert dieses eine Dokument, statt Kopien anzuhäufen. Die URL ist die Quelle der Wahrheit: Sie wird bei jedem Laden neu geholt, lokale Änderungen daran überleben ein Neuladen also nicht.

Notationsdateien tragen die Endung .werkbaum (UTF-8; siehe docs/SPEC.md §12 und D24) — Konvention, kein Vertrag: sourceUrl liest jede per http(s) erreichbare Textdatei, unabhängig von Endung und Content-Type.

Einschränkung — CORS: Der Browser lädt fremde Hosts nur, wenn sie Access-Control-Allow-Origin senden. raw.githubusercontent.com, GitLab-Raw-Links und git.javagil.de tun das (D96); ein beliebiger Webserver oft nicht. Scheitert das Laden, bleibt der bisherige Stand stehen und eine Warnung nennt die Ursache. Zugelassen sind nur http/https.

Zusammen an einem Plan arbeiten (?live=)

Liegt der Plan auf einem Werkbaum-Backend, bearbeiten ihn alle im Editor selbst und sehen die Änderungen der anderen, ohne neu zu laden:

https://werkbaum.javagil.de/?live=https://werkbaum.javagil.de/api/v1/documents/<uuid>

Angelegt wird so ein Dokument über den Teilen-Knopf in der Titelzeile des Text-Editors: Er lädt den aktiven Plan hoch, schaltet dorthin um und schreibt den Link in die Adresszeile und in die Zwischenablage. Diesen Link weitergeben — die Adresse ist die Einladung, und wer sie kennt, kommt hinein.

Das Textfeld bleibt beschreibbar. Nach 0,6 s Ruhe schickt der Editor die Änderung als Zeilen-Diff; ein offener Abruf hält die Gegenrichtung bereit und spielt fremde Änderungen ein. Die Schreibmarke wandert mit — fügt jemand oberhalb Zeilen ein, bleibt sie an ihrer Stelle im Text.

Der Name ist der Titel des Dokuments (alle sehen denselben), die vollständige Adresse steht im Tooltip.

Die Adresszeile folgt dem Dokument, das vorn ist. Umschalten auf einen lokalen Plan räumt ?live= weg, Umschalten auf ein anderes Server-Dokument trägt dessen Adresse ein — ein Neuladen bringt also zurück, was man vor sich hatte. Wer ein Server-Dokument im Menü auswählt, arbeitet darin auch wieder gemeinsam.

Überschneiden sich zwei Änderungen wirklich — dieselben Zeilen —, fragt ein Band oben, wessen Fassung gelten soll: Fremde übernehmen oder Eigene durchsetzen. Alles andere führt der Server selbst zusammen, ohne zu fragen. Verloren geht nichts: Der verworfene Stand bleibt in den früheren Ständen, jede Version in der Historie des Servers.

Ein gemeinsamer Zeigefinger: !!! auf einer Zeile hebt diesen Knoten hervor und holt ihn ins Bild — bei allen, die das Dokument ansehen. Das kann ein Cursor nicht. Erkannt nur als alleinstehendes Token, Achtung!!! bleibt also ein gewöhnliches Label. Die Marke bleibt stehen, bis jemand sie löscht.

Eine Git-Historie für einen geteilten Plan: tools/pull-doc <dokument-url> <datei> holt das Dokument (auch ein ?live=-Link funktioniert) und schreibt es in die Datei; mit --git-commit wird es zusätzlich in das git-Worktree der Datei committet — Datum, Titel und Version in der Nachricht, kein Commit ohne Änderung. Per Cron aufgerufen archiviert sich der Plan von selbst; --open öffnet die Datei danach in IntelliJ IDEA. Siehe docs/DECISIONS.md D88.

Mehrere Dokumente, ohne Zutun: tools/mirror-docs [--push] <worktree> <liste> schickt jede Zeile der Liste (<uuid-oder-url> <pfad>) durch pull-doc --git-commit und pusht einmal am Ende; eine UUID braucht die Backend-Basis in --api oder WERKBAUM_API. Als systemd-Timer auf dem Backend-Host spiegelt es die geteilten Pläne alle 15 Minuten in einen Branch — siehe D88, Nachtrag 3.

Das Backend einrichten: siehe backend/README.md und docs/DECISIONS.md D76.

Dafür lieh sich Werkbaum früher ein Etherpad (?etherpad=). Das ist ausgebaut — das Backend kann dasselbe besser und im Editor selbst. Ein alter ?etherpad=-Link zeigt heute einen Hinweis hierher, statt still nichts zu tun; siehe docs/DECISIONS.md D78.

Wo der Code liegt

Das Repository liegt auf https://git.javagil.de/mi/werkbaum (Gitea) — das ist origin, und dort gehören die Branches hin:

git clone mih09-git@git.javagil.de:mi/werkbaum.git      # oder https://git.javagil.de/mi/werkbaum.git

GitHub bleibt ein Klon. main wird dorthin von Hand gespiegelt (scripts/push-github.sh), denn die GitHub-Pages-Instanz hängt daran — der 🚧 latest build ganz oben. Die Beispiel-Links waren ein zweiter Grund und sind es nicht mehr: git.javagil.de liefert raw-Dateien inzwischen mit Access-Control-Allow-Origin, sie zeigen deshalb auf Gitea (docs/DECISIONS.md D96, revidiert D95).

Lokal ausführen

Die Editor-Quelle liegt jetzt als ES-Module unter frontend/src/, gebündelt mit Vite (siehe docs/DECISIONS.md D19). Da Browser ES-Modul-Importe über file:// blocken, funktioniert das direkte Öffnen von frontend/index.html nicht mehr — stattdessen:

cd frontend
npm install          # einmalig
npm run dev          # Dev-Server unter http://localhost:8137
npm test             # Vitest-Unit-Tests
npm run build        # -> frontend/dist/index.html (eine self-contained Datei)

Die gebaute dist/index.html inlint JS, CSS und Favicon — diese Datei öffnet also standalone per file:// und ist zugleich das, was deployt wird.

Build-Hinweis & eigene Produktions-Installation

Nicht-produktive Builds tragen hinter dem Titel einen kleinen Hinweis (Symbol + Tooltip), damit klar ist, dass es nicht die stabile Instanz ist:

  • Dev-Server (npm run dev) → 🔧 „Vorschau lokaler Entwicklungsstand"
  • Default-Build (npm run build, u. a. der GitHub-Pages-Deploy) → 🚧 „Aktueller Entwicklungsstand (latest build) kann noch Fehler enthalten"

Für die eigene produktive Installation wird der Hinweis abgeschaltet:

cd frontend
npm ci                # oder: npm install
npm run build:prod    # -> frontend/dist/index.html OHNE Hinweis

build:prod läuft im Vite-Modus prod; frontend/.env.prod setzt dabei VITE_BUILD_BADGE=none, wodurch der Badge-Code komplett wegoptimiert wird (er steht dann nicht einmal mehr im Quelltext der Ausgabe). Die entstandene dist/index.html legst du standalone auf deinen Webspace/Server (file://- tauglich). Steuerung im Detail: app.js (mountBuildBadge), docs/DECISIONS.md D16.

Zwei Dinge, die sonst nur der Pages-Workflow erledigt und die du im Eigenbetrieb selbst geradeziehst: der Footer-Link MIT-License zeigt relativ auf ../LICENSE (lege die Datei eine Ebene über index.html ab oder passe den Link an), und die Versionsnummer bleibt der Quelltext-Platzhalter 1.0 (der Workflow ersetzt ihn sonst aus VERSION + Commit-Zahl).

Bequemer: scripts/deploy-prod.sh. Das Skript macht genau den obigen Prod-Build und die beiden Nacharbeiten (LICENSE danebenlegen + Link geradeziehen, Footer-Version + Commit-Link wie beim Pages-Workflow) und spiegelt das Ergebnis per rsync/SSH auf einen Server:

scripts/deploy-prod.sh mih00@mih00.hostsharing.net:~/doms/werkbaum.javagil.de/htdocs-ssl

Das Ziel ist entweder dieses Argument oder — ohne Argument — die Variable DEPLOY_TARGET aus der git-ignorierten Datei .env (Vorlage: .env.example, einmal kopieren und den Pfad eintragen). Ein Argument hat Vorrang.

Ohne -y zeigt es zuerst eine --dry-run-Vorschau und fragt nach. rsync --delete sorgt dafür, dass am Ziel nichts Altes stehen bleibt — das Zielverzeichnis gilt also als exklusiv für Werkbaum (eine laufende Let's-Encrypt- Challenge unter .well-known/ wird per --filter=protect ausgenommen, web- taugliche Rechte 755/644 werden erzwungen). (Hostsharing: eine direkt aufgeschaltete Domain liefert aus …/htdocs-ssl/; als Subdomain unter einer anderen Domain läge das Web-Verzeichnis in …/subs-ssl/<name>/.)

Projektdokumente

  • frontend/ — Editor · backend/ — Kotlin/Spring (Gerüst folgt, siehe backend/README.md)
  • docs/SPEC.md — verbindliche Sprachdefinition
  • docs/DECISIONS.md — Design-Entscheidungen mit Begründung
  • docs/ROADMAP.md — Mermaid-Plugin, Taiga-Integration, Tenzu
  • docs/TASKS.md — offene Aufgaben (Checkboxen)
  • docs/rfc/ — Vorschläge, die mehrere Teile des Repos berühren und vor dem Bauen abgewogen werden (001: ein MCP-Server für KI-Agenten; 002: installierte App und Browser-Tab nebeneinander)
  • docs/brand/BRAND.md — Logo, Wortbild, Anwendungsregeln
  • docs/design/ — Design-Herleitung der Marke
  • CLAUDE.md — Projektkontext für Claude Code

Deployment

Der Editor wird per GitHub Actions als statische Seite auf GitHub Pages veröffentlicht (Workflow: .github/workflows/pages.yml). Ausgelöst bei jedem Push auf main des Klons — also nachdem scripts/push-github.sh gespiegelt hat (D95) — sowie manuell (workflow_dispatch).

Der Workflow richtet Node ein, führt npm ci, npm test (Vitest) und npm run build (Vite) aus und veröffentlicht die gebündelte frontend/dist/index.html als index.html an der Wurzel-URL, dazu LICENSE für den MIT-Link im Footer. Das Favicon ist im Build bereits inline, es muss also nichts weiter kopiert werden; nur der Laufzeit-Link ../LICENSE wird auf der Kopie geradegezogen. Ein fehlschlagender Test blockiert das Deployment. backend/ und die übrigen docs/ werden nicht veröffentlicht.

Beim Zusammenstellen setzt der Workflow zudem die Versionsnummer im Footer: Major.Minor stammt aus der Datei VERSION (per bewusstem „Bump-Commit" gepflegt), die Micro-Stelle aus der Zahl der Commits seit diesem letzten Bump — sie steigt also mit jedem Commit und beginnt nach einem Bump wieder bei 0 (Werkbaum 1.0.0, 1.0.1, … dann VERSION auf 1.1 bumpen → 1.1.0). Es wird nichts ins Repo zurückgeschrieben. Im Footer verlinkt der Name Werkbaum die Repo-Startseite auf Gitea, die Versionsnummer genau den zugehörigen Commit dort (…/commit/<sha>) — der Klon trägt dieselben SHAs. Lokal geöffnet zeigt der Editor den Platzhalter aus dem Quelltext (Werkbaum 1.0).

Einmalige Einrichtung: In den Repo-Settings unter Pages als Source „GitHub Actions" wählen. Das Repo muss dafür öffentlich sein (GitHub Pages via Actions ist für private Repos nur mit kostenpflichtigem Plan verfügbar).

Lizenz

MIT — siehe LICENSE. © 2026 Michael Hönnig. Die mitgelieferten IBM-Plex-Schriften stehen unter der SIL Open Font License 1.1 (siehe LICENSE und frontend/src/fonts/OFL.txt).