diff --git a/.checkpoint-pending.txt b/.checkpoint-pending.txt index 68590e2..cc8fb43 100644 --- a/.checkpoint-pending.txt +++ b/.checkpoint-pending.txt @@ -1,6 +1,8 @@ S06 -PDF-Build-Hotfix nach erstem Build der Tabellen-Revision: LuaLaTeX schlug in der Tabellen-Spaltenangabe mit der Meldung ueber einen nicht definierten Counter none fehl, weil Thomas Pandoc-Version (3.x) calc-basierte Spaltenbreiten der Form p von Klammer Spaltenbreite minus 2 mal tabcolsep Klammerzu mal real Faktor emittiert und das Template weder das calc-Paket noch das Pandoc-Hilfsmakro real bereitstellte (Sandbox-Pandoc 2.9 emittiert die simplere ll-Spaltenform und hat den Fehler nicht reproduziert). -templates/template.tex Tabellen-Block ergaenzt um usepackage array, usepackage calc und providecommand real. -Sandbox-Verifikation: synthetischer Pandoc-3.x-Spalten-Output kompiliert mit dem erweiterten Template via LuaLaTeX zu PDF, nur eine harmlose longtable-Rerun-Warnung. -DOCX nach Tabellen-Revision von Thomas visuell bestaetigt (Tabelle sieht gut aus, nur Default-Word-Tabellenrahmenlinien noch da, Rahmen-Aus in Iteration B). -teilgebiete/01-lebenslauf.md und agent-prompt.md um Hotfix-Eintrag und DOCX-Bestaetigung ergaenzt. +Tooling-Fix: checkpoint.ps1 robust gegen problematische Eingabedaten gemacht. +Commit-Message wird jetzt via Temp-Datei und git commit -F uebergeben statt via -m mit String, damit doppelte Anfuehrungszeichen im Summary nicht mehr das Argument zerlegen (Ursache des fehlgeschlagenen Hotfix-Commits zuvor). +Pipe-Zeichen im Summary werden vorab abgelehnt, da sie mit dem Changelog-Format Timestamp Pipe Session Pipe Summary kollidieren. +Whitespace und Zeilenumbrueche im Summary werden zu einem einzelnen Leerzeichen normalisiert. +Pre-flight-Checks ergaenzt: Existenz von .git, verwaiste .git/index.lock mit klarer Anleitung melden, changelog.md muss vor dem Lauf clean sein. +Atomarer Rollback bei Fehler im Hauptablauf: changelog.md wird auf Original-Stand zurueckgeschrieben und Index-Stagung von changelog.md per git restore --staged oder git reset HEAD zurueckgesetzt, sodass der naechste Lauf nicht doppelt anhaengt. +Cleanup-Robustheit: Temp-Message-Datei wird in finally geloescht, das Loeschen der Pending-Datei ist nicht mehr fatal sondern nur eine Warnung. diff --git a/changelog.md b/changelog.md index b7d49c7..9d6846d 100644 --- a/changelog.md +++ b/changelog.md @@ -40,3 +40,4 @@ Chronologisches Log aller Entscheidungen und Prozessereignisse. 2026-04-25 14:28 | S06 | Teilgebiet 01 Iteration A abgeschlossen: Ausbildung als 2-Spalten-Layout via Pandoc-Definition-List umgesetzt. source/cv.md Ausbildungs-Abschnitt auf Term/Definition-Syntax umgestellt (Datum als Term, Inhalt als Definition). templates/template.tex um enumitem-Konfiguration der description-Liste erweitert (style=multiline, labelwidth=5.5em, leftmargin=6.5em, font=\normalfont). Sandbox-Verifikation: Pandoc-LaTeX rendert sauberes \begin{description} mit vier Eintraegen, Pandoc-DOCX nutzt die Standardstile DefinitionTerm und Definition (in Iteration B in Word zu stylen). Hinweis: Pandoc setzt \tightlist innerhalb der Description-Liste und ueberschreibt damit zur Laufzeit das itemsep auf 0 — fuer vier kurze Eintraege visuell vertretbar. teilgebiete/01-lebenslauf.md um Iteration-A-Block ergaenzt und Naechste-Schritte-Liste auf B/C/D reduziert. agent-prompt.md Aktueller-Stand-Abschnitt auf S06 fortgeschrieben. 2026-04-25 20:58 | S06 | Iteration A revidiert: Ausbildungs-Layout von Definition-List auf Pandoc-Multiline-Tabelle umgestellt, weil Definition-List im DOCX kein echtes 2-Spalten-Layout liefert (Word kann Term und Definition als zwei Absatzstile nicht in eine Zeile zwingen). source/cv.md Ausbildungs-Abschnitt nutzt jetzt headerless Multiline-Tabelle mit Strich-Verhaeltnis 10:70 (Pandoc berechnet Spaltenbreiten von ca. 14 Prozent und 80 Prozent der Textbreite). templates/template.tex Description-List-Block wieder entfernt; neuer Tabellen-Block mit booktabs und longtable, Linienbreiten und Rule-Separations auf 0pt, LTpre/LTpost auf 0.4em. Sandbox-Verifikation: Pandoc-LaTeX rendert longtable mit Minipage-Auto-Wrap und vier Datenzeilen, Pandoc-DOCX rendert eine native Word-Tabelle mit vier Zeilen und acht Zellen, keine Reste der Definition-List-Stile. teilgebiete/01-lebenslauf.md Iteration-A-Block umgeschrieben mit Begruendung der Revision und Beschreibung des neuen Setups. agent-prompt.md Aktueller-Stand-Abschnitt auf die Tabellen-Variante fortgeschrieben. 2026-04-25 22:15 | S06 | PDF-Build-Hotfix nach erstem Build der Tabellen-Revision: LuaLaTeX schlug in der Tabellen-Spaltenangabe mit der Meldung ueber einen nicht definierten Counter none fehl, weil Thomas Pandoc-Version (3.x) calc-basierte Spaltenbreiten der Form p von Klammer Spaltenbreite minus 2 mal tabcolsep Klammerzu mal real Faktor emittiert und das Template weder das calc-Paket noch das Pandoc-Hilfsmakro real bereitstellte (Sandbox-Pandoc 2.9 emittiert die simplere ll-Spaltenform und hat den Fehler nicht reproduziert). templates/template.tex Tabellen-Block ergaenzt um usepackage array, usepackage calc und providecommand real. Sandbox-Verifikation: synthetischer Pandoc-3.x-Spalten-Output kompiliert mit dem erweiterten Template via LuaLaTeX zu PDF, nur eine harmlose longtable-Rerun-Warnung. DOCX nach Tabellen-Revision von Thomas visuell bestaetigt (Tabelle sieht gut aus, nur Default-Word-Tabellenrahmenlinien noch da, Rahmen-Aus in Iteration B). teilgebiete/01-lebenslauf.md und agent-prompt.md um Hotfix-Eintrag und DOCX-Bestaetigung ergaenzt. +2026-04-25 22:35 | S06 | Tooling-Fix: checkpoint.ps1 robust gegen problematische Eingabedaten gemacht. Commit-Message wird jetzt via Temp-Datei und git commit -F uebergeben statt via -m mit String, damit doppelte Anfuehrungszeichen im Summary nicht mehr das Argument zerlegen (Ursache des fehlgeschlagenen Hotfix-Commits zuvor). Pipe-Zeichen im Summary werden vorab abgelehnt, da sie mit dem Changelog-Format Timestamp Pipe Session Pipe Summary kollidieren. Whitespace und Zeilenumbrueche im Summary werden zu einem einzelnen Leerzeichen normalisiert. Pre-flight-Checks ergaenzt: Existenz von .git, verwaiste .git/index.lock mit klarer Anleitung melden, changelog.md muss vor dem Lauf clean sein. Atomarer Rollback bei Fehler im Hauptablauf: changelog.md wird auf Original-Stand zurueckgeschrieben und Index-Stagung von changelog.md per git restore --staged oder git reset HEAD zurueckgesetzt, sodass der naechste Lauf nicht doppelt anhaengt. Cleanup-Robustheit: Temp-Message-Datei wird in finally geloescht, das Loeschen der Pending-Datei ist nicht mehr fatal sondern nur eine Warnung. diff --git a/checkpoint.ps1 b/checkpoint.ps1 index 9768d43..44bbc11 100644 --- a/checkpoint.ps1 +++ b/checkpoint.ps1 @@ -5,23 +5,68 @@ # .checkpoint-pending.txt, haengt einen Eintrag an changelog.md # an (mit aktuellem Timestamp vom lokalen PC), fuehrt einen # Git-Commit aus und loescht die Pending-Datei. +# +# Robust gegen problematische Eingabedaten: +# - Doppelte Anfuehrungszeichen in der Zusammenfassung werden +# sauber durchgereicht, weil die Commit-Message via +# "git commit -F " uebergeben wird (keine +# Shell-Argument-Quoting-Probleme). +# - Pipe-Zeichen "|" in der Zusammenfassung werden abgelehnt, +# weil sie mit dem Changelog-Format +# Timestamp | Session | Summary kollidieren. +# - Whitespace und Zeilenumbrueche in der Zusammenfassung +# werden zu einem Leerzeichen normalisiert. +# - Bei Fehler im Hauptablauf wird der Anhang an changelog.md +# und die Index-Stagung von changelog.md zurueckgerollt, +# sodass der naechste Lauf nicht doppelt anhaengt. +# - Eine verwaiste .git/index.lock wird vor dem Lauf erkannt +# und mit klarer Anleitung gemeldet. # ============================================================ $ErrorActionPreference = 'Stop' -# Repo-Root = Ordner, in dem dieses Skript liegt +# --- Pfade ------------------------------------------------- $repoRoot = $PSScriptRoot Set-Location $repoRoot $pendingFile = Join-Path $repoRoot '.checkpoint-pending.txt' $changelogFile = Join-Path $repoRoot 'changelog.md' +$gitDir = Join-Path $repoRoot '.git' +$indexLock = Join-Path $gitDir 'index.lock' -# --- Pending-Datei lesen ----------------------------------- +$utf8NoBom = New-Object System.Text.UTF8Encoding $false + +# --- Pre-flight Checks ------------------------------------- if (-not (Test-Path $pendingFile)) { Write-Error ".checkpoint-pending.txt nicht gefunden." exit 1 } +if (-not (Test-Path $changelogFile)) { + Write-Error "changelog.md nicht gefunden." + exit 1 +} +if (-not (Test-Path $gitDir)) { + Write-Error ".git-Verzeichnis nicht gefunden ($gitDir)." + exit 1 +} +if (Test-Path $indexLock) { + Write-Error ".git/index.lock existiert bereits. Eine vorherige Git-Operation hat sich nicht aufgeraeumt. Falls kein Git-Prozess mehr laeuft, manuell loeschen: Remove-Item '$indexLock' -Force" + exit 1 +} +# changelog.md darf vor dem Lauf keine lokalen Aenderungen haben, +# damit ein eventueller Rollback eindeutig bleibt. +$clStatus = & git status --porcelain -- changelog.md 2>$null +if ($LASTEXITCODE -ne 0) { + Write-Error "git status fehlgeschlagen (Exit Code $LASTEXITCODE). Liegt das Repo in einem konsistenten Zustand vor?" + exit 1 +} +if ($null -ne $clStatus -and ($clStatus -join '').Trim() -ne '') { + Write-Error "changelog.md hat lokale Aenderungen. Bitte erst per Hand committen oder mit 'git checkout -- changelog.md' verwerfen, bevor checkpoint.cmd laeuft." + exit 1 +} + +# --- Pending-Datei einlesen -------------------------------- $lines = Get-Content $pendingFile -Encoding UTF8 if ($lines.Count -lt 2) { Write-Error ".checkpoint-pending.txt muss mindestens 2 Zeilen enthalten (Session, Zusammenfassung)." @@ -29,8 +74,10 @@ if ($lines.Count -lt 2) { } $session = $lines[0].Trim() -$summary = ($lines | Select-Object -Skip 1 | Where-Object { $_.Trim() -ne '' }) -join ' ' -$summary = $summary.Trim() +$summaryLines = $lines | Select-Object -Skip 1 | Where-Object { $_.Trim() -ne '' } +$summary = ($summaryLines -join ' ') +# Whitespace und Steuerzeichen normalisieren +$summary = ($summary -replace '\s+', ' ').Trim() if ([string]::IsNullOrWhiteSpace($session)) { Write-Error "Session-Nummer (Zeile 1) ist leer." @@ -44,49 +91,94 @@ if ([string]::IsNullOrWhiteSpace($summary)) { Write-Error "Zusammenfassung (Zeile 2+) ist leer." exit 1 } +if ($summary -match '\|') { + Write-Error "Zusammenfassung enthaelt das Pipe-Zeichen '|', das mit dem Changelog-Format Timestamp | Session | Summary kollidiert. Bitte ersetzen." + exit 1 +} # --- Timestamp und Eintrag bauen --------------------------- $timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm' -$entry = "$timestamp | $session | $summary" +$entry = "$timestamp | $session | $summary" +$commitMsg = "${session}: $summary" Write-Host "" Write-Host "[checkpoint] Neuer Eintrag:" -ForegroundColor Cyan Write-Host " $entry" Write-Host "" -# --- Eintrag an changelog.md anhaengen --------------------- -# Immer erst sicherstellen, dass die Datei mit einem Zeilenumbruch endet. -$utf8NoBom = New-Object System.Text.UTF8Encoding $false +# --- Backup fuer Rollback und Temp-Message-Datei ----------- +$originalChangelog = [System.IO.File]::ReadAllText($changelogFile, $utf8NoBom) +$tempMsgFile = Join-Path ([System.IO.Path]::GetTempPath()) ("checkpoint-msg-" + [guid]::NewGuid().ToString() + ".txt") -if (Test-Path $changelogFile) { - $existing = [System.IO.File]::ReadAllText($changelogFile, $utf8NoBom) - if ($existing.Length -gt 0 -and -not ($existing.EndsWith("`n"))) { +# --- Hauptablauf ------------------------------------------- +$success = $false +$errorMsg = $null +try { + # 1. Sicherstellen, dass changelog.md mit Newline endet + if ($originalChangelog.Length -gt 0 -and -not ($originalChangelog.EndsWith("`n"))) { [System.IO.File]::AppendAllText($changelogFile, "`r`n", $utf8NoBom) } -} else { - Write-Error "changelog.md nicht gefunden." + + # 2. Eintrag anhaengen + [System.IO.File]::AppendAllText($changelogFile, $entry + "`r`n", $utf8NoBom) + Write-Host "[checkpoint] An changelog.md angehaengt." -ForegroundColor Green + + # 3. Commit-Message-Datei schreiben (UTF-8 ohne BOM) + [System.IO.File]::WriteAllText($tempMsgFile, $commitMsg + "`n", $utf8NoBom) + + # 4. git add -A + & git add -A + if ($LASTEXITCODE -ne 0) { + throw "git add fehlgeschlagen (Exit Code $LASTEXITCODE)." + } + + # 5. git commit -F (umgeht Shell-Argument-Quoting) + & git commit -F $tempMsgFile + if ($LASTEXITCODE -ne 0) { + throw "git commit fehlgeschlagen (Exit Code $LASTEXITCODE)." + } + + Write-Host "[checkpoint] Commit erstellt: $commitMsg" -ForegroundColor Green + $success = $true +} +catch { + $errorMsg = $_.Exception.Message +} +finally { + # Temp-Message-Datei aufraeumen + if (Test-Path $tempMsgFile) { + Remove-Item $tempMsgFile -Force -ErrorAction SilentlyContinue + } +} + +if (-not $success) { + Write-Host "" + Write-Host "[checkpoint] FEHLER: $errorMsg" -ForegroundColor Red + Write-Host "[checkpoint] Rollback wird ausgefuehrt..." -ForegroundColor Yellow + + # changelog.md auf Original-Stand zurueckschreiben + try { + [System.IO.File]::WriteAllText($changelogFile, $originalChangelog, $utf8NoBom) + Write-Host "[checkpoint] changelog.md auf Original-Stand zurueckgerollt." -ForegroundColor Yellow + } catch { + Write-Host "[checkpoint] WARNUNG: Rollback von changelog.md fehlgeschlagen ($($_.Exception.Message))." -ForegroundColor Red + } + + # Index-Stagung fuer changelog.md auf HEAD zuruecksetzen + & git restore --staged -- changelog.md 2>$null | Out-Null + if ($LASTEXITCODE -ne 0) { + # Fallback fuer aelteres Git ohne 'restore' + & git reset HEAD -- changelog.md 2>$null | Out-Null + } + + Write-Host "[checkpoint] FEHLGESCHLAGEN - .checkpoint-pending.txt bleibt erhalten fuer einen erneuten Lauf." -ForegroundColor Red exit 1 } -[System.IO.File]::AppendAllText($changelogFile, $entry + "`r`n", $utf8NoBom) -Write-Host "[checkpoint] An changelog.md angehaengt." -ForegroundColor Green - -# --- Git add + commit -------------------------------------- -& git add -A -if ($LASTEXITCODE -ne 0) { - Write-Error "git add fehlgeschlagen (Exit Code $LASTEXITCODE)." - exit $LASTEXITCODE +# --- Pending-Datei loeschen (nicht fatal wenn das fehlschlaegt) --- +try { + Remove-Item $pendingFile -Force + Write-Host "[checkpoint] .checkpoint-pending.txt entfernt." -ForegroundColor Green +} catch { + Write-Host "[checkpoint] WARNUNG: .checkpoint-pending.txt konnte nicht geloescht werden ($($_.Exception.Message)). Bitte manuell entfernen." -ForegroundColor Yellow } - -$commitMsg = "${session}: $summary" -& git commit -m $commitMsg -if ($LASTEXITCODE -ne 0) { - Write-Error "git commit fehlgeschlagen (Exit Code $LASTEXITCODE)." - exit $LASTEXITCODE -} - -Write-Host "[checkpoint] Commit erstellt: $commitMsg" -ForegroundColor Green - -# --- Pending-Datei loeschen -------------------------------- -Remove-Item $pendingFile -Force -Write-Host "[checkpoint] .checkpoint-pending.txt entfernt." -ForegroundColor Green