diff --git a/README.de.md b/README.de.md index 0866248..5dec317 100644 --- a/README.de.md +++ b/README.de.md @@ -128,10 +128,11 @@ Cursor nicht. Erkannt nur als alleinstehendes Token, `Achtung!!!` bleibt also ei gewöhnliches Label. Die Marke bleibt stehen, bis jemand sie löscht. **Eine Git-Historie für einen geteilten Plan:** `tools/pull-doc -` holt das Dokument (auch ein `?live=`-Link funktioniert) und committet -es in das git-Worktree der Datei — Datum, Titel und Version in der Nachricht, -kein Commit ohne Änderung. Per Cron aufgerufen archiviert sich der Plan von -selbst; siehe `docs/DECISIONS.md` D88. +` 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; siehe +`docs/DECISIONS.md` D88. Das Backend einrichten: siehe [backend/README.md](backend/README.md) und `docs/DECISIONS.md` D76. diff --git a/README.md b/README.md index 9d4fca1..09f415b 100644 --- a/README.md +++ b/README.md @@ -122,10 +122,10 @@ something a cursor cannot do. Recognised only as a standalone token, so deletes it. **A git history for a shared plan:** `tools/pull-doc ` -fetches the document (a `?live=` link works too) and commits it into the file's -git worktree — date, title and version in the message, and no commit when -nothing changed. Run it from cron and the plan archives itself; see -`docs/DECISIONS.md` D88. +fetches the document (a `?live=` link works too) and writes it to the file; +with `--git-commit` it also commits it into the file's git worktree — date, +title and version in the message, and no commit when nothing changed. Run it +from cron and the plan archives itself; see `docs/DECISIONS.md` D88. Setting up the backend: see [backend/README.md](backend/README.md) and `docs/DECISIONS.md` D76. diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 70a61b7..c08dc92 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -19,7 +19,7 @@ reverse. ## 2026-08-27 -- A `pull-doc` script fetches a shared document from the backend and commits it into a git worktree — dated commits, none when nothing changed, so a cron gives the plan a git history +- A `pull-doc` script fetches a shared document from the backend into a file — with `--git-commit` it also commits it, dated, and only when something changed, so a cron gives the plan a git history - A benefit rating per node recorded as planned: a 0-9 digit inside the size token (`M/9`), and a third path mode that picks alternatives by benefit over cost — spelled out in SPEC §11 before it is built - A people bar below the diagram shows each `@person` with their share of the open work on the cheapest path — plus an entry for what is assigned to nobody - Tapping a person filters the diagram to their nodes: everything else folds, their packages stand collapsed as `▸ n`, their pills turn teal — a view-only lens that never writes into the text diff --git a/docs/DECISIONS.md b/docs/DECISIONS.md index a785dad..2c5ffe0 100644 --- a/docs/DECISIONS.md +++ b/docs/DECISIONS.md @@ -7575,3 +7575,25 @@ geänderter Inhalt ergibt den zweiten Commit; der prozent-kodierte enden mit klarer Meldung und ohne Rückstände. Der echte Backend-Abruf ist derselbe GET wie im Mock — dieselbe Werkzeuggrenze wie überall: Der native Serverbetrieb ist über D76/D77 abgedeckt. + +**Nachtrag — committet wird nur mit `--git-commit`.** Nutzer-Einwand direkt +nach dem Bauen: „pull ist nur die eine Hälfte, somit ist der Name etwas +fehlleitend" — der wichtigere Teil sei gerade das Commit. Statt umzubenennen +wird der Name **wahr gemacht**: Ohne Schalter tut `pull-doc`, was es sagt +(holen und schreiben), das Commit ist ein ausdrücklicher Zusatz +(`--git-commit`, als erstes Argument). Damit fällt auch die +Worktree-Pflicht auf den Commit-Fall zurück — wer nur holen will, darf in +jedes Verzeichnis schreiben. + +**Dabei eine Lücke gefunden, die es vorher nicht geben konnte:** Läuft erst +der flag-lose Abruf (schreibt die Datei) und dann `--git-commit` bei +unverändertem Server-Stand, war „Datei gleich Server" wahr — und die +liegende, nie committete Änderung bliebe **für immer** uncommittet. Im +Commit-Modus heißt „unverändert" deshalb zusätzlich: die Datei ist in git +sauber (`git status --porcelain` leer); sonst wird trotz gleichen Inhalts +committet. Nachgemessen in beiden Richtungen: flaglos geschrieben (` M`), +dann `--git-commit` → Commit, Worktree sauber; sauber und gleich → +„nichts zu tun", Commit-Zahl unverändert. Die übrigen Messungen aus dem +Haupttext gelten fort; neu geprüft außerdem: flaglos außerhalb jedes +Worktrees schreibt anstandslos, `--git-commit` dort lehnt mit klarer +Meldung ab. diff --git a/docs/examples/werkbaum.werkbaum b/docs/examples/werkbaum.werkbaum index fc2b90e..4cb1846 100644 --- a/docs/examples/werkbaum.werkbaum +++ b/docs/examples/werkbaum.werkbaum @@ -142,7 +142,7 @@ - [-] #col.pad: Borrow an Etherpad — it merges, we render (L) %% built, then removed, see D78 - [~] #col.git: Git as the shared store (L) | [ ] #col.git.pr: A file in a repository, changed by pull request (S) %% works today, no code - | [x] #col.git.pull: A script pulls the server document and commits it (S) %% tools/pull-doc, dated commits — see D88 + | [x] #col.git.pull: A script pulls the server document and commits it (S) %% tools/pull-doc --git-commit, dated commits — see D88 | [?] #col.git.auto: The backend commits every change (L) :#be.scaffold - [?] #col.git.hist: History and restore (M) - [?] #col.git.diff: Diff between two versions (S) @@ -889,8 +889,9 @@ #col.git.pull The tools/pull-doc script fetches a server document (a ?live= link works too) - and commits it into a git worktree — date, title and version in the message, - no commit when nothing changed. Run from cron, a shared plan archives itself. + and writes it to a file; with --git-commit it also commits it into the git + worktree — date, title and version in the message, no commit when nothing + changed. Run from cron, a shared plan archives itself. #col.git.auto The server turns every change into a commit. History, restore and branches diff --git a/tools/pull-doc b/tools/pull-doc index 769090f..3c55312 100755 --- a/tools/pull-doc +++ b/tools/pull-doc @@ -1,34 +1,39 @@ #!/usr/bin/env bash # -# Werkbaum — pull-doc: ein Server-Dokument in ein git-Worktree holen und -# committen. Gedacht als Archiv-Schritt (auch per Cron): Der Notationstext -# eines geteilten Plans (D76) bekommt so eine Git-Historie. +# Werkbaum — pull-doc: ein Server-Dokument in eine lokale Datei holen; auf +# Wunsch committet es dazu. Gedacht als Archiv-Schritt (auch per Cron): Der +# Notationstext eines geteilten Plans (D76) bekommt so eine Git-Historie. # # Verwendung: -# pull-doc +# pull-doc [--git-commit] # +# --git-commit Die Zieldatei zusätzlich committen. Sie muss dann in einem +# git-Worktree liegen; committet wird nur diese eine Datei, +# die Commit-Nachricht nennt Datum, Titel und Version des +# Server-Stands. Ohne den Schalter wird nur geschrieben. # Die Dokument-Adresse des Backends # (https://…/api/v1/documents/) — oder gleich der # geteilte Editor-Link (…?live=); der Parameter # wird erkannt und ausgepackt. -# Datei, in die der Notationstext geschrieben wird. Sie muss -# in einem git-Worktree liegen. Committet wird nur diese -# eine Datei; die Commit-Nachricht nennt Datum, Titel und -# Version des Server-Stands. +# Datei, in die der Notationstext geschrieben wird. # -# Unverändert heißt: kein Commit — der Lauf meldet es und endet mit 0. -# Geschrieben wird byte-getreu, was der Server hält (der Text ist das -# führende Datenformat, D14); andere vorgemerkte Änderungen im Worktree +# Unverändert heißt: nichts geschrieben, kein Commit — der Lauf meldet es und +# endet mit 0. Geschrieben wird byte-getreu, was der Server hält (der Text ist +# das führende Datenformat, D14); andere vorgemerkte Änderungen im Worktree # bleiben unangetastet (Commit mit Pfadangabe). # # Siehe docs/DECISIONS.md D88. set -euo pipefail -usage(){ sed -n '2,22p' "$0" | sed 's/^# \{0,1\}//'; } +usage(){ sed -n '2,24p' "$0" | sed 's/^# \{0,1\}//'; } -case "${1:-}" in -h|--help) usage; exit 0;; esac -[ $# -eq 2 ] || { echo "Fehler: genau zwei Argumente erwartet (URL und Zieldatei)." >&2; echo >&2; usage >&2; exit 2; } +do_commit=0 +case "${1:-}" in + -h|--help) usage; exit 0;; + --git-commit) do_commit=1; shift;; +esac +[ $# -eq 2 ] || { echo "Fehler: erwartet [--git-commit] URL und Zieldatei." >&2; echo >&2; usage >&2; exit 2; } url="$1"; target="$2" @@ -50,11 +55,13 @@ case "$url" in http://*|https://*) ;; *) echo "Fehler: keine http(s)-URL: $url" [ -d "$target" ] && { echo "Fehler: $target ist ein Verzeichnis." >&2; exit 2; } dir="$(dirname -- "$target")"; base="$(basename -- "$target")" [ -d "$dir" ] || { echo "Fehler: Verzeichnis $dir gibt es nicht." >&2; exit 2; } -if [ "$(git -C "$dir" rev-parse --is-inside-work-tree 2>/dev/null)" != "true" ]; then - echo "Fehler: $dir liegt in keinem git-Worktree." >&2; exit 2 -fi -if [ "$(git -C "$dir" rev-parse --is-inside-git-dir 2>/dev/null)" = "true" ]; then - echo "Fehler: $dir liegt im .git-Verzeichnis." >&2; exit 2 +if [ "$do_commit" = 1 ]; then + if [ "$(git -C "$dir" rev-parse --is-inside-work-tree 2>/dev/null)" != "true" ]; then + echo "Fehler: $dir liegt in keinem git-Worktree (nötig für --git-commit)." >&2; exit 2 + fi + if [ "$(git -C "$dir" rev-parse --is-inside-git-dir 2>/dev/null)" = "true" ]; then + echo "Fehler: $dir liegt im .git-Verzeichnis." >&2; exit 2 + fi fi tmp_json="$(mktemp)"; tmp_doc="$dir/.$base.pull-doc.$$" @@ -80,13 +87,22 @@ PY )" title="${meta%$'\t'*}"; version="${meta##*$'\t'}" +# Unveraendert heisst: Datei gleich dem Server-Stand — und im Commit-Modus +# zusaetzlich in git sauber, sonst bliebe eine liegende Aenderung (etwa aus +# einem Lauf ohne --git-commit) fuer immer uncommittet. if [ -f "$target" ] && cmp -s "$tmp_doc" "$target"; then - echo "Unverändert: „$title“ (Version $version) — kein Commit." - exit 0 + if [ "$do_commit" != 1 ] || [ -z "$(git -C "$dir" status --porcelain -- "$base")" ]; then + echo "Unverändert: „$title“ (Version $version) — nichts zu tun." + exit 0 + fi fi mv -- "$tmp_doc" "$target" -msg="Werkbaum-Stand vom $(date '+%Y-%m-%d %H:%M') — „$title“ (Version $version)" -git -C "$dir" add -- "$base" -git -C "$dir" commit -q -m "$msg" -- "$base" -echo "Committet $(git -C "$dir" rev-parse --short HEAD): $msg" +if [ "$do_commit" = 1 ]; then + msg="Werkbaum-Stand vom $(date '+%Y-%m-%d %H:%M') — „$title“ (Version $version)" + git -C "$dir" add -- "$base" + git -C "$dir" commit -q -m "$msg" -- "$base" + echo "Committet $(git -C "$dir" rev-parse --short HEAD): $msg" +else + echo "Geschrieben: $target — „$title“ (Version $version)" +fi