Preflight, Launcher und Tool-Pfade: Voraussetzungen früh prüfen, anhalten statt ausweichen – auf allen Plattformen #151

Open
opened 2026-09-27 08:44:01 +00:00 by torben · 11 comments
Owner

Teilpaket von #140 (Installation neu schneiden, Windows nativ). Die Entscheidungen dazu sind getroffen: D13 (Ort der Regel), D14 (.wikitool-tools.json auf allen Plattformen), D15 (Launcher-Satz), D16 (Mark of the Web, mit Anleitung für den Nutzer) und D27 (Release-Download beim Erstinstall) am 2026-09-28, D32 Teil 2 (Ordnerlänge) am 2026-09-30, D33–D37 (aus der Vorbereitung) am 2026-09-30, D38–D41 (für Abschnitt C) am 2026-10-01. Die Prüfpunkte T1, T2 und T4–T8 aus #140 sind beantwortet (2026-09-30) und unten eingearbeitet.

Stand 2026-10-01: Alle drei Abschnitte sind publiziert.

  • A (sh-Hälfte, Baum-Modus): e4b2b6d, Kandidat 8.0.0-beta.14, CI-Lauf 469 grün.
  • B (pwsh-Hälfte, Baum-Modus): 210e0c8, Kandidat 8.0.0-beta.15 (Image chemenu-ci-pwsh in 4035b1b), CI-Lauf 476 grün, Release-Lauf 477 grün.
  • C (Asset-Modus, beide Plattformen): c33e8cd (8.0.0-beta.16) und der Nachzug d6e973c (8.0.0-beta.17). CI-Lauf 480 (verify + pwsh) und Release-Lauf 481 sind grün.

Die Handprüfung auf dem Windows-Zielsystem ist gelaufen (Betreiber, 2026-10-01, Stand 8.0.0-beta.17), siehe Handprüfung. Alles, was #151 selbst verspricht, hat gehalten. Offen ist nur noch ein Punkt: der Asset-Weg aus einem echten Release. Er ist erst nach dem nächsten Release ohne Suffix möglich. Zwei Nebenbefunde gehören nicht zu #151 und stehen in eigenen Paketen:

  • #164: Die Copilot-Hooks öffnen unter Windows den Dialog „App auswählen“.
  • #152: Die Ausgabe kommt in den Harnesses falsch kodiert an.

Warum

Im analysierten Installationslauf (#140) fehlte zu Beginn Python im Terminal, später rg. Der Agent ist ausgewichen – nach WSL, mit einem lokalen Patch, mit Handarbeit an Git-Konfiguration und Push – statt anzuhalten. Die Regel dagegen (Betreiber, 2026-09-27):

Die nötigen Tools werden früh per möglichst einfacher Shell auf Existenz geprüft. Fehlt etwas, hält der Agent an, meldet was fehlt und gibt dem Nutzer Gelegenheit, Abhängigkeiten zu installieren und Pfade anzugeben – in einer Schleife, bis alle Tools erreichbar sind. Pfade werden in einer Konfigurationsdatei festgehalten.

Der Agent installiert nie selbst, auch nicht mit Zustimmung (#140 D6).

Die Prüfung kann kein wikitool-Befehl sein: ohne Python startet wikitool nicht.

Entscheidungen aus der Vorbereitung (Betreiber, 2026-09-30)

Beim Abgleich mit dem Baum aufgefallen, jeweils mit der Empfehlung entschieden. Nummern fortlaufend zu #140.

D33 – Preflight in zwei Modi; das Manifest steht nur im Baum

Befund: Nach D5/D27 ist der Preflight ein Release-Asset und läuft, bevor es einen Baum gibt. tools/prerequisites.txt und das Ziel für .wikitool-tools.json gibt es dann noch nicht.

Entschieden: ein Skript je Plattform mit zwei Modi. Welcher gilt, entscheidet, ob neben dem Skript ein Stack-Baum liegt.

  • Asset-Modus (Erstinstall): Ordnerlänge prüfen → Release laden, sha256 prüfen, entpacken → die mitgelieferte Kopie tools/preflight.* im entpackten Baum aufrufen.
  • Baum-Modus (nach dem Entpacken, Klon, Handweg, nach dist upgrade): Markierung → Tools nach Manifest → .wikitool-tools.json → venv (D34).

Die Reihenfolge weicht damit von D27 ab: Geladen wird vor der Tool-Prüfung. Fehlt Python, liegt schon ein entpackter Baum da, und die Schleife läuft dort weiter.

Der sh-Asset-Modus braucht curl, tar und sha256sum oder shasum. Fehlt eins, gibt es Exit 42 mit Anleitung. Unter pwsh reichen Bordmittel (Invoke-WebRequest, Get-FileHash, tar.exe).

Die Ordnergrenze 95 steht im Manifest (limit|install_dir_max|95). Im Asset-Modus liegt das Manifest vor dem Entpacken noch nicht auf der Platte. Es wird nach der sha256-Prüfung per tar -xOzf <archiv> <oberster>/tools/prerequisites.txt aus dem Archiv gelesen; das geht mit GNU tar wie mit tar.exe. So bleibt die Zahl an einer Stelle, und die Prüfung liegt trotzdem vor dem Entpacken.

Verworfen: das Manifest in beide Skripte einbetten. Das hätte drei Kopien der Liste und eine weitere generierte Region gekostet.

D34 – Der Preflight legt das venv an

Befund: Der Launcher schickt einen ohne venv zum Preflight, der Entwurf ließ den Preflight aber kein venv anlegen. So hätte die Schleife nie geendet.

Entschieden: Der Preflight legt im Baum-Modus als letzten Schritt tools/.venv an: <python> -m venv, dann <venv-python> -m pip install -r tools/requirements.txt. Das läuft idempotent bei jedem Lauf und bringt damit nach dist upgrade auch geänderte Requirements nach.

Mit D6 ist das vereinbar: Alles bleibt im Installationsordner, am System ändert sich nichts. Ein Fehler bei venv oder pip (kein Netz, Proxy, ASR) ist ein Stoppfall mit Anleitung.

Verworfen: den venv-Schritt in den Anleitungen belassen. Das hätte die Shell-Befehle zurückgebracht, die #153 Punkt 6 entfernt.

D35 – Der Bruch wird angenommen und in 8.0.0 gebündelt

Befund: Mit „ohne .wikitool-tools.json Exit 42“ startet nach dem Update auf 8.0.0 bei keiner bestehenden Instanz wikitool, bis einmal der Preflight gelaufen ist. Das betrifft auch den Entwicklungs-Checkout, alle vier Workflows (ci, release, nightly, tracker-live) und das CI-Replay. Nach dem Drop-in-Test ist das ein Bruch.

Entschieden: Der Bruch wird angenommen. Der Kandidat ist schon major, die Instanzen zahlen also nur einmal.

  • version bump --major --breaking "…"
  • Die Workflows rufen im selben Abschnitt den Preflight statt ihres venv-Blocks auf.
  • upgrade-instance.md bekommt den Preflight als Schritt vor instructions sync, und die Abschlussmeldung von dist upgrade nennt ihn.

Verworfen: ein Shim mit PATH-Rückfall. Er hätte genau das Überspringen erlaubt, das die Regel verhindern soll.

D36 – Hooks starten über die venv-Python

Befund: Hook-Befehle sind statische Strings in .claude/settings.json, .github/hooks/wiki-trace.json und .vibe/hooks.toml. Sie können .wikitool-tools.json nicht lesen, und Claude Code hat einen einzigen Befehlsstring für Linux, macOS und Git Bash unter Windows.

Entschieden: Die Hooks starten trace_ingest.py (nur Standardbibliothek) mit der venv-Python. Sie stammt aus der festgelegten Python und liegt an einem festen Ort.

  • Ein kleines sh-Skript tools/trace-hook wählt das Layout (.venv/bin/python oder .venv/Scripts/python.exe). Claude Code, Vibe und Copilots bash-Zweig rufen es auf.
  • Copilots powershell-Zweig ruft .\tools\.venv\Scripts\python.exe direkt auf.
  • Ohne venv bleibt der Hook still wie heute (|| true).

Damit braucht kein Hook einen JSON-Parser, und keiner hängt an der Execution Policy. #82 (Tool-Hooks auf Claude Code) baut danach auf tools/trace-hook auf.

Nachtrag (Handprüfung 2026-10-01): Unter Windows führt Copilot den bash-Zweig aus. Windows versucht dann, ./tools/trace-hook über eine Dateizuordnung zu öffnen, und fragt nach einer App. Die Annahme „Copilot nimmt unter Windows den powershell-Zweig“ hält also für mindestens einen Client nicht. Die Korrektur ist #164.

Verworfen: die JSON-Datei in sh lesen. Das wäre aufwendiger gewesen, ohne etwas zu gewinnen.

D37 – pwsh im CI über ein vorgebautes Image

Befund: debian:trixie-slim hat pwsh nicht in seinen Paketquellen, und PSScriptAnalyzer kommt aus der PowerShell Gallery. Ob der Runner github.com und die Gallery erreicht, ist nicht geprüft. dash ist unkritisch, er ist dort /bin/sh.

Entschieden: ein Image gitea.nehmer.net/torben/chemenu-ci-pwsh (trixie-slim + pwsh + PSScriptAnalyzer), gebaut nach dem Muster von chemenu-sp-live (#156). Ein eigener Job in ci.yml nutzt es. Handschritt Betreiber: Nach dem ersten Push das Paket in der Gitea-Oberfläche mit dem Repo verknüpfen; der Job wartet so lange darauf. Erledigt (2026-10-01).

Verworfen: pwsh und PSScriptAnalyzer bei jedem Lauf installieren. Dann hinge jeder CI-Lauf an zwei externen Quellen.

Entscheidungen für Abschnitt C (Betreiber, 2026-10-01)

Vor C geklärt, jeweils mit der Empfehlung entschieden. Ausgangslage: #140 D5 legt die Preflight-Skripte als Release-Assets neben den Tarball, nennt aber weder Asset-Namen noch Zielordner. release.yml hängte bis dahin nur Tarball und .sha256 an. Für Gitea ist keine stabile Download-URL „neuestes Asset“ belegt, nur die API …/releases/latest.

D38 – C hängt die Preflight-Skripte ans Release

Entschieden: release.yml hängt zusätzlich preflight.sh und preflight.ps1 an, unter genau diesen Namen. Von #153 Punkt 5 bleibt dort nur die Installationsanweisung als Asset.

Warum: Ohne Asset ruft den Asset-Modus in der Praxis niemand auf. Die Änderung sind zwei Einträge in der bestehenden Upload-Schleife.

Verworfen: alles Anhängen in #153 belassen und C nur lokal testen.

D39 – Das Asset-Skript kennt sein eigenes Release

Entschieden: release.yml schreibt beim Anhängen die URLs von Tarball und .sha256 desselben Releases in die Asset-Kopie (Platzhalter im Skript). Das Skript lädt immer genau das Release, zu dem es gehört. Die Kopie im Baum hat leere Platzhalter; ohne eingetragene URL und ohne --archive (D41) endet der Asset-Modus mit Exit 1 und dem Hinweis, dass diese Kopie nicht aus einem Release stammt.

Warum: Kein JSON-Parsen in sh. Die URLs setzt der Workflow ein, der sie kennt, nicht das Skript. Welches Release das neueste ist, klärt der Agent beim Laden des Skripts (#153, Installationssatz).

Verworfen: das Skript fragt selbst releases/latest ab. Unter pwsh ginge das sauber, unter sh nur per sed über JSON, und das ist fragil.

D40 – Zielordner chemenu neben dem Skript, --into überschreibt

Entschieden: Standardziel ist <Ordner des Skripts>/chemenu, mit --into <pfad> überschreibbar. Ablauf:

  • die Ordnerlänge (Grenze aus dem Manifest im Archiv, D33) wird am endgültigen Zielpfad geprüft, vor dem Entpacken;
  • entpackt wird in einen temporären Nachbarordner;
  • geprüft wird, dass das Archiv genau einen obersten Ordner hat, wie _extract_single_top_level_dir in dist_cmd.py;
  • danach wird umbenannt.

Ein schon vorhandenes Ziel wird verweigert.

Warum: Ein Ordnername mit Version (chemenu-stack-<version>) führt nach dem ersten dist upgrade in die Irre, weil der Ordner bleibt und die Version wechselt.

Verworfen: wie Weg A in INSTALL.md nach chemenu-stack-<version>/ entpacken.

D41 – --archive <pfad> für ein lokales Archiv

Entschieden: --archive <pfad> nimmt einen schon vorhandenen Tarball; <pfad>.sha256 muss daneben liegen. Die sha256-Prüfung läuft genauso wie beim Download.

Warum: Das ist ein echter Weg für Rechner ohne direkten Download (Proxy, offline) und zugleich der Test-Einstieg auf beiden Plattformen. Invoke-WebRequest kann kein file://; Tests über eine Netz-URL bräuchten also einen Server.

Verworfen: nur eine Testvariable statt einer Option.

Was das Zielsystem gezeigt hat (T-Ergebnisse, #140, 2026-09-30)

Prüfpunkt Ergebnis Folge für dieses Paket
T1 pwsh 7 löst tools/wikitool zuerst auf .ps1 auf, dann .cmd, zuletzt die Datei ohne Endung. Git Bash führt die Datei ohne Endung aus. wikitool.ps1 + wikitool (sh) genügen. Kein .cmd. Am 2026-10-01 bestätigt: tools/wikitool doctor startet in pwsh wikitool.ps1.
T10/T9 Allein die Datei ohne Endung ist in pwsh ein stiller No-Op: tools/wikitool doctor gibt nichts aus und endet ohne Fehler. Das war der „Hänger“. wikitool.ps1 ist Pflicht, nicht Komfort.
T4 Copilot in VS Code und Copilot CLI laufen in pwsh 7.6.6. Claude Code läuft in Git Bash (MINGW64); dort ist python = C:\Python314\python, python3 = Store-Alias. Unter Windows darf der sh-Preflight nicht python3 zuerst nehmen. Der Claude-Code-Hook (python3-Shebang) lief dort nachweislich ins Leere (behoben mit D36).
T5 python.exe und python3.exe gibt es als Store-Aliase unter WindowsApps, dazu C:\Windows\py.exe. Punkt 1 (veralteter PATH) wurde nicht nachgestellt. Store-Alias verwerfen, Kandidaten durch Ausführen prüfen. Registry-PATH bleibt als billige Absicherung.
T2 pip.exe blockiert Defender ASR. Der Betreiber lässt es freischalten und arbeitet unter dieser Annahme. Keine ASR-Erkennung. -m pip bleibt, damit der Stack die Freischaltung gar nicht braucht.
T6 LocalMachine = RemoteSigned, keine Gruppenrichtlinie. Der prozessweite Bypass (D16) trägt. Eine Gruppenrichtlinie bleibt ein Stoppfall.
T7 Invoke-WebRequest setzt keine Markierung, der Browser schon; tar -xf gibt sie nicht weiter. Der Download nach D27 (IWR + tar) erzeugt keine Markierung. Die MotW-Prüfung schützt nur noch den Handweg (Browser plus Entpacken im Explorer). Am 2026-10-01 bestätigt: Nach --archive trägt kein entpacktes Skript eine Markierung.
T8 LongPathsEnabled = 0, core.longpaths nicht gesetzt. Prüfung der Ordnerlänge (D32 Teil 2, unten). Die Pfade im Repo begrenzt #163.

Gebaut

Was mit Abschnitt A gebaut ist, ist mit (A ✔) markiert, was mit B gebaut ist, mit (B ✔), was mit C gebaut ist, mit (C ✔).

  • Manifest tools/prerequisites.txt (A ✔) – |-getrennte Zeilen, damit sh, pwsh und Python es ohne Parser lesen: limit|install_dir_max|95 und je Tool tool|name|min|all/windows|Label|Warum|choco|winget|brew|apt|pacman. Inhalt: python ≥ 3.11, git, rg; unter Windows zusätzlich pwsh ≥ 7. Die Execution Policy (#140 D8) prüft nur der pwsh-Preflight (B ✔) und steht nicht im Manifest. Python liest es über chemenu/prerequisites.py.

  • tools/preflight.sh in POSIX-sh (A ✔ Baum-Modus, C ✔ Asset-Modus). Läuft auch unter Git Bash – dort führt Claude Code unter Windows seine Befehle aus (T4); Pfade werden dort per cygpath -w in native Windows-Form gebracht. Die Markierungsprüfung macht nur der pwsh-Preflight.

  • tools/preflight.ps1 mit #Requires -Version 7 (B ✔ Baum-Modus, C ✔ Asset-Modus). Windows PowerShell 5.1 wird nicht unterstützt (#140 D8); #Requires liefert dort eine klare Absage. Schreibt byteidentisches JSON zu preflight.sh (CI vergleicht per cmp).

  • Zwei Modi je Skript (D33; C ✔): Welcher gilt, entscheidet allein, ob tools/prerequisites.txt neben dem Skript liegt. Im Baum-Modus werden --into/--archive mit Exit 1 abgelehnt („belong to the release asset“).

  • Start des pwsh-Preflights immer per pwsh -NoProfile -ExecutionPolicy Bypass -File tools/preflight.ps1 (D16; B ✔). Das gilt nur für diesen einen Prozess und ändert keine Einstellung. Nötig ist es, weil unter RemoteSigned ein markierter Preflight sonst gar nicht startet und seine eigene Markierung nicht melden kann. Auf dem Zielsystem bestätigt: .\tools\preflight.ps1 ohne Präfix scheitert in einem markierten Checkout mit der PowerShell-Meldung „nicht digital signiert“, ohne Anleitung.

  • Unter Windows vor der Suche PATH aus der Registry neu lesen (Machine + User; B ✔). Sonst sieht eine laufende Harness-Sitzung ein frisch per Chocolatey installiertes Tool womöglich nie, und die Schleife endet nicht (Lauf in #140, Punkt 1).

  • Python-Kandidaten, geschärft nach T4/T5 (A ✔ für sh, B ✔ für pwsh):

    • Reihenfolge unter Windows (pwsh und Git Bash): python, py -3, python3. Sonst: python3, python.
    • Jeder Pfad unter …\Microsoft\WindowsApps\ wird verworfen, ohne ihn auszuführen – der Store-Alias kann einen Store-Dialog öffnen. Gesucht wird über alle PATH-Einträge, nicht nur den ersten Treffer.
    • Ein Kandidat gilt erst, wenn <kandidat> -c "import sys; print(…version_info[:2]…, sys.executable)" mit Exit 0 läuft.
    • In .wikitool-tools.json steht sys.executable, nicht der Aufrufname. Auf dem Zielsystem: C:\Python314\python.exe.
  • Ausgabe (A ✔, B ✔): eine Zeile je Tool – OK/MISSING/TOO_OLD, Tool, Version, Pfad. Exit 0 = alles da. Exit 42 = der Nutzer muss handeln. Exit 1 = Aufruffehler, Download/Prüfsumme/Entpacken im Asset-Modus fehlgeschlagen, vorhandenes Ziel, oder unvollständiger Baum.

  • Anleitung bei jedem Stopp (A ✔, B ✔, C ✔): STOP-Kopf mit einer Zeile an den Agenten, dann nummerierte Blöcke mit Why:, Fix: (Befehl für den erkannten Paketmanager, sonst alle), Next:. Die Ausgabe ist englisch; instructions/preflight.md lässt den Agenten eine Übersetzung darunter setzen, nie statt ihrer.

    Stoppfälle: fehlendes Tool (A ✔, B ✔), zu alte Version (A ✔, B ✔), ungültiger --set-Pfad (A ✔, B ✔), Installationsordner zu lang (A ✔, B ✔), fehlgeschlagene venv- oder pip-Einrichtung (A ✔, B ✔), Markierung (B ✔), Execution Policy Restricted/AllSigned, bei Gruppenrichtlinie mit eigener Anleitung (B ✔), fehlendes Download- oder Entpack-Werkzeug im Asset-Modus – sh: curl, tar, sha256sum/shasum; pwsh: tar (C ✔), Ordnerlänge am Asset-Ziel (C ✔).

  • --set <tool>=<pfad> (A ✔, B ✔; im Asset-Modus an den Baum durchgereicht, C ✔) prüft einen vom Nutzer genannten Pfad und schreibt ihn. Ein ungültiger Pfad schreibt nichts. Ein gültiger bleibt bei späteren Läufen erhalten, weil der Preflight einen noch funktionierenden aufgezeichneten Pfad vor der PATH-Suche nimmt.

  • Mark of the Web (D16, B ✔): Der Preflight prüft die *.ps1 unter tools/ auf Zone.Identifier (ZoneId ≥ 3). Bei einem Fund hält er mit Exit 42 und der Anleitung (Get-ChildItem -Recurse -File | Unblock-File) an. Nach T7 tritt das nur auf dem Handweg auf.

  • Execution Policy (B ✔): wirksam ist der erste nicht undefinierte Scope aus MachinePolicy, UserPolicy, CurrentUser, LocalMachine (Process zählt nicht). Restricted/AllSigned ist ein Stoppfall; eine Gruppenrichtlinie bekommt „Admin fragen / Git Bash“, sonst Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned. Prüft der Preflight und doctor.

  • Release-Download beim Erstinstall (D27, D33, D38–D41; C ✔):

    • Der Preflight lädt im Asset-Modus das Release, zu dem er gehört (D39), und prüft die sha256. Ist sie falsch, endet er mit Exit 1, und nichts wird entpackt.
    • Er liest die Ordnergrenze per tar -xOzf <archiv> <oberster>/tools/prerequisites.txt aus dem Archiv und prüft den endgültigen Zielpfad (D40).
    • Er entpackt in den Nachbarordner .chemenu-unpack.<pid>, verlangt genau einen obersten Ordner und benennt um.
    • Danach ruft er die Kopie tools/preflight.* im neuen Baum auf. --set und der Exit-Code werden durchgereicht: unter sh per exec, unter pwsh per Kindprozess mit demselben Bypass.
    • Werkzeuge: unter pwsh Invoke-WebRequest, Get-FileHash und tar.exe; unter sh curl, tar und sha256sum/shasum.
    • Unter Git Bash werden --archive/--into per cygpath -u umgesetzt, weil GNU tar C: als Host liest.
    • --archive (D41) ersetzt den Download.
    • Asset-Namen wie in version.py (chemenu-stack-<version>.tar.gz + .sha256).
    • release.yml erzeugt die Asset-Kopien per sed, prüft per grep -qF beide URLs in beiden Kopien und lädt preflight.sh/preflight.ps1 in derselben Schleife wie Tarball und .sha256 hoch.
  • Ordnerlänge (D32 Teil 2; A ✔ für sh und doctor, B ✔ für pwsh, C ✔ für den Asset-Modus):

    • Unter Windows mit LongPathsEnabled = 0 darf der Installationsordner – das Verzeichnis, das tools/ enthält, als absoluter Windows-Pfad – höchstens 95 UTF-16-Einheiten lang sein.
    • preflight.sh fragt LongPathsEnabled per reg query ab (ein nicht lesbarer Schlüssel gilt als aus); doctor per winreg. Für Tests stehen CHEMENU_PREFLIGHT_PLATFORM und CHEMENU_PREFLIGHT_LONGPATHS bereit; B ergänzt CHEMENU_PREFLIGHT_POLICY und CHEMENU_PREFLIGHT_MARKED.
    • Invariante: 95 + 1 + 160 (titles.PATH_BUDGET, #163) ≤ 259. Die 95 steht nur im Manifest; test_manifest_limit_and_path_budget_fit_max_path_together hält die Summe.
  • .wikitool-tools.json (D14; A ✔): gitignored, pro Checkout, {"schema": 1, "complete": true|false, "tools": {…}}. complete wird erst nach dem venv-Schritt true. Nach einem Stopp stehen die gefundenen Tools mit complete: false in der Datei, damit --set-Werte die Schleife überleben. Deshalb verweigert der Launcher nach jedem Stopp des Preflights, auch nach einem wegen der Execution Policy, bis der Preflight wieder mit 0 endet. Auf dem Zielsystem so beobachtet.

    • chemenu/toolpaths.py löst die Pfade auf; gelesen wird neben tools/ (config._PACKAGE_ROOT), nicht unter CHEMENU_ROOT. Alle Aufrufstellen gehen darüber: git_publish._run und der Scratch-Index-Lauf, config.default_author, corpus_cache, dist_cmd, migrate_cmd (2×), doctor, docs_verify, search/ripgrep.build_argv. upstream_cmd.py bleibt unberührt (entfällt mit #153).
    • Ohne Datei: Rückfall auf den bloßen Namen (Testsuite, direkter Modulaufruf; der Hermetik-Fixture zeigt jeden Test auf eine fehlende Datei). Datei da, aber Tool fehlt oder Pfad weg: ToolPathError (kein OSError), vom CLI als ERROR-Zeile mit Verweis auf den Preflight ausgegeben.
    • Dieselben Aufrufstellen fasst #152 an (encoding="utf-8"). Wer als Zweites landet, zieht nach.
  • Launcher (D15):

    • tools/wikitool (POSIX sh; A ✔): beide venv-Layouts, Exit 42 ohne vollständige Datei oder ohne venv, startet tools/run_wikitool.py statt -m mit PYTHONPATH. Der Name beginnt bewusst nicht mit wikitool. (PATHEXT/.PY).
    • tools/wikitool.ps1 mit #Requires -Version 7 (B ✔). Kein tools/wikitool.cmd (T1, T4). Die Meldungen von Launcher, toolpaths.PREFLIGHT und doctor.PREFLIGHT_FIX nennen auch den pwsh-Aufruf.
  • venv und pip (D34; A ✔, B ✔): immer <python> -m venv --clear (nur wenn das venv fehlt oder kein pip hat) und <venv-python> -m pip install -r. Ein Stempel tools/.venv/.chemenu-requirements.sha256 überspringt pip, solange sich requirements.txt nicht geändert hat.

  • Hooks (D36; A ✔, unter Windows mit Copilot fehlerhaft → #164): .claude/settings.json, der bash-Zweig in .github/hooks/wiki-trace.json und .vibe/hooks.toml rufen ./tools/trace-hook auf; Copilots powershell-Zweig .\tools\.venv\Scripts\python.exe tools\trace_ingest.py. EVALS.md beschreibt es.

  • Bugreport-Sammler (Nachzug aus #157; B ✔):

    • instructions/bug-report.md verweist darauf, dass die Preflight-Ausgabe der Bericht ist, wenn kein Python startet.
    • tools/bugreport.py startet wikitool unter Windows per pwsh -NoProfile -ExecutionPolicy Bypass -File tools/wikitool.ps1 (launcher_command), abgeglichen mit dem gebauten Launcher.
    • Die Pfadprüfung (_collect_tools_config) ist gegen eine echte schema: 1-Datei getestet.
  • Regel-Ort (D13; A ✔): instructions/preflight.md; AGENTS.md § Bootstrap verweist darauf. Keine neue Invariante. Seit C mit einem Entscheidungspunkt für das Asset-Skript.

  • doctor: tool-paths und install-dir (A ✔); Execution Policy samt Gruppenrichtlinie und Mark of the Web an Stack-Skripten (B ✔).

Test ohne Windows-Runner

  • preflight.sh läuft in test_preflight.py unter jeder vorhandenen Shell aus dash und bash, gegen einen PATH aus einzeln verlinkten Hilfsprogrammen plus Stubs. Die Stub-Python spielt auch -m venv und -m pip; kein Test legt ein echtes venv an oder braucht Netz. Der Store-Alias ist ein Stub unter …/WindowsApps/, der beim Ausführen eine Markerdatei schreibt. (A ✔)

  • Lokal (Arch) gibt es nur bash; zusätzlich geprüft unter zsh --emulate sh und in debian:trixie-slim per Docker unter dash und bash (52 Tests grün, dazu ein echter Preflight mit frischem venv).

  • Die Ordnerlänge wird an den Grenzwerten 95/96 gegen LongPathsEnabled = 0/1 geprüft, im Preflight und in doctor. (A ✔)

  • CI: ci.yml richtet sich per Preflight ein, lässt ihn zweimal laufen und vergleicht die Datei; das Replay im exportierten Baum prüft zuerst, dass tools/wikitool doctor mit Exit 42 verweigert, dann den Preflight. (A ✔, Lauf 469 grün)

  • pwsh 7 im Image chemenu-ci-pwsh (D37) mit PSScriptAnalyzer (B ✔, Lauf 476 grün): Job pwsh in ci.yml mit PSScriptAnalyzer (ohne PSAvoidUsingPositionalParameters, im Workflow begründet), preflight.ps1 zweimal plus cmp gegen preflight.sh, tools/wikitool version show aus pwsh, und test_preflight_pwsh.py, test_preflight.py, test_doctor.py.

  • Asset-Modus (C ✔): per --archive (D41) gegen einen im Test gebauten Tarball mit .sha256, auf beiden Plattformen. Abgedeckt sind:

    • Standardziel, --into (auch relativ) und ein vorhandenes Ziel;
    • falsche und fehlende .sha256, zwei oberste Ordner, leere Platzhalter;
    • fehlende Werkzeuge (Exit 42) und die Durchreichung von --set und Exit-Code;
    • die Ordnergrenze 95/96 sowie 110/121 bei einer Grenze von 120 aus dem Archiv.

    Der Download läuft unter sh gegen einen curl-Stub und unter pwsh gegen einen lokalen ThreadingHTTPServer, jeweils auch als fehlgeschlagener Download. test_the_release_workflow_fills_exactly_the_placeholders_the_scripts_keep leitet die sed-Ausdrücke aus den Platzhaltern ab und hält sie gegen release.yml.

  • test_preflight_pwsh.py wird ohne lokales pwsh komplett übersprungen (pytestmark). instructions/dev/testing-conventions.md sagt, wie man das erkennt und die Tests per Docker im Image chemenu-ci-pwsh laufen lässt. Für C liefen sie mit lokalem pwsh 7.6.6 (54 grün) und im CI-Job pwsh. Ein übersprungener pwsh-Test ist kein bestandener.

  • Ohne Windows-Runner (#140 T12) prüft das CI nichts davon auf Windows. Was nur dort prüfbar ist, hat der Betreiber am 2026-10-01 von Hand geprüft (nächster Abschnitt). Nach wie vor ungeprüft:

    • der echte Store-Alias;
    • der Registry-PATH an einem Tool, das einen neuen PATH-Eintrag anlegt;
    • die Gruppenrichtlinie auf dem Zielsystem;
    • der Download aus einem echten Release.

Handprüfung auf dem Windows-Zielsystem (2026-10-01)

Ausgeführt vom Betreiber auf Stand 8.0.0-beta.17 (Windows 11, pwsh 7.6.6, Git Bash, Python 3.14.7, LongPathsEnabled = 0, LocalMachine RemoteSigned). Für den Asset-Modus lag ein Tarball vor, den dist export auf dem Zielsystem gebaut hatte.

Prüfung Ergebnis
doctor in pwsh (Copilot, auch direkt) und in Git Bash (Claude Code, auch direkt) ✔ gibt Ausgabe. Ohne Preflight Exit 42 mit Verweis auf den Preflight, auch aus Copilot heraus. Der Agent hat angehalten und nachgefragt.
reg query aus Git Bash ✔ liefert LongPathsEnabled = 0x0
Aufgezeichnete Windows-Pfade in Git Bash ✔ zweiter tools/preflight.sh-Lauf mit Exit 0. C:\Python314\python.exe, C:\Program Files\Git\cmd\git.exe, C:\ProgramData\chocolatey\bin\rg.exe und C:\Program Files\PowerShell\7\pwsh.exe werden als ausführbar erkannt.
Ordnerlänge 101 Zeichen (Klon) ✔ Exit 42 mit Anleitung
Fehlendes Tool ✔ Nach choco uninstall ripgrep meldet der Preflight in Copilot Exit 42 mit MISSING rg. Der Agent installiert nichts. Nach choco install ripgrep endet der Preflight in derselben Sitzung mit 0. Einschränkung: Der choco-Shim-Ordner stand schon im PATH; das Neueinlesen aus der Registry war hier nicht nötig.
Execution Policy Restricted (CurrentUser) ✔ Der Preflight meldet Exit 42 mit Set-ExecutionPolicy … RemoteSigned, doctor (aus Git Bash) meldet FAIL execution-policy.
Gruppenrichtlinie nicht auf dem Zielsystem geprüft. Der Betreiber nimmt an, dass sie sich analog verhält; der Zweig ist per Testhook abgedeckt.
Mark of the Web (main.zip per Browser, Entpacken im Explorer, ZoneId=3) ✔ Exit 42, der Block nennt wikitool.ps1 und die Zeile Unblock-File. Nach dem Ausführen dieser Zeile endet der Preflight mit 0.
Asset-Modus pwsh ✔ Mit leeren Platzhaltern Exit 1 („does not come from a release“). Mit --archive folgen sha256 OK, das Entpacken nach chemenu\ neben dem Skript und der Baum-Preflight mit 0; dort keine Markierung. Ein zweiter Lauf endet mit Exit 1 „already exists“. Mit --into auf 103 Zeichen Exit 42, nichts entpackt.
Asset-Modus Git Bash ✔ --archive und --into in Windows-Form (C:\…) wie in POSIX-Form (/c/…), jeweils Exit 0 (cygpath)

Befunde außerhalb von #151:

  • Copilot öffnet bei Hook-Ereignissen den Dialog „App auswählen“ für trace-hook → #164.
  • doctor gibt Fu�noten aus, wenn die Ausgabe über die Harness läuft (Copilot und Claude Code); direkt in der Konsole stimmt sie → #152.
  • Unter Copilot warnt session-id, weil keine Harness-Variable gesetzt ist → gehört zu #153 (D26).
  • Einmal hat Copilot .\tools\preflight.ps1 ohne den Bypass-Präfix gestartet und den Anleitungsblock übersetzt wiedergegeben, statt eine Übersetzung darunter zu setzen. instructions/preflight.md hatte er nicht gelesen, weil die Aufforderung direkt „führe tools/preflight aus“ lautete. Das ist ein Punkt für den Installationssatz in #153.

Umsetzungsplan

Drei Abschnitte mit je einem Publish und einem Bump auf dem 8.0.0-Kandidaten – alle erledigt.

A – sh-Hälfte, Baum-Modus – erledigt: e4b2b6d, 8.0.0-beta.14, CI-Lauf 469 grün (2026-10-01)

  • tools/prerequisites.txt, tools/preflight.sh, tools/wikitool, tools/run_wikitool.py, tools/trace-hook, chemenu/toolpaths.py, chemenu/prerequisites.py; alle git/rg-Aufrufstellen; CLI-Behandlung von ToolPathError; doctor (tool-paths, install-dir); .gitignore.
  • Hooks (D36); Workflows ci, release, nightly, tracker-live und CI-Replay (D35).
  • instructions/preflight.md (neu), AGENTS.md § Bootstrap, bootstrap.md, setup-instance.md Schritt 7, upgrade-instance.md Schritt 8, Abschlussmeldung von dist upgrade.
  • Doku: README.md, tools/README.md, tools/CONTRACT.md (Setup + doctor-Record, regeneriert), INSTALL.md (Voraussetzungen, Weg C, § Konfiguration, Troubleshooting), EVALS.md (Hooks).
  • Entwicklungs-Checkout per Preflight eingerichtet.
  • Bump --major --impact high mit dem --breaking-Satz (D35), Changeset in CHANGES.md.
  • Verifiziert: pytest 1827 grün, docs verify, instructions verify, lint --fail-on-error, Replay des CI-Schritts gegen einen frischen dist export; danach CI 469 und Release-Workflow 470 (überspringt die Beta) grün.

B – pwsh-Hälfte, Baum-Modus – erledigt: Image 4035b1b, Code 210e0c8, 8.0.0-beta.15, CI-Lauf 476 (verify + pwsh) und Release-Lauf 477 grün (2026-10-01)

  • tools/preflight.ps1 (Registry-PATH, Python-Kandidaten, Markierung, Execution Policy samt Gruppenrichtlinie, Ordnerlänge), tools/wikitool.ps1.
  • Meldungen von Launcher, toolpaths.PREFLIGHT, doctor.PREFLIGHT_FIX, cli.py, dist_cmd und instructions/preflight.md nennen den pwsh-Aufruf.
  • doctor: execution-policy und script-marks.
  • CI-Image chemenu-ci-pwsh (.gitea/pwsh-ci/Dockerfile, pwsh-ci-image.yml) und -Job; Paket vom Betreiber verknüpft.
  • Bugreport-Nachzug: bugreport.py (launcher_command, echtes schema: 1 im Test), instructions/bug-report.md.
  • Doku: preflight.md, bootstrap.md, setup-instance.md, upgrade-instance.md, bug-report.md, INSTALL.md, README.md, tools/README.md, tools/CONTRACT.md (regeneriert), docs/why-gates-are-code.md.
  • Bump --minor, Changeset in CHANGES.md.
  • Verifiziert: pytest in tools/ 1841 grün (39 übersprungen); pwsh-Tests in Docker 159 grün; ps1- und sh-Preflight schreiben identisches JSON; docs verify, instructions verify, lint --fail-on-error grün; dist export liefert beide .ps1.

C – Asset-Modus (D27/D33, D38–D41), beide Plattformen – erledigt: c33e8cd (8.0.0-beta.16) und d6e973c (8.0.0-beta.17), CI-Lauf 480 (verify + pwsh) und Release-Lauf 481 grün (2026-10-01)

  • preflight.sh und preflight.ps1: Asset-Modus, wenn kein Manifest daneben liegt. Optionen --into <pfad> (D40) und --archive <pfad> (D41); --set wird an die Kopie im Baum durchgereicht, ihr Exit-Code ebenso.
  • URL-Platzhalter RELEASE_ARCHIVE_URL/RELEASE_CHECKSUM_URL (sh) bzw. $ReleaseArchiveUrl/$ReleaseChecksumUrl (pwsh), leer im Baum (D39).
  • Laden, sha256, Ordnergrenze aus dem Archiv, Zielprüfung, Entpacken in einen temporären Nachbarordner, genau ein oberster Ordner, Umbenennen, Aufruf der Kopie im Baum.
  • Stoppfall „Download-/Entpack-Werkzeug fehlt“ (Exit 42 mit Anleitung). Falsche sha256, fehlgeschlagener Download und vorhandenes Ziel enden mit Exit 1, und nichts wird entpackt.
  • release.yml: preflight.sh und preflight.ps1 mit eingetragenen URLs angehängt (D38, D39). Ein Test hält Platzhalter und Workflow zusammen.
  • Tests auf beiden Plattformen (siehe oben).
  • instructions/dev/testing-conventions.md: Entscheidungspunkt, dass test_preflight_pwsh.py ohne pwsh still übersprungen wird und wie die Tests dann per Docker laufen.
  • Doku: instructions/preflight.md (Entscheidungspunkt Asset-Skript, Exit-1-Zeile, Ordnerlänge im Asset-Modus), INSTALL.md (Weg A nennt den Preflight als Asset), tools/README.md, tools/CONTRACT.md (Setup-Absatz), README.md.
  • Bump --minor (8.0.0-beta.16), Changeset in CHANGES.md.
  • Nachzug d6e973c (8.0.0-beta.17, --patch): CI-Lauf 478 auf c33e8cd war im Job pwsh rot. PSScriptAnalyzer (PSUseShouldProcessForStateChangingFunctions) liest das Verb Stop in der Hilfsfunktion Stop-Asset als zustandsändernd. Sie heißt jetzt Exit-Asset, neben Exit-WithGuide; das Verhalten ist unverändert. Lokal per Docker im Image chemenu-ci-pwsh geprüft: 0 Funde.
  • #153 Punkt 5: das Anhängen der Preflight-Skripte hat C übernommen (D38); dort bleibt die Installationsanweisung.
  • Verifiziert:
    • pytest in tools/ 1918 grün, 3 übersprungen. Darin test_preflight.py 59 und test_preflight_pwsh.py 54 grün, mit lokalem pwsh 7.6.6.
    • docs verify, instructions verify und lint --fail-on-error grün.
    • Die sed-Ersetzung aus release.yml lokal mit dem herausgelösten Schnipsel nachgestellt.
    • CI-Lauf 480 grün.
    • Die neuen Assets hängen erst am nächsten Release ohne Suffix; Release-Lauf 481 hat die Beta übersprungen.

Akzeptanzkriterien

  • Mit einem PATH ohne rg endet tools/preflight.sh mit Exit 42 und einer MISSING rg-Zeile; mit vollständigem PATH endet es mit Exit 0 und schreibt .wikitool-tools.json mit absoluten Pfaden. (A: test_missing_rg_…, test_complete_path_…)
  • Dasselbe gilt für tools/preflight.ps1 unter pwsh 7 (Linux-CI). (B: test_preflight_pwsh.py, Job pwsh)
  • Liegt vor der echten Python ein Stub unter …/WindowsApps/python3, schreibt der Preflight den Pfad der echten Python (sys.executable) und führt den Stub nie aus. sh ✔ (test_store_alias_…, Linux- und Windows-Reihenfolge); pwsh ✔ (B).
  • Jede Exit-42-Ausgabe enthält den Anleitungsblock, ein Test je Stoppfall. sh ✔ und pwsh ✔ für fehlendes Tool, zu alte Version, ungültiger --set-Pfad, Ordnerlänge, venv, pip, Markierung, Gruppenrichtlinie; C ✔ für fehlendes curl/tar/sha256sum (sh) und Ordnerlänge am Asset-Ziel (beide).
  • Bei simuliertem LongPathsEnabled = 0 ergibt ein Installationsordner mit 96 Einheiten Exit 42, mit 95 geht es, mit LongPathsEnabled = 1 auch 96; doctor meldet den 96er-Fall als FAIL. sh, pwsh und doctor ✔; C ✔: im Asset-Modus wird bei 96 nichts entpackt (beide Skripte).
  • --set rg=<pfad> mit nicht existierendem Pfad: Exit 42, nichts geschrieben. Mit gültigem Pfad: der Pfad steht in der Datei und bleibt beim nächsten Lauf.
  • Nach einem erfolgreichen Preflight im Baum-Modus existiert tools/.venv; ein zweiter Lauf ändert nichts und endet mit Exit 0 (D34). (Test + CI-Doppellauf, sh und pwsh)
  • Der Download-Schritt bricht bei falscher sha256 mit Exit 1 ab und hinterlässt kein entpacktes Verzeichnis. (C, beide Skripte)
  • Der Asset-Modus ruft nach dem Entpacken die Kopie des Preflights im entpackten Baum auf; das Manifest wird nur dort gelesen (D33) – vor dem Entpacken nur die Ordnergrenze aus dem Archiv. (C)
  • Standardziel ist <Ordner des Skripts>/chemenu; --into überschreibt es; ein vorhandenes Ziel wird mit Exit 1 verweigert, ohne etwas zu entpacken (D40). (C; auf dem Zielsystem bestätigt)
  • --archive <pfad> installiert aus einem lokalen Tarball mit .sha256 daneben; ohne .sha256 Exit 1 (D41). (C; auf dem Zielsystem bestätigt)
  • Eine Kopie mit leeren URL-Platzhaltern endet im Asset-Modus ohne --archive mit Exit 1 und sagt, dass sie nicht aus einem Release stammt; release.yml hängt preflight.sh und preflight.ps1 mit eingetragenen URLs an, ein Test hält Platzhalter und Workflow zusammen (D38, D39). (C; der erste echte Upload kommt mit dem nächsten Release ohne Suffix)
  • tools/wikitool ohne .wikitool-tools.json oder ohne venv endet mit Exit 42, nennt den Preflight und druckt keinen Traceback. sh ✔ (auch bei complete: false); wikitool.ps1 ✔ (B).
  • Im Repo gibt es tools/wikitool und tools/wikitool.ps1, aber kein tools/wikitool.cmd. (test_there_is_a_powershell_launcher_and_no_cmd)
  • wikitool startet git und rg über die Pfade aus .wikitool-tools.json (test_git_and_rg_start_from_the_recorded_paths_not_from_path, PATH leer).
  • .wikitool-tools.json ist gitignored; doctor meldet einen verschwundenen Pfad als FAIL.
  • Alle vier Workflows und das CI-Replay richten ihre Umgebung per Preflight ein (D35); upgrade-instance.md und die Abschlussmeldung von dist upgrade nennen den Preflight. CI-Lauf 469 grün, einschließlich der Exit-42-Verweigerung im Replay.
  • Der CHANGES.md-Eintrag des Kandidaten trägt den --breaking-Satz aus D35.
  • Keine Hook-Konfiguration ruft trace_ingest.py per Shebang oder mit bloßem python/python3 auf; tools/trace-hook startet es mit beiden venv-Layouts und bleibt ohne venv still (D36). (Was Copilot unter Windows davon tatsächlich ausführt, korrigiert #164.)
  • PSScriptAnalyzer meldet im CI nichts; der Job läuft im Image chemenu-ci-pwsh (D37). (B, Lauf 476; nach C wieder grün in Lauf 480; die Regel PSAvoidUsingPositionalParameters ist im Workflow ausgenommen und dort begründet)
  • instructions/bug-report.md verweist auf die Preflight-Ausgabe, und die Windows-Startlogik sowie die Pfadprüfung von tools/bugreport.py stimmen mit dem gebauten Launcher und .wikitool-tools.json überein. (B)
  • Auf dem Windows-Zielsystem (von Hand, bis ein Runner existiert; Ergebnisse oben):
    • Der Preflight meldet ein fehlendes Tool; der Nutzer installiert es per choco; der erneute Preflight in derselben Harness-Sitzung findet es. (Einschränkung zum Registry-PATH siehe oben)
    • Ein per Browser geladenes, markiertes wikitool.ps1 meldet der Preflight mit Exit 42 samt Anleitung.
    • tools/wikitool doctor gibt in pwsh (Copilot) und in Git Bash (Claude Code) Ausgabe aus, statt still zu enden.
    • Aus Git Bash: reg query liefert LongPathsEnabled, und aufgezeichnete Windows-Pfade (C:\…\python.exe) werden als ausführbar erkannt.
    • preflight.ps1 erkennt die Execution Policy Restricted als Stoppfall, und doctor meldet dasselbe. Die Gruppenrichtlinie ist auf dem Zielsystem nicht geprüft; der Betreiber nimmt an, dass sie sich analog verhält.
    • Asset-Modus per --archive aus pwsh und aus Git Bash: Installation neben dem Skript bzw. per --into, vorhandenes Ziel mit Exit 1, zu langer --into mit Exit 42 ohne Entpacken, keine Markierung im entpackten Baum.
    • Nach dem nächsten Release ohne Suffix: das Asset preflight.ps1 aus pwsh und preflight.sh aus Git Bash von der Release-Seite laden und ohne --archive ausführen. Beide laden den Tarball selbst, prüfen die sha256 und installieren in chemenu/ neben sich.

Abhängigkeiten

Keine offenen. Das Pfadbudget aus #163 ist im Baum (titles.PATH_BUDGET); die Summenprüfung liest es. #152 fasst dieselben subprocess-Aufrufstellen an (siehe .wikitool-tools.json). #153 Punkt 5 teilt sich mit C: das Anhängen der Preflight-Skripte hat C gemacht (D38), die Installationsanweisung bleibt in #153. Der letzte offene Punkt wartet auf ein Release ohne Suffix, also auf die Freigabe von 8.0.0 (#140).

Version

Landet im 8.0.0-Kandidaten (#140 D19).

  • Abschnitt A hat --major gebumpt (8.0.0-beta.14) und den --breaking-Text des Kandidaten ergänzt; eskaliert hat damit nichts.
  • B hat --minor gebumpt (8.0.0-beta.15), C ebenfalls (8.0.0-beta.16).
  • Der PSScriptAnalyzer-Nachzug ist ein --patch (8.0.0-beta.17).
Teilpaket von #140 (Installation neu schneiden, Windows nativ). Die Entscheidungen dazu sind getroffen: **D13** (Ort der Regel), **D14** (`.wikitool-tools.json` auf allen Plattformen), **D15** (Launcher-Satz), **D16** (Mark of the Web, mit Anleitung für den Nutzer) und **D27** (Release-Download beim Erstinstall) am 2026-09-28, **D32 Teil 2** (Ordnerlänge) am 2026-09-30, **D33–D37** (aus der Vorbereitung) am 2026-09-30, **D38–D41** (für Abschnitt C) am 2026-10-01. Die Prüfpunkte T1, T2 und T4–T8 aus #140 sind beantwortet (2026-09-30) und unten eingearbeitet. **Stand 2026-10-01:** Alle drei Abschnitte sind publiziert. - A (sh-Hälfte, Baum-Modus): `e4b2b6d`, Kandidat **8.0.0-beta.14**, CI-Lauf 469 grün. - B (pwsh-Hälfte, Baum-Modus): `210e0c8`, Kandidat **8.0.0-beta.15** (Image `chemenu-ci-pwsh` in `4035b1b`), CI-Lauf 476 grün, Release-Lauf 477 grün. - C (Asset-Modus, beide Plattformen): `c33e8cd` (8.0.0-beta.16) und der Nachzug `d6e973c` (8.0.0-beta.17). CI-Lauf 480 (`verify` + `pwsh`) und Release-Lauf 481 sind grün. **Die Handprüfung auf dem Windows-Zielsystem ist gelaufen** (Betreiber, 2026-10-01, Stand 8.0.0-beta.17), siehe [Handprüfung](#handprüfung-auf-dem-windows-zielsystem-2026-10-01). Alles, was #151 selbst verspricht, hat gehalten. Offen ist nur noch ein Punkt: der Asset-Weg aus einem **echten** Release. Er ist erst nach dem nächsten Release ohne Suffix möglich. Zwei Nebenbefunde gehören nicht zu #151 und stehen in eigenen Paketen: - #164: Die Copilot-Hooks öffnen unter Windows den Dialog „App auswählen“. - #152: Die Ausgabe kommt in den Harnesses falsch kodiert an. ## Warum Im analysierten Installationslauf (#140) fehlte zu Beginn Python im Terminal, später `rg`. Der Agent ist ausgewichen – nach WSL, mit einem lokalen Patch, mit Handarbeit an Git-Konfiguration und Push – statt anzuhalten. Die Regel dagegen (Betreiber, 2026-09-27): > Die nötigen Tools werden früh per möglichst einfacher Shell auf Existenz geprüft. Fehlt etwas, hält der Agent an, meldet was fehlt und gibt dem Nutzer Gelegenheit, Abhängigkeiten zu installieren und Pfade anzugeben – in einer Schleife, bis alle Tools erreichbar sind. Pfade werden in einer Konfigurationsdatei festgehalten. Der Agent installiert nie selbst, auch nicht mit Zustimmung (#140 D6). Die Prüfung kann kein `wikitool`-Befehl sein: ohne Python startet `wikitool` nicht. ## Entscheidungen aus der Vorbereitung (Betreiber, 2026-09-30) Beim Abgleich mit dem Baum aufgefallen, jeweils mit der Empfehlung entschieden. Nummern fortlaufend zu #140. ### D33 – Preflight in zwei Modi; das Manifest steht nur im Baum **Befund:** Nach D5/D27 ist der Preflight ein Release-Asset und läuft, bevor es einen Baum gibt. `tools/prerequisites.txt` und das Ziel für `.wikitool-tools.json` gibt es dann noch nicht. **Entschieden:** ein Skript je Plattform mit zwei Modi. Welcher gilt, entscheidet, ob neben dem Skript ein Stack-Baum liegt. - **Asset-Modus** (Erstinstall): Ordnerlänge prüfen → Release laden, sha256 prüfen, entpacken → die mitgelieferte Kopie `tools/preflight.*` im entpackten Baum aufrufen. - **Baum-Modus** (nach dem Entpacken, Klon, Handweg, nach `dist upgrade`): Markierung → Tools nach Manifest → `.wikitool-tools.json` → venv (D34). Die Reihenfolge weicht damit von D27 ab: Geladen wird **vor** der Tool-Prüfung. Fehlt Python, liegt schon ein entpackter Baum da, und die Schleife läuft dort weiter. Der sh-Asset-Modus braucht `curl`, `tar` und `sha256sum` oder `shasum`. Fehlt eins, gibt es Exit 42 mit Anleitung. Unter pwsh reichen Bordmittel (`Invoke-WebRequest`, `Get-FileHash`, `tar.exe`). Die Ordnergrenze 95 steht im Manifest (`limit|install_dir_max|95`). Im Asset-Modus liegt das Manifest vor dem Entpacken noch nicht auf der Platte. Es wird nach der sha256-Prüfung per `tar -xOzf <archiv> <oberster>/tools/prerequisites.txt` aus dem Archiv gelesen; das geht mit GNU tar wie mit `tar.exe`. So bleibt die Zahl an einer Stelle, und die Prüfung liegt trotzdem vor dem Entpacken. Verworfen: das Manifest in beide Skripte einbetten. Das hätte drei Kopien der Liste und eine weitere generierte Region gekostet. ### D34 – Der Preflight legt das venv an **Befund:** Der Launcher schickt einen ohne venv zum Preflight, der Entwurf ließ den Preflight aber kein venv anlegen. So hätte die Schleife nie geendet. **Entschieden:** Der Preflight legt im Baum-Modus als letzten Schritt `tools/.venv` an: `<python> -m venv`, dann `<venv-python> -m pip install -r tools/requirements.txt`. Das läuft idempotent bei jedem Lauf und bringt damit nach `dist upgrade` auch geänderte Requirements nach. Mit D6 ist das vereinbar: Alles bleibt im Installationsordner, am System ändert sich nichts. Ein Fehler bei venv oder pip (kein Netz, Proxy, ASR) ist ein Stoppfall mit Anleitung. Verworfen: den venv-Schritt in den Anleitungen belassen. Das hätte die Shell-Befehle zurückgebracht, die #153 Punkt 6 entfernt. ### D35 – Der Bruch wird angenommen und in 8.0.0 gebündelt **Befund:** Mit „ohne `.wikitool-tools.json` Exit 42“ startet nach dem Update auf 8.0.0 bei keiner bestehenden Instanz `wikitool`, bis einmal der Preflight gelaufen ist. Das betrifft auch den Entwicklungs-Checkout, alle vier Workflows (`ci`, `release`, `nightly`, `tracker-live`) und das CI-Replay. Nach dem Drop-in-Test ist das ein Bruch. **Entschieden:** Der Bruch wird angenommen. Der Kandidat ist schon major, die Instanzen zahlen also nur einmal. - `version bump --major --breaking "…"` - Die Workflows rufen im selben Abschnitt den Preflight statt ihres venv-Blocks auf. - `upgrade-instance.md` bekommt den Preflight als Schritt vor `instructions sync`, und die Abschlussmeldung von `dist upgrade` nennt ihn. Verworfen: ein Shim mit PATH-Rückfall. Er hätte genau das Überspringen erlaubt, das die Regel verhindern soll. ### D36 – Hooks starten über die venv-Python **Befund:** Hook-Befehle sind statische Strings in `.claude/settings.json`, `.github/hooks/wiki-trace.json` und `.vibe/hooks.toml`. Sie können `.wikitool-tools.json` nicht lesen, und Claude Code hat einen einzigen Befehlsstring für Linux, macOS und Git Bash unter Windows. **Entschieden:** Die Hooks starten `trace_ingest.py` (nur Standardbibliothek) mit der venv-Python. Sie stammt aus der festgelegten Python und liegt an einem festen Ort. - Ein kleines sh-Skript `tools/trace-hook` wählt das Layout (`.venv/bin/python` oder `.venv/Scripts/python.exe`). Claude Code, Vibe und Copilots `bash`-Zweig rufen es auf. - Copilots `powershell`-Zweig ruft `.\tools\.venv\Scripts\python.exe` direkt auf. - Ohne venv bleibt der Hook still wie heute (`|| true`). Damit braucht kein Hook einen JSON-Parser, und keiner hängt an der Execution Policy. #82 (Tool-Hooks auf Claude Code) baut danach auf `tools/trace-hook` auf. **Nachtrag (Handprüfung 2026-10-01):** Unter Windows führt Copilot den `bash`-Zweig aus. Windows versucht dann, `./tools/trace-hook` über eine Dateizuordnung zu öffnen, und fragt nach einer App. Die Annahme „Copilot nimmt unter Windows den `powershell`-Zweig“ hält also für mindestens einen Client nicht. Die Korrektur ist #164. Verworfen: die JSON-Datei in sh lesen. Das wäre aufwendiger gewesen, ohne etwas zu gewinnen. ### D37 – pwsh im CI über ein vorgebautes Image **Befund:** `debian:trixie-slim` hat pwsh nicht in seinen Paketquellen, und PSScriptAnalyzer kommt aus der PowerShell Gallery. Ob der Runner github.com und die Gallery erreicht, ist nicht geprüft. `dash` ist unkritisch, er ist dort `/bin/sh`. **Entschieden:** ein Image `gitea.nehmer.net/torben/chemenu-ci-pwsh` (trixie-slim + pwsh + PSScriptAnalyzer), gebaut nach dem Muster von `chemenu-sp-live` (#156). Ein eigener Job in `ci.yml` nutzt es. **Handschritt Betreiber:** Nach dem ersten Push das Paket in der Gitea-Oberfläche mit dem Repo verknüpfen; der Job wartet so lange darauf. **Erledigt (2026-10-01).** Verworfen: pwsh und PSScriptAnalyzer bei jedem Lauf installieren. Dann hinge jeder CI-Lauf an zwei externen Quellen. ## Entscheidungen für Abschnitt C (Betreiber, 2026-10-01) Vor C geklärt, jeweils mit der Empfehlung entschieden. Ausgangslage: #140 D5 legt die Preflight-Skripte als Release-Assets neben den Tarball, nennt aber weder Asset-Namen noch Zielordner. `release.yml` hängte bis dahin nur Tarball und `.sha256` an. Für Gitea ist keine stabile Download-URL „neuestes Asset“ belegt, nur die API `…/releases/latest`. ### D38 – C hängt die Preflight-Skripte ans Release **Entschieden:** `release.yml` hängt zusätzlich `preflight.sh` und `preflight.ps1` an, unter genau diesen Namen. Von #153 Punkt 5 bleibt dort nur die Installationsanweisung als Asset. **Warum:** Ohne Asset ruft den Asset-Modus in der Praxis niemand auf. Die Änderung sind zwei Einträge in der bestehenden Upload-Schleife. Verworfen: alles Anhängen in #153 belassen und C nur lokal testen. ### D39 – Das Asset-Skript kennt sein eigenes Release **Entschieden:** `release.yml` schreibt beim Anhängen die URLs von Tarball und `.sha256` **desselben** Releases in die Asset-Kopie (Platzhalter im Skript). Das Skript lädt immer genau das Release, zu dem es gehört. Die Kopie im Baum hat leere Platzhalter; ohne eingetragene URL und ohne `--archive` (D41) endet der Asset-Modus mit Exit 1 und dem Hinweis, dass diese Kopie nicht aus einem Release stammt. **Warum:** Kein JSON-Parsen in sh. Die URLs setzt der Workflow ein, der sie kennt, nicht das Skript. Welches Release das neueste ist, klärt der Agent beim Laden des Skripts (#153, Installationssatz). Verworfen: das Skript fragt selbst `releases/latest` ab. Unter pwsh ginge das sauber, unter sh nur per sed über JSON, und das ist fragil. ### D40 – Zielordner `chemenu` neben dem Skript, `--into` überschreibt **Entschieden:** Standardziel ist `<Ordner des Skripts>/chemenu`, mit `--into <pfad>` überschreibbar. Ablauf: - die Ordnerlänge (Grenze aus dem Manifest im Archiv, D33) wird am **endgültigen** Zielpfad geprüft, vor dem Entpacken; - entpackt wird in einen temporären Nachbarordner; - geprüft wird, dass das Archiv genau einen obersten Ordner hat, wie `_extract_single_top_level_dir` in `dist_cmd.py`; - danach wird umbenannt. Ein schon vorhandenes Ziel wird verweigert. **Warum:** Ein Ordnername mit Version (`chemenu-stack-<version>`) führt nach dem ersten `dist upgrade` in die Irre, weil der Ordner bleibt und die Version wechselt. Verworfen: wie Weg A in INSTALL.md nach `chemenu-stack-<version>/` entpacken. ### D41 – `--archive <pfad>` für ein lokales Archiv **Entschieden:** `--archive <pfad>` nimmt einen schon vorhandenen Tarball; `<pfad>.sha256` muss daneben liegen. Die sha256-Prüfung läuft genauso wie beim Download. **Warum:** Das ist ein echter Weg für Rechner ohne direkten Download (Proxy, offline) und zugleich der Test-Einstieg auf beiden Plattformen. `Invoke-WebRequest` kann kein `file://`; Tests über eine Netz-URL bräuchten also einen Server. Verworfen: nur eine Testvariable statt einer Option. ## Was das Zielsystem gezeigt hat (T-Ergebnisse, #140, 2026-09-30) | Prüfpunkt | Ergebnis | Folge für dieses Paket | |---|---|---| | T1 | pwsh 7 löst `tools/wikitool` zuerst auf `.ps1` auf, dann `.cmd`, zuletzt die Datei ohne Endung. Git Bash führt die Datei ohne Endung aus. | `wikitool.ps1` + `wikitool` (sh) genügen. **Kein `.cmd`.** Am 2026-10-01 bestätigt: `tools/wikitool doctor` startet in pwsh `wikitool.ps1`. | | T10/T9 | Allein die Datei ohne Endung ist in pwsh ein stiller No-Op: `tools/wikitool doctor` gibt nichts aus und endet ohne Fehler. | Das war der „Hänger“. `wikitool.ps1` ist Pflicht, nicht Komfort. | | T4 | Copilot in VS Code und Copilot CLI laufen in pwsh 7.6.6. Claude Code läuft in Git Bash (MINGW64); dort ist `python` = `C:\Python314\python`, **`python3` = Store-Alias**. | Unter Windows darf der sh-Preflight nicht `python3` zuerst nehmen. Der Claude-Code-Hook (`python3`-Shebang) lief dort nachweislich ins Leere (behoben mit D36). | | T5 | `python.exe` und `python3.exe` gibt es als Store-Aliase unter `WindowsApps`, dazu `C:\Windows\py.exe`. Punkt 1 (veralteter PATH) wurde nicht nachgestellt. | Store-Alias verwerfen, Kandidaten durch Ausführen prüfen. Registry-PATH bleibt als billige Absicherung. | | T2 | `pip.exe` blockiert Defender ASR. Der Betreiber lässt es freischalten und arbeitet unter dieser Annahme. | Keine ASR-Erkennung. `-m pip` bleibt, damit der Stack die Freischaltung gar nicht braucht. | | T6 | `LocalMachine = RemoteSigned`, keine Gruppenrichtlinie. | Der prozessweite Bypass (D16) trägt. Eine Gruppenrichtlinie bleibt ein Stoppfall. | | T7 | `Invoke-WebRequest` setzt keine Markierung, der Browser schon; `tar -xf` gibt sie nicht weiter. | Der Download nach D27 (IWR + `tar`) erzeugt keine Markierung. Die MotW-Prüfung schützt nur noch den Handweg (Browser plus Entpacken im Explorer). Am 2026-10-01 bestätigt: Nach `--archive` trägt kein entpacktes Skript eine Markierung. | | T8 | `LongPathsEnabled = 0`, `core.longpaths` nicht gesetzt. | Prüfung der Ordnerlänge (D32 Teil 2, unten). Die Pfade im Repo begrenzt #163. | ## Gebaut Was mit Abschnitt A gebaut ist, ist mit **(A ✔)** markiert, was mit B gebaut ist, mit **(B ✔)**, was mit C gebaut ist, mit **(C ✔)**. - **Manifest** `tools/prerequisites.txt` **(A ✔)** – `|`-getrennte Zeilen, damit sh, pwsh und Python es ohne Parser lesen: `limit|install_dir_max|95` und je Tool `tool|name|min|all/windows|Label|Warum|choco|winget|brew|apt|pacman`. Inhalt: python ≥ 3.11, git, rg; unter Windows zusätzlich pwsh ≥ 7. Die Execution Policy (#140 D8) prüft nur der pwsh-Preflight (B ✔) und steht nicht im Manifest. Python liest es über `chemenu/prerequisites.py`. - **`tools/preflight.sh`** in POSIX-sh **(A ✔ Baum-Modus, C ✔ Asset-Modus)**. Läuft auch unter Git Bash – dort führt Claude Code unter Windows seine Befehle aus (T4); Pfade werden dort per `cygpath -w` in native Windows-Form gebracht. Die Markierungsprüfung macht nur der pwsh-Preflight. - **`tools/preflight.ps1`** mit `#Requires -Version 7` **(B ✔ Baum-Modus, C ✔ Asset-Modus)**. Windows PowerShell 5.1 wird nicht unterstützt (#140 D8); `#Requires` liefert dort eine klare Absage. Schreibt byteidentisches JSON zu `preflight.sh` (CI vergleicht per `cmp`). - **Zwei Modi je Skript (D33; C ✔):** Welcher gilt, entscheidet allein, ob `tools/prerequisites.txt` neben dem Skript liegt. Im Baum-Modus werden `--into`/`--archive` mit Exit 1 abgelehnt („belong to the release asset“). - **Start des pwsh-Preflights immer per `pwsh -NoProfile -ExecutionPolicy Bypass -File tools/preflight.ps1`** (D16; B ✔). Das gilt nur für diesen einen Prozess und ändert keine Einstellung. Nötig ist es, weil unter `RemoteSigned` ein markierter Preflight sonst gar nicht startet und seine eigene Markierung nicht melden kann. Auf dem Zielsystem bestätigt: `.\tools\preflight.ps1` ohne Präfix scheitert in einem markierten Checkout mit der PowerShell-Meldung „nicht digital signiert“, ohne Anleitung. - **Unter Windows vor der Suche PATH aus der Registry neu lesen** (Machine + User; B ✔). Sonst sieht eine laufende Harness-Sitzung ein frisch per Chocolatey installiertes Tool womöglich nie, und die Schleife endet nicht (Lauf in #140, Punkt 1). - **Python-Kandidaten, geschärft nach T4/T5 (A ✔ für sh, B ✔ für pwsh):** - Reihenfolge unter Windows (pwsh und Git Bash): `python`, `py -3`, `python3`. Sonst: `python3`, `python`. - Jeder Pfad unter `…\Microsoft\WindowsApps\` wird verworfen, ohne ihn auszuführen – der Store-Alias kann einen Store-Dialog öffnen. Gesucht wird über alle PATH-Einträge, nicht nur den ersten Treffer. - Ein Kandidat gilt erst, wenn `<kandidat> -c "import sys; print(…version_info[:2]…, sys.executable)"` mit Exit 0 läuft. - **In `.wikitool-tools.json` steht `sys.executable`,** nicht der Aufrufname. Auf dem Zielsystem: `C:\Python314\python.exe`. - **Ausgabe (A ✔, B ✔):** eine Zeile je Tool – `OK`/`MISSING`/`TOO_OLD`, Tool, Version, Pfad. **Exit 0** = alles da. **Exit 42** = der Nutzer muss handeln. **Exit 1** = Aufruffehler, Download/Prüfsumme/Entpacken im Asset-Modus fehlgeschlagen, vorhandenes Ziel, oder unvollständiger Baum. - **Anleitung bei jedem Stopp (A ✔, B ✔, C ✔):** `STOP`-Kopf mit einer Zeile an den Agenten, dann nummerierte Blöcke mit `Why:`, `Fix:` (Befehl für den erkannten Paketmanager, sonst alle), `Next:`. Die Ausgabe ist englisch; `instructions/preflight.md` lässt den Agenten eine Übersetzung *darunter* setzen, nie statt ihrer. **Stoppfälle:** fehlendes Tool (A ✔, B ✔), zu alte Version (A ✔, B ✔), ungültiger `--set`-Pfad (A ✔, B ✔), Installationsordner zu lang (A ✔, B ✔), fehlgeschlagene venv- oder pip-Einrichtung (A ✔, B ✔), Markierung (B ✔), Execution Policy `Restricted`/`AllSigned`, bei Gruppenrichtlinie mit eigener Anleitung (B ✔), fehlendes Download- oder Entpack-Werkzeug im Asset-Modus – sh: `curl`, `tar`, `sha256sum`/`shasum`; pwsh: `tar` (C ✔), Ordnerlänge am Asset-Ziel (C ✔). - **`--set <tool>=<pfad>` (A ✔, B ✔; im Asset-Modus an den Baum durchgereicht, C ✔)** prüft einen vom Nutzer genannten Pfad und schreibt ihn. Ein ungültiger Pfad schreibt nichts. Ein gültiger bleibt bei späteren Läufen erhalten, weil der Preflight einen noch funktionierenden aufgezeichneten Pfad vor der PATH-Suche nimmt. - **Mark of the Web (D16, B ✔):** Der Preflight prüft die `*.ps1` unter `tools/` auf `Zone.Identifier` (ZoneId ≥ 3). Bei einem Fund hält er mit Exit 42 und der Anleitung (`Get-ChildItem -Recurse -File | Unblock-File`) an. Nach T7 tritt das nur auf dem Handweg auf. - **Execution Policy (B ✔):** wirksam ist der erste nicht undefinierte Scope aus MachinePolicy, UserPolicy, CurrentUser, LocalMachine (Process zählt nicht). `Restricted`/`AllSigned` ist ein Stoppfall; eine Gruppenrichtlinie bekommt „Admin fragen / Git Bash“, sonst `Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned`. Prüft der Preflight und `doctor`. - **Release-Download beim Erstinstall (D27, D33, D38–D41; C ✔):** - Der Preflight lädt im Asset-Modus das Release, zu dem er gehört (D39), und prüft die sha256. Ist sie falsch, endet er mit Exit 1, und nichts wird entpackt. - Er liest die Ordnergrenze per `tar -xOzf <archiv> <oberster>/tools/prerequisites.txt` aus dem Archiv und prüft den endgültigen Zielpfad (D40). - Er entpackt in den Nachbarordner `.chemenu-unpack.<pid>`, verlangt genau einen obersten Ordner und benennt um. - Danach ruft er die Kopie `tools/preflight.*` im neuen Baum auf. `--set` und der Exit-Code werden durchgereicht: unter sh per `exec`, unter pwsh per Kindprozess mit demselben Bypass. - Werkzeuge: unter pwsh `Invoke-WebRequest`, `Get-FileHash` und `tar.exe`; unter sh `curl`, `tar` und `sha256sum`/`shasum`. - Unter Git Bash werden `--archive`/`--into` per `cygpath -u` umgesetzt, weil GNU tar `C:` als Host liest. - `--archive` (D41) ersetzt den Download. - Asset-Namen wie in `version.py` (`chemenu-stack-<version>.tar.gz` + `.sha256`). - `release.yml` erzeugt die Asset-Kopien per `sed`, prüft per `grep -qF` beide URLs in beiden Kopien und lädt `preflight.sh`/`preflight.ps1` in derselben Schleife wie Tarball und `.sha256` hoch. - **Ordnerlänge (D32 Teil 2; A ✔ für sh und `doctor`, B ✔ für pwsh, C ✔ für den Asset-Modus):** - Unter Windows mit `LongPathsEnabled = 0` darf der Installationsordner – das Verzeichnis, das `tools/` enthält, als absoluter Windows-Pfad – höchstens **95** UTF-16-Einheiten lang sein. - `preflight.sh` fragt `LongPathsEnabled` per `reg query` ab (ein nicht lesbarer Schlüssel gilt als aus); `doctor` per `winreg`. Für Tests stehen `CHEMENU_PREFLIGHT_PLATFORM` und `CHEMENU_PREFLIGHT_LONGPATHS` bereit; B ergänzt `CHEMENU_PREFLIGHT_POLICY` und `CHEMENU_PREFLIGHT_MARKED`. - **Invariante:** 95 + 1 + 160 (`titles.PATH_BUDGET`, #163) ≤ 259. Die 95 steht nur im Manifest; `test_manifest_limit_and_path_budget_fit_max_path_together` hält die Summe. - **`.wikitool-tools.json` (D14; A ✔):** gitignored, pro Checkout, `{"schema": 1, "complete": true|false, "tools": {…}}`. `complete` wird erst nach dem venv-Schritt `true`. Nach einem Stopp stehen die gefundenen Tools mit `complete: false` in der Datei, damit `--set`-Werte die Schleife überleben. Deshalb verweigert der Launcher nach **jedem** Stopp des Preflights, auch nach einem wegen der Execution Policy, bis der Preflight wieder mit 0 endet. Auf dem Zielsystem so beobachtet. - `chemenu/toolpaths.py` löst die Pfade auf; gelesen wird neben `tools/` (`config._PACKAGE_ROOT`), nicht unter `CHEMENU_ROOT`. Alle Aufrufstellen gehen darüber: `git_publish._run` und der Scratch-Index-Lauf, `config.default_author`, `corpus_cache`, `dist_cmd`, `migrate_cmd` (2×), `doctor`, `docs_verify`, `search/ripgrep.build_argv`. `upstream_cmd.py` bleibt unberührt (entfällt mit #153). - Ohne Datei: Rückfall auf den bloßen Namen (Testsuite, direkter Modulaufruf; der Hermetik-Fixture zeigt jeden Test auf eine fehlende Datei). Datei da, aber Tool fehlt oder Pfad weg: `ToolPathError` (kein `OSError`), vom CLI als `ERROR`-Zeile mit Verweis auf den Preflight ausgegeben. - Dieselben Aufrufstellen fasst #152 an (`encoding="utf-8"`). Wer als Zweites landet, zieht nach. - **Launcher (D15):** - `tools/wikitool` (POSIX sh; A ✔): beide venv-Layouts, Exit 42 ohne vollständige Datei oder ohne venv, startet `tools/run_wikitool.py` statt `-m` mit `PYTHONPATH`. Der Name beginnt bewusst nicht mit `wikitool.` (PATHEXT/`.PY`). - `tools/wikitool.ps1` mit `#Requires -Version 7` (B ✔). **Kein `tools/wikitool.cmd`** (T1, T4). Die Meldungen von Launcher, `toolpaths.PREFLIGHT` und `doctor.PREFLIGHT_FIX` nennen auch den pwsh-Aufruf. - **venv und pip (D34; A ✔, B ✔):** immer `<python> -m venv --clear` (nur wenn das venv fehlt oder kein pip hat) und `<venv-python> -m pip install -r`. Ein Stempel `tools/.venv/.chemenu-requirements.sha256` überspringt pip, solange sich `requirements.txt` nicht geändert hat. - **Hooks (D36; A ✔, unter Windows mit Copilot fehlerhaft → #164):** `.claude/settings.json`, der `bash`-Zweig in `.github/hooks/wiki-trace.json` und `.vibe/hooks.toml` rufen `./tools/trace-hook` auf; Copilots `powershell`-Zweig `.\tools\.venv\Scripts\python.exe tools\trace_ingest.py`. EVALS.md beschreibt es. - **Bugreport-Sammler (Nachzug aus #157; B ✔):** - `instructions/bug-report.md` verweist darauf, dass die Preflight-Ausgabe der Bericht ist, wenn kein Python startet. - `tools/bugreport.py` startet `wikitool` unter Windows per `pwsh -NoProfile -ExecutionPolicy Bypass -File tools/wikitool.ps1` (`launcher_command`), abgeglichen mit dem gebauten Launcher. - Die Pfadprüfung (`_collect_tools_config`) ist gegen eine echte `schema: 1`-Datei getestet. - **Regel-Ort (D13; A ✔):** `instructions/preflight.md`; AGENTS.md § Bootstrap verweist darauf. Keine neue Invariante. Seit C mit einem Entscheidungspunkt für das Asset-Skript. - **`doctor`:** `tool-paths` und `install-dir` (A ✔); Execution Policy samt Gruppenrichtlinie und Mark of the Web an Stack-Skripten (B ✔). ## Test ohne Windows-Runner - `preflight.sh` läuft in `test_preflight.py` unter jeder vorhandenen Shell aus dash und bash, gegen einen PATH aus einzeln verlinkten Hilfsprogrammen plus Stubs. Die Stub-Python spielt auch `-m venv` und `-m pip`; kein Test legt ein echtes venv an oder braucht Netz. Der Store-Alias ist ein Stub unter `…/WindowsApps/`, der beim Ausführen eine Markerdatei schreibt. **(A ✔)** - Lokal (Arch) gibt es nur bash; zusätzlich geprüft unter `zsh --emulate sh` und in `debian:trixie-slim` per Docker unter dash und bash (52 Tests grün, dazu ein echter Preflight mit frischem venv). - Die Ordnerlänge wird an den Grenzwerten 95/96 gegen `LongPathsEnabled = 0/1` geprüft, im Preflight und in `doctor`. **(A ✔)** - CI: `ci.yml` richtet sich per Preflight ein, lässt ihn zweimal laufen und vergleicht die Datei; das Replay im exportierten Baum prüft zuerst, dass `tools/wikitool doctor` mit Exit 42 verweigert, dann den Preflight. **(A ✔, Lauf 469 grün)** - pwsh 7 im Image `chemenu-ci-pwsh` (D37) mit PSScriptAnalyzer **(B ✔, Lauf 476 grün)**: Job `pwsh` in `ci.yml` mit PSScriptAnalyzer (ohne `PSAvoidUsingPositionalParameters`, im Workflow begründet), `preflight.ps1` zweimal plus `cmp` gegen `preflight.sh`, `tools/wikitool version show` aus pwsh, und `test_preflight_pwsh.py`, `test_preflight.py`, `test_doctor.py`. - Asset-Modus **(C ✔)**: per `--archive` (D41) gegen einen im Test gebauten Tarball mit `.sha256`, auf beiden Plattformen. Abgedeckt sind: - Standardziel, `--into` (auch relativ) und ein vorhandenes Ziel; - falsche und fehlende `.sha256`, zwei oberste Ordner, leere Platzhalter; - fehlende Werkzeuge (Exit 42) und die Durchreichung von `--set` und Exit-Code; - die Ordnergrenze 95/96 sowie 110/121 bei einer Grenze von 120 aus dem Archiv. Der Download läuft unter sh gegen einen `curl`-Stub und unter pwsh gegen einen lokalen `ThreadingHTTPServer`, jeweils auch als fehlgeschlagener Download. `test_the_release_workflow_fills_exactly_the_placeholders_the_scripts_keep` leitet die `sed`-Ausdrücke aus den Platzhaltern ab und hält sie gegen `release.yml`. - `test_preflight_pwsh.py` wird ohne lokales pwsh **komplett übersprungen** (`pytestmark`). `instructions/dev/testing-conventions.md` sagt, wie man das erkennt und die Tests per Docker im Image `chemenu-ci-pwsh` laufen lässt. Für C liefen sie mit lokalem pwsh 7.6.6 (54 grün) und im CI-Job `pwsh`. Ein übersprungener pwsh-Test ist kein bestandener. - Ohne Windows-Runner (#140 T12) prüft das CI nichts davon auf Windows. Was nur dort prüfbar ist, hat der Betreiber am 2026-10-01 von Hand geprüft (nächster Abschnitt). Nach wie vor ungeprüft: - der echte Store-Alias; - der Registry-PATH an einem Tool, das einen **neuen** PATH-Eintrag anlegt; - die Gruppenrichtlinie auf dem Zielsystem; - der Download aus einem echten Release. ## Handprüfung auf dem Windows-Zielsystem (2026-10-01) Ausgeführt vom Betreiber auf Stand 8.0.0-beta.17 (Windows 11, pwsh 7.6.6, Git Bash, Python 3.14.7, `LongPathsEnabled = 0`, LocalMachine `RemoteSigned`). Für den Asset-Modus lag ein Tarball vor, den `dist export` auf dem Zielsystem gebaut hatte. | Prüfung | Ergebnis | |---|---| | `doctor` in pwsh (Copilot, auch direkt) und in Git Bash (Claude Code, auch direkt) | ✔ gibt Ausgabe. Ohne Preflight Exit 42 mit Verweis auf den Preflight, auch aus Copilot heraus. Der Agent hat angehalten und nachgefragt. | | `reg query` aus Git Bash | ✔ liefert `LongPathsEnabled = 0x0` | | Aufgezeichnete Windows-Pfade in Git Bash | ✔ zweiter `tools/preflight.sh`-Lauf mit Exit 0. `C:\Python314\python.exe`, `C:\Program Files\Git\cmd\git.exe`, `C:\ProgramData\chocolatey\bin\rg.exe` und `C:\Program Files\PowerShell\7\pwsh.exe` werden als ausführbar erkannt. | | Ordnerlänge 101 Zeichen (Klon) | ✔ Exit 42 mit Anleitung | | Fehlendes Tool | ✔ Nach `choco uninstall ripgrep` meldet der Preflight in Copilot Exit 42 mit `MISSING rg`. Der Agent installiert nichts. Nach `choco install ripgrep` endet der Preflight in derselben Sitzung mit 0. **Einschränkung:** Der choco-Shim-Ordner stand schon im PATH; das Neueinlesen aus der Registry war hier nicht nötig. | | Execution Policy `Restricted` (CurrentUser) | ✔ Der Preflight meldet Exit 42 mit `Set-ExecutionPolicy … RemoteSigned`, `doctor` (aus Git Bash) meldet `FAIL execution-policy`. | | Gruppenrichtlinie | nicht auf dem Zielsystem geprüft. Der Betreiber nimmt an, dass sie sich analog verhält; der Zweig ist per Testhook abgedeckt. | | Mark of the Web (main.zip per Browser, Entpacken im Explorer, `ZoneId=3`) | ✔ Exit 42, der Block nennt `wikitool.ps1` und die Zeile `Unblock-File`. Nach dem Ausführen dieser Zeile endet der Preflight mit 0. | | Asset-Modus pwsh | ✔ Mit leeren Platzhaltern Exit 1 („does not come from a release“). Mit `--archive` folgen `sha256 OK`, das Entpacken nach `chemenu\` neben dem Skript und der Baum-Preflight mit 0; dort keine Markierung. Ein zweiter Lauf endet mit Exit 1 „already exists“. Mit `--into` auf 103 Zeichen Exit 42, nichts entpackt. | | Asset-Modus Git Bash | ✔ `--archive` und `--into` in Windows-Form (`C:\…`) wie in POSIX-Form (`/c/…`), jeweils Exit 0 (`cygpath`) | **Befunde außerhalb von #151:** - Copilot öffnet bei Hook-Ereignissen den Dialog „App auswählen“ für `trace-hook` → #164. - `doctor` gibt `Fu�noten` aus, wenn die Ausgabe über die Harness läuft (Copilot und Claude Code); direkt in der Konsole stimmt sie → #152. - Unter Copilot warnt `session-id`, weil keine Harness-Variable gesetzt ist → gehört zu #153 (D26). - Einmal hat Copilot `.\tools\preflight.ps1` ohne den Bypass-Präfix gestartet und den Anleitungsblock übersetzt wiedergegeben, statt eine Übersetzung darunter zu setzen. `instructions/preflight.md` hatte er nicht gelesen, weil die Aufforderung direkt „führe tools/preflight aus“ lautete. Das ist ein Punkt für den Installationssatz in #153. ## Umsetzungsplan Drei Abschnitte mit je einem Publish und einem Bump auf dem 8.0.0-Kandidaten – alle erledigt. **A – sh-Hälfte, Baum-Modus** – **erledigt: `e4b2b6d`, 8.0.0-beta.14, CI-Lauf 469 grün (2026-10-01)** - `tools/prerequisites.txt`, `tools/preflight.sh`, `tools/wikitool`, `tools/run_wikitool.py`, `tools/trace-hook`, `chemenu/toolpaths.py`, `chemenu/prerequisites.py`; alle `git`/`rg`-Aufrufstellen; CLI-Behandlung von `ToolPathError`; `doctor` (`tool-paths`, `install-dir`); `.gitignore`. - Hooks (D36); Workflows `ci`, `release`, `nightly`, `tracker-live` und CI-Replay (D35). - `instructions/preflight.md` (neu), AGENTS.md § Bootstrap, `bootstrap.md`, `setup-instance.md` Schritt 7, `upgrade-instance.md` Schritt 8, Abschlussmeldung von `dist upgrade`. - Doku: README.md, tools/README.md, tools/CONTRACT.md (Setup + `doctor`-Record, regeneriert), INSTALL.md (Voraussetzungen, Weg C, § Konfiguration, Troubleshooting), EVALS.md (Hooks). - Entwicklungs-Checkout per Preflight eingerichtet. - Bump `--major --impact high` mit dem `--breaking`-Satz (D35), Changeset in CHANGES.md. - Verifiziert: pytest 1827 grün, `docs verify`, `instructions verify`, `lint --fail-on-error`, Replay des CI-Schritts gegen einen frischen `dist export`; danach CI 469 und Release-Workflow 470 (überspringt die Beta) grün. **B – pwsh-Hälfte, Baum-Modus** – **erledigt: Image `4035b1b`, Code `210e0c8`, 8.0.0-beta.15, CI-Lauf 476 (`verify` + `pwsh`) und Release-Lauf 477 grün (2026-10-01)** - `tools/preflight.ps1` (Registry-PATH, Python-Kandidaten, Markierung, Execution Policy samt Gruppenrichtlinie, Ordnerlänge), `tools/wikitool.ps1`. - Meldungen von Launcher, `toolpaths.PREFLIGHT`, `doctor.PREFLIGHT_FIX`, `cli.py`, `dist_cmd` und `instructions/preflight.md` nennen den pwsh-Aufruf. - `doctor`: `execution-policy` und `script-marks`. - CI-Image `chemenu-ci-pwsh` (`.gitea/pwsh-ci/Dockerfile`, `pwsh-ci-image.yml`) und -Job; Paket vom Betreiber verknüpft. - Bugreport-Nachzug: `bugreport.py` (`launcher_command`, echtes `schema: 1` im Test), `instructions/bug-report.md`. - Doku: preflight.md, bootstrap.md, setup-instance.md, upgrade-instance.md, bug-report.md, INSTALL.md, README.md, tools/README.md, tools/CONTRACT.md (regeneriert), `docs/why-gates-are-code.md`. - Bump `--minor`, Changeset in CHANGES.md. - Verifiziert: pytest in `tools/` 1841 grün (39 übersprungen); pwsh-Tests in Docker 159 grün; ps1- und sh-Preflight schreiben identisches JSON; `docs verify`, `instructions verify`, `lint --fail-on-error` grün; `dist export` liefert beide `.ps1`. **C – Asset-Modus (D27/D33, D38–D41), beide Plattformen** – **erledigt: `c33e8cd` (8.0.0-beta.16) und `d6e973c` (8.0.0-beta.17), CI-Lauf 480 (`verify` + `pwsh`) und Release-Lauf 481 grün (2026-10-01)** - `preflight.sh` und `preflight.ps1`: Asset-Modus, wenn kein Manifest daneben liegt. Optionen `--into <pfad>` (D40) und `--archive <pfad>` (D41); `--set` wird an die Kopie im Baum durchgereicht, ihr Exit-Code ebenso. - URL-Platzhalter `RELEASE_ARCHIVE_URL`/`RELEASE_CHECKSUM_URL` (sh) bzw. `$ReleaseArchiveUrl`/`$ReleaseChecksumUrl` (pwsh), leer im Baum (D39). - Laden, sha256, Ordnergrenze aus dem Archiv, Zielprüfung, Entpacken in einen temporären Nachbarordner, genau ein oberster Ordner, Umbenennen, Aufruf der Kopie im Baum. - Stoppfall „Download-/Entpack-Werkzeug fehlt“ (Exit 42 mit Anleitung). Falsche sha256, fehlgeschlagener Download und vorhandenes Ziel enden mit Exit 1, und nichts wird entpackt. - `release.yml`: `preflight.sh` und `preflight.ps1` mit eingetragenen URLs angehängt (D38, D39). Ein Test hält Platzhalter und Workflow zusammen. - Tests auf beiden Plattformen (siehe oben). - `instructions/dev/testing-conventions.md`: Entscheidungspunkt, dass `test_preflight_pwsh.py` ohne pwsh still übersprungen wird und wie die Tests dann per Docker laufen. - Doku: `instructions/preflight.md` (Entscheidungspunkt Asset-Skript, Exit-1-Zeile, Ordnerlänge im Asset-Modus), INSTALL.md (Weg A nennt den Preflight als Asset), tools/README.md, tools/CONTRACT.md (Setup-Absatz), README.md. - Bump `--minor` (8.0.0-beta.16), Changeset in CHANGES.md. - **Nachzug `d6e973c` (8.0.0-beta.17, `--patch`):** CI-Lauf 478 auf `c33e8cd` war im Job `pwsh` rot. PSScriptAnalyzer (`PSUseShouldProcessForStateChangingFunctions`) liest das Verb `Stop` in der Hilfsfunktion `Stop-Asset` als zustandsändernd. Sie heißt jetzt `Exit-Asset`, neben `Exit-WithGuide`; das Verhalten ist unverändert. Lokal per Docker im Image `chemenu-ci-pwsh` geprüft: 0 Funde. - #153 Punkt 5: das Anhängen der Preflight-Skripte hat C übernommen (D38); dort bleibt die Installationsanweisung. - Verifiziert: - pytest in `tools/` 1918 grün, 3 übersprungen. Darin `test_preflight.py` 59 und `test_preflight_pwsh.py` 54 grün, mit lokalem pwsh 7.6.6. - `docs verify`, `instructions verify` und `lint --fail-on-error` grün. - Die `sed`-Ersetzung aus `release.yml` lokal mit dem herausgelösten Schnipsel nachgestellt. - CI-Lauf 480 grün. - Die neuen Assets hängen erst am nächsten Release ohne Suffix; Release-Lauf 481 hat die Beta übersprungen. ## Akzeptanzkriterien - [x] Mit einem PATH ohne `rg` endet `tools/preflight.sh` mit Exit 42 und einer `MISSING rg`-Zeile; mit vollständigem PATH endet es mit Exit 0 und schreibt `.wikitool-tools.json` mit absoluten Pfaden. (A: `test_missing_rg_…`, `test_complete_path_…`) - [x] Dasselbe gilt für `tools/preflight.ps1` unter pwsh 7 (Linux-CI). (B: `test_preflight_pwsh.py`, Job `pwsh`) - [x] Liegt vor der echten Python ein Stub unter `…/WindowsApps/python3`, schreibt der Preflight den Pfad der echten Python (`sys.executable`) und führt den Stub nie aus. sh ✔ (`test_store_alias_…`, Linux- und Windows-Reihenfolge); pwsh ✔ (B). - [x] Jede Exit-42-Ausgabe enthält den Anleitungsblock, ein Test je Stoppfall. sh ✔ und pwsh ✔ für fehlendes Tool, zu alte Version, ungültiger `--set`-Pfad, Ordnerlänge, venv, pip, Markierung, Gruppenrichtlinie; C ✔ für fehlendes `curl`/`tar`/`sha256sum` (sh) und Ordnerlänge am Asset-Ziel (beide). - [x] Bei simuliertem `LongPathsEnabled = 0` ergibt ein Installationsordner mit 96 Einheiten Exit 42, mit 95 geht es, mit `LongPathsEnabled = 1` auch 96; `doctor` meldet den 96er-Fall als FAIL. sh, pwsh und `doctor` ✔; C ✔: im Asset-Modus wird bei 96 nichts entpackt (beide Skripte). - [x] `--set rg=<pfad>` mit nicht existierendem Pfad: Exit 42, nichts geschrieben. Mit gültigem Pfad: der Pfad steht in der Datei und bleibt beim nächsten Lauf. - [x] Nach einem erfolgreichen Preflight im Baum-Modus existiert `tools/.venv`; ein zweiter Lauf ändert nichts und endet mit Exit 0 (D34). (Test + CI-Doppellauf, sh und pwsh) - [x] Der Download-Schritt bricht bei falscher sha256 mit Exit 1 ab und hinterlässt kein entpacktes Verzeichnis. (C, beide Skripte) - [x] Der Asset-Modus ruft nach dem Entpacken die Kopie des Preflights im entpackten Baum auf; das Manifest wird nur dort gelesen (D33) – vor dem Entpacken nur die Ordnergrenze aus dem Archiv. (C) - [x] Standardziel ist `<Ordner des Skripts>/chemenu`; `--into` überschreibt es; ein vorhandenes Ziel wird mit Exit 1 verweigert, ohne etwas zu entpacken (D40). (C; auf dem Zielsystem bestätigt) - [x] `--archive <pfad>` installiert aus einem lokalen Tarball mit `.sha256` daneben; ohne `.sha256` Exit 1 (D41). (C; auf dem Zielsystem bestätigt) - [x] Eine Kopie mit leeren URL-Platzhaltern endet im Asset-Modus ohne `--archive` mit Exit 1 und sagt, dass sie nicht aus einem Release stammt; `release.yml` hängt `preflight.sh` und `preflight.ps1` mit eingetragenen URLs an, ein Test hält Platzhalter und Workflow zusammen (D38, D39). (C; der erste echte Upload kommt mit dem nächsten Release ohne Suffix) - [x] `tools/wikitool` ohne `.wikitool-tools.json` oder ohne venv endet mit Exit 42, nennt den Preflight und druckt keinen Traceback. sh ✔ (auch bei `complete: false`); `wikitool.ps1` ✔ (B). - [x] Im Repo gibt es `tools/wikitool` und `tools/wikitool.ps1`, aber kein `tools/wikitool.cmd`. (`test_there_is_a_powershell_launcher_and_no_cmd`) - [x] `wikitool` startet `git` und `rg` über die Pfade aus `.wikitool-tools.json` (`test_git_and_rg_start_from_the_recorded_paths_not_from_path`, PATH leer). - [x] `.wikitool-tools.json` ist gitignored; `doctor` meldet einen verschwundenen Pfad als FAIL. - [x] Alle vier Workflows und das CI-Replay richten ihre Umgebung per Preflight ein (D35); `upgrade-instance.md` und die Abschlussmeldung von `dist upgrade` nennen den Preflight. CI-Lauf 469 grün, einschließlich der Exit-42-Verweigerung im Replay. - [x] Der `CHANGES.md`-Eintrag des Kandidaten trägt den `--breaking`-Satz aus D35. - [x] Keine Hook-Konfiguration ruft `trace_ingest.py` per Shebang oder mit bloßem `python`/`python3` auf; `tools/trace-hook` startet es mit beiden venv-Layouts und bleibt ohne venv still (D36). (Was Copilot unter Windows davon tatsächlich ausführt, korrigiert #164.) - [x] PSScriptAnalyzer meldet im CI nichts; der Job läuft im Image `chemenu-ci-pwsh` (D37). (B, Lauf 476; nach C wieder grün in Lauf 480; die Regel `PSAvoidUsingPositionalParameters` ist im Workflow ausgenommen und dort begründet) - [x] `instructions/bug-report.md` verweist auf die Preflight-Ausgabe, und die Windows-Startlogik sowie die Pfadprüfung von `tools/bugreport.py` stimmen mit dem gebauten Launcher und `.wikitool-tools.json` überein. (B) - [ ] Auf dem Windows-Zielsystem (von Hand, bis ein Runner existiert; Ergebnisse oben): - [x] Der Preflight meldet ein fehlendes Tool; der Nutzer installiert es per choco; der erneute Preflight in derselben Harness-Sitzung findet es. (Einschränkung zum Registry-PATH siehe oben) - [x] Ein per Browser geladenes, markiertes `wikitool.ps1` meldet der Preflight mit Exit 42 samt Anleitung. - [x] `tools/wikitool doctor` gibt in pwsh (Copilot) und in Git Bash (Claude Code) Ausgabe aus, statt still zu enden. - [x] Aus Git Bash: `reg query` liefert `LongPathsEnabled`, und aufgezeichnete Windows-Pfade (`C:\…\python.exe`) werden als ausführbar erkannt. - [x] `preflight.ps1` erkennt die Execution Policy `Restricted` als Stoppfall, und `doctor` meldet dasselbe. Die Gruppenrichtlinie ist auf dem Zielsystem nicht geprüft; der Betreiber nimmt an, dass sie sich analog verhält. - [x] Asset-Modus per `--archive` aus pwsh und aus Git Bash: Installation neben dem Skript bzw. per `--into`, vorhandenes Ziel mit Exit 1, zu langer `--into` mit Exit 42 ohne Entpacken, keine Markierung im entpackten Baum. - [ ] Nach dem nächsten Release ohne Suffix: das Asset `preflight.ps1` aus pwsh und `preflight.sh` aus Git Bash von der Release-Seite laden und **ohne** `--archive` ausführen. Beide laden den Tarball selbst, prüfen die sha256 und installieren in `chemenu/` neben sich. ## Abhängigkeiten Keine offenen. Das Pfadbudget aus #163 ist im Baum (`titles.PATH_BUDGET`); die Summenprüfung liest es. #152 fasst dieselben `subprocess`-Aufrufstellen an (siehe `.wikitool-tools.json`). #153 Punkt 5 teilt sich mit C: das Anhängen der Preflight-Skripte hat C gemacht (D38), die Installationsanweisung bleibt in #153. Der letzte offene Punkt wartet auf ein Release ohne Suffix, also auf die Freigabe von 8.0.0 (#140). ## Version Landet im 8.0.0-Kandidaten (#140 D19). - Abschnitt A hat `--major` gebumpt (8.0.0-beta.14) und den `--breaking`-Text des Kandidaten ergänzt; eskaliert hat damit nichts. - B hat `--minor` gebumpt (8.0.0-beta.15), C ebenfalls (8.0.0-beta.16). - Der PSScriptAnalyzer-Nachzug ist ein `--patch` (8.0.0-beta.17).
torben added the prio/plannedsize/Larea/distributionkind/decision labels 2026-09-27 08:44:01 +00:00
torben added kind/build and removed kind/decision labels 2026-09-28 16:54:55 +00:00
Author
Owner

Changelog:

  • Entschieden (Betreiber, 2026-09-28): D13–D16 und D27. Darum kind/decision → kind/build.
  • Neu: Jede Exit-42-Ausgabe enthält eine Anleitung für den Menschen (Zusatz zu D16), dazu ein Akzeptanzkriterium.
  • Version: landet im 8.0.0-Kandidaten (D19).
  • Weiterhin offen: die Prüfpunkte T1, T2 und T4–T8 auf dem Windows-Zielsystem.
**Changelog:** - **Entschieden (Betreiber, 2026-09-28):** D13–D16 und D27. Darum `kind/decision` → `kind/build`. - **Neu:** Jede Exit-42-Ausgabe enthält eine Anleitung für den Menschen (Zusatz zu D16), dazu ein Akzeptanzkriterium. - **Version:** landet im 8.0.0-Kandidaten (D19). - **Weiterhin offen:** die Prüfpunkte T1, T2 und T4–T8 auf dem Windows-Zielsystem.
Author
Owner

Changelog: Neu ist der Nachzug aus #157 (Betreiber, 2026-09-30): ein Entwurfspunkt „Bugreport-Sammler“ und ein Akzeptanzkriterium. Es geht um den Verweis auf die Preflight-Ausgabe in instructions/bug-report.md und um den Abgleich der Windows-Startlogik und Pfadprüfung von tools/bugreport.py mit dem gebauten Launcher und .wikitool-tools.json. Sonst ist nichts geändert.

**Changelog:** Neu ist der Nachzug aus #157 (Betreiber, 2026-09-30): ein Entwurfspunkt „Bugreport-Sammler“ und ein Akzeptanzkriterium. Es geht um den Verweis auf die Preflight-Ausgabe in `instructions/bug-report.md` und um den Abgleich der Windows-Startlogik und Pfadprüfung von `tools/bugreport.py` mit dem gebauten Launcher und `.wikitool-tools.json`. Sonst ist nichts geändert.
Author
Owner

Changelog: T1, T2 und T4–T8 aus #140 eingearbeitet (2026-09-30). Neuer Abschnitt mit einer Tabelle der Ergebnisse. Dazu:

  • Launcher: kein .cmd (T1); wikitool.ps1 ist Pflicht, weil die Datei ohne Endung in pwsh still nichts tut (T10).
  • Python-Wahl: Unter Windows gilt die Reihenfolge python, py -3, python3. WindowsApps-Pfade werden ohne Ausführung verworfen, und in der Datei steht sys.executable (T4/T5). Dazu ein neues Kriterium mit einem Store-Alias-Stub.
  • Stoppfälle vollständig aufgezählt; neu sind Gruppenrichtlinie (T6) und Ordnerlänge (D32).
  • MotW: Auf dem Weg nach D27 entsteht keine Markierung (T7); die Prüfung schützt nur noch den Handweg.
  • Ordnerlänge als Entwurfspunkt, wartet auf D32.
  • ASR (T2): keine Erkennung; -m pip macht die Freischaltung für den Stack überflüssig.
  • #157 ist geschlossen: Der Nachzug gilt jetzt unbedingt.
  • Handkriterium: doctor muss in pwsh und in Git Bash Ausgabe liefern.
**Changelog:** T1, T2 und T4–T8 aus #140 eingearbeitet (2026-09-30). Neuer Abschnitt mit einer Tabelle der Ergebnisse. Dazu: - **Launcher:** kein `.cmd` (T1); `wikitool.ps1` ist Pflicht, weil die Datei ohne Endung in pwsh still nichts tut (T10). - **Python-Wahl:** Unter Windows gilt die Reihenfolge `python`, `py -3`, `python3`. `WindowsApps`-Pfade werden ohne Ausführung verworfen, und in der Datei steht `sys.executable` (T4/T5). Dazu ein neues Kriterium mit einem Store-Alias-Stub. - **Stoppfälle** vollständig aufgezählt; neu sind Gruppenrichtlinie (T6) und Ordnerlänge (D32). - **MotW:** Auf dem Weg nach D27 entsteht keine Markierung (T7); die Prüfung schützt nur noch den Handweg. - **Ordnerlänge** als Entwurfspunkt, wartet auf D32. - **ASR (T2):** keine Erkennung; `-m pip` macht die Freischaltung für den Stack überflüssig. - **#157** ist geschlossen: Der Nachzug gilt jetzt unbedingt. - **Handkriterium:** `doctor` muss in pwsh und in Git Bash Ausgabe liefern.
Author
Owner

Changelog: D32 Teil 2 entschieden (2026-09-30). Die Prüfung der Ordnerlänge ist jetzt fest spezifiziert:

  • höchstens 95 UTF-16-Einheiten, nur bei LongPathsEnabled = 0
  • vor dem Entpacken, auch in doctor
  • mit der Invariante zu #163

Neu sind ein CI-Test und ein Kriterium an den Grenzwerten 95 und 96. Die Abhängigkeit auf D32 ist aufgelöst; das Paket ist vollständig startbar.

**Changelog:** D32 Teil 2 entschieden (2026-09-30). Die Prüfung der Ordnerlänge ist jetzt fest spezifiziert: - höchstens 95 UTF-16-Einheiten, nur bei `LongPathsEnabled = 0` - vor dem Entpacken, auch in `doctor` - mit der Invariante zu #163 Neu sind ein CI-Test und ein Kriterium an den Grenzwerten 95 und 96. Die Abhängigkeit auf D32 ist aufgelöst; das Paket ist vollständig startbar.
torben added kind/decision and removed kind/build labels 2026-09-30 21:30:13 +00:00
Author
Owner

Changelog: Vorbereitung zur Umsetzung (2026-09-30, Claude Code/Opus 5.5). Beim Abgleich mit dem Baum sind fünf Lücken aufgefallen, die neu als offene Entscheidungen D33–D37 im Body stehen:

  • D33: Asset-Modus vs. Manifest im Baum
  • D34: Wer legt das venv an?
  • D35: Bruch für bestehende Instanzen und CI
  • D36: Hooks
  • D37: pwsh im CI

Darum kind/build → kind/decision. Nach der Entscheidung geht es zurück auf kind/build.

Außerdem:

  • Neu: Abschnitt „Umsetzungsplan“ (A: sh, B: pwsh, C: Asset-Modus). Die Aufrufstellen für git/rg sind aufgezählt, dazu die Überschneidung mit #152, die Vibe-Hooks und die Namensregel für das Einstiegsskript (PATHEXT).
  • Korrigiert: „Version: minor“ → Bruch im 8.0.0-Kandidaten (D35). „Vollständig spezifiziert und startbar“ gilt erst wieder nach D33–D37.
**Changelog:** Vorbereitung zur Umsetzung (2026-09-30, Claude Code/Opus 5.5). Beim Abgleich mit dem Baum sind fünf Lücken aufgefallen, die neu als offene Entscheidungen **D33–D37** im Body stehen: - D33: Asset-Modus vs. Manifest im Baum - D34: Wer legt das venv an? - D35: Bruch für bestehende Instanzen und CI - D36: Hooks - D37: pwsh im CI Darum `kind/build` → `kind/decision`. Nach der Entscheidung geht es zurück auf `kind/build`. Außerdem: - **Neu:** Abschnitt „Umsetzungsplan“ (A: sh, B: pwsh, C: Asset-Modus). Die Aufrufstellen für `git`/`rg` sind aufgezählt, dazu die Überschneidung mit #152, die Vibe-Hooks und die Namensregel für das Einstiegsskript (PATHEXT). - **Korrigiert:** „Version: minor“ → Bruch im 8.0.0-Kandidaten (D35). „Vollständig spezifiziert und startbar“ gilt erst wieder nach D33–D37.
torben added kind/build and removed kind/decision labels 2026-09-30 21:35:34 +00:00
Author
Owner

Changelog: D33–D37 entschieden (Betreiber, 2026-09-30, alle wie empfohlen). Darum kind/decision → kind/build; das Paket ist startbar.

  • „Offene Entscheidungen“ → „Entscheidungen aus der Vorbereitung“, jeweils mit dem verworfenen Weg.
  • Der Entwurf verweist nicht mehr auf offene Punkte: zwei Modi (D33), venv durch den Preflight (D34), Bruch angenommen (D35), tools/trace-hook (D36), Image chemenu-ci-pwsh (D37).
  • Neue Kriterien: venv/Idempotenz, Asset-Modus ruft die Kopie im Baum auf, Workflows per Preflight, --breaking-Satz, Hooks, CI-Image. Die Stoppfall-Liste ist um Download-Werkzeug und venv/pip erweitert.
  • Im Umsetzungsplan trägt jeder Abschnitt seinen Stand. Neu in A ist die Einrichtung des Entwicklungs-Checkouts per Preflight.
**Changelog:** D33–D37 entschieden (Betreiber, 2026-09-30, alle wie empfohlen). Darum `kind/decision` → `kind/build`; das Paket ist startbar. - „Offene Entscheidungen“ → „Entscheidungen aus der Vorbereitung“, jeweils mit dem verworfenen Weg. - Der Entwurf verweist nicht mehr auf offene Punkte: zwei Modi (D33), venv durch den Preflight (D34), Bruch angenommen (D35), `tools/trace-hook` (D36), Image `chemenu-ci-pwsh` (D37). - **Neue Kriterien:** venv/Idempotenz, Asset-Modus ruft die Kopie im Baum auf, Workflows per Preflight, `--breaking`-Satz, Hooks, CI-Image. Die Stoppfall-Liste ist um Download-Werkzeug und venv/pip erweitert. - Im Umsetzungsplan trägt jeder Abschnitt seinen Stand. Neu in A ist die Einrichtung des Entwicklungs-Checkouts per Preflight.
Author
Owner

Changelog: Abschnitt A (sh-Hälfte, Baum-Modus) ist umgesetzt und publiziert, e4b2b6d, Kandidat 8.0.0-beta.14, CI-Lauf 469 grün (2026-09-30/10-01, Claude Code/Opus 5.5).

  • Kriterien: acht abgehakt; fünf weitere sind für sh erfüllt und warten auf B oder C.
  • Entwurf: Was gebaut ist, ist mit „(A ✔)“ markiert und beschreibt den tatsächlichen Stand. Dazu gehören das Dateiformat mit complete, der Leseort _PACKAGE_ROOT, ToolPathError und der pip-Stempel.
  • D33: Neu ist der Hinweis für C, das Manifest per tar -xOf vor dem Entpacken zu lesen.
  • Handkriterium: Hinzugekommen sind reg query und Windows-Pfade unter Git Bash.
  • Bewusst offen in A: Die Meldungen nennen den pwsh-Aufruf noch nicht; das zieht B nach.
**Changelog:** Abschnitt A (sh-Hälfte, Baum-Modus) ist umgesetzt und publiziert, `e4b2b6d`, Kandidat 8.0.0-beta.14, CI-Lauf 469 grün (2026-09-30/10-01, Claude Code/Opus 5.5). - **Kriterien:** acht abgehakt; fünf weitere sind für sh erfüllt und warten auf B oder C. - **Entwurf:** Was gebaut ist, ist mit „(A ✔)“ markiert und beschreibt den tatsächlichen Stand. Dazu gehören das Dateiformat mit `complete`, der Leseort `_PACKAGE_ROOT`, `ToolPathError` und der pip-Stempel. - **D33:** Neu ist der Hinweis für C, das Manifest per `tar -xOf` vor dem Entpacken zu lesen. - **Handkriterium:** Hinzugekommen sind `reg query` und Windows-Pfade unter Git Bash. - **Bewusst offen in A:** Die Meldungen nennen den pwsh-Aufruf noch nicht; das zieht B nach.
Author
Owner

Changelog: stack-close nach Abschnitt A (2026-10-01).

  • Geschlossen wird nicht: B und C sind offen, und ein Paket über mehrere Sitzungen schließt erst nach dem letzten Publish.
  • docs/-Prüfung: docs/why-gates-are-code.md § „Exit 42 is a posture“ nennt den Preflight jetzt als zweiten Exit-42-Fall außerhalb der Gates (8dae8a1). Die übrigen docs/-Seiten sind von A nicht betroffen.
  • Modelle: Entwurf (D33–D37), Umsetzung und dieser Abschluss liefen alle auf Claude Code/Opus 5.5.
**Changelog:** stack-close nach Abschnitt A (2026-10-01). - **Geschlossen wird nicht:** B und C sind offen, und ein Paket über mehrere Sitzungen schließt erst nach dem letzten Publish. - **`docs/`-Prüfung:** `docs/why-gates-are-code.md` § „Exit 42 is a posture“ nennt den Preflight jetzt als zweiten Exit-42-Fall außerhalb der Gates (`8dae8a1`). Die übrigen `docs/`-Seiten sind von A nicht betroffen. - **Modelle:** Entwurf (D33–D37), Umsetzung und dieser Abschluss liefen alle auf Claude Code/Opus 5.5.
Author
Owner

Abschnitt B ist publiziert (4035b1b Image, 210e0c8 Code, 8.0.0-beta.15). CI-Lauf 476 mit verify und dem neuen pwsh-Job ist grün, ebenso Release-Lauf 477. Der Body ist auf diesen Stand gebracht: B-Kriterien abgehakt, Umsetzungsplan B erledigt, D37-Handschritt vermerkt. Offen bleiben C (Asset-Modus) und die manuellen Windows-Kriterien, darunter neu die Execution-Policy-Erkennung. Das Issue bleibt offen.

Abschnitt B ist publiziert (`4035b1b` Image, `210e0c8` Code, 8.0.0-beta.15). CI-Lauf 476 mit `verify` und dem neuen `pwsh`-Job ist grün, ebenso Release-Lauf 477. Der Body ist auf diesen Stand gebracht: B-Kriterien abgehakt, Umsetzungsplan B erledigt, D37-Handschritt vermerkt. Offen bleiben C (Asset-Modus) und die manuellen Windows-Kriterien, darunter neu die Execution-Policy-Erkennung. Das Issue bleibt offen.
Author
Owner

Changelog: Abschnitt C (Asset-Modus) ist publiziert (2026-10-01): c33e8cd (8.0.0-beta.16) und der Nachzug d6e973c (8.0.0-beta.17).

  • CI: Lauf 478 auf c33e8cd war im Job pwsh rot. PSScriptAnalyzer stieß sich am Verb Stop in Stop-Asset; die Funktion heißt jetzt Exit-Asset. Danach sind CI-Lauf 480 (verify + pwsh) und Release-Lauf 481 grün.
  • Body: Die sechs C-Kriterien sind abgehakt, dazu die beiden Kriterien, die auf C gewartet hatten (Download-Werkzeug, Ordnerlänge im Asset-Modus). „Entwurf“ heißt jetzt „Gebaut“ und ist mit (C ✔) markiert. Der Umsetzungsplan für C ist erledigt, samt Verifikation.
  • Handkriterium: Neu ist der Asset-Weg aus einem echten Release. Er ist erst nach dem nächsten Release ohne Suffix möglich.
  • Geschlossen wird nicht: Die manuellen Kriterien auf dem Windows-Zielsystem bleiben offen.
  • docs/-Prüfung: docs/why-gates-are-code.md bleibt gültig. Der Asset-Modus fügt Exit-42-Fälle hinzu, ändert aber nicht die Begründung. Andere docs/-Seiten sind nicht betroffen.
  • Modelle:
    • Die Entscheidungen D38–D41 wurden in einer früheren Sitzung vorbereitet; welches Modell dort lief, ist hier nicht vermerkt.
    • Umsetzung, Tests, Doku-Nachzug und der Changelog-Text für beta.16 liefen auf Claude Code/Sonnet 5.5.
    • Publish, der CI-Nachzug (beta.17) und dieser Abschluss liefen auf Claude Code/Opus 5.5.
**Changelog:** Abschnitt C (Asset-Modus) ist publiziert (2026-10-01): `c33e8cd` (8.0.0-beta.16) und der Nachzug `d6e973c` (8.0.0-beta.17). - **CI:** Lauf 478 auf `c33e8cd` war im Job `pwsh` rot. PSScriptAnalyzer stieß sich am Verb `Stop` in `Stop-Asset`; die Funktion heißt jetzt `Exit-Asset`. Danach sind CI-Lauf 480 (`verify` + `pwsh`) und Release-Lauf 481 grün. - **Body:** Die sechs C-Kriterien sind abgehakt, dazu die beiden Kriterien, die auf C gewartet hatten (Download-Werkzeug, Ordnerlänge im Asset-Modus). „Entwurf“ heißt jetzt „Gebaut“ und ist mit (C ✔) markiert. Der Umsetzungsplan für C ist erledigt, samt Verifikation. - **Handkriterium:** Neu ist der Asset-Weg aus einem echten Release. Er ist erst nach dem nächsten Release ohne Suffix möglich. - **Geschlossen wird nicht:** Die manuellen Kriterien auf dem Windows-Zielsystem bleiben offen. - **`docs/`-Prüfung:** `docs/why-gates-are-code.md` bleibt gültig. Der Asset-Modus fügt Exit-42-Fälle hinzu, ändert aber nicht die Begründung. Andere `docs/`-Seiten sind nicht betroffen. - **Modelle:** - Die Entscheidungen D38–D41 wurden in einer früheren Sitzung vorbereitet; welches Modell dort lief, ist hier nicht vermerkt. - Umsetzung, Tests, Doku-Nachzug und der Changelog-Text für beta.16 liefen auf Claude Code/Sonnet 5.5. - Publish, der CI-Nachzug (beta.17) und dieser Abschluss liefen auf Claude Code/Opus 5.5.
Author
Owner

Changelog: Die Handprüfung auf dem Windows-Zielsystem ist eingearbeitet (Betreiber, 2026-10-01, Stand 8.0.0-beta.17).

  • Neu: der Abschnitt „Handprüfung auf dem Windows-Zielsystem“ mit einer Ergebnistabelle. Das letzte Kriterium ist in Unterpunkte aufgeteilt; sechs davon sind abgehakt.
  • Offen ist nur noch der Asset-Weg aus einem echten Release. Er ist erst nach dem nächsten Release ohne Suffix möglich.
  • Einschränkungen festgehalten:
    • Der Registry-PATH war beim choco-Test nicht wirklich nötig, weil der Shim-Ordner schon im PATH stand.
    • Die Gruppenrichtlinie ist auf dem Zielsystem nicht geprüft; der Betreiber nimmt an, dass sie sich analog verhält.
  • Nachtrag zu D36: Copilot führt unter Windows den bash-Zweig aus und öffnet damit den Dialog „App auswählen“. Das ist jetzt #164 (neu, prio/blocking).
  • Weitere Befunde ausgelagert:
    • Die Ausgabe kommt in den Harnesses falsch kodiert an → #152, Punkt 8.
    • Die Warnung session-id unter Copilot und der Preflight-Aufruf ohne Bypass-Präfix → #153.
**Changelog:** Die Handprüfung auf dem Windows-Zielsystem ist eingearbeitet (Betreiber, 2026-10-01, Stand 8.0.0-beta.17). - **Neu:** der Abschnitt „Handprüfung auf dem Windows-Zielsystem“ mit einer Ergebnistabelle. Das letzte Kriterium ist in Unterpunkte aufgeteilt; sechs davon sind abgehakt. - **Offen ist nur noch** der Asset-Weg aus einem echten Release. Er ist erst nach dem nächsten Release ohne Suffix möglich. - **Einschränkungen festgehalten:** - Der Registry-PATH war beim choco-Test nicht wirklich nötig, weil der Shim-Ordner schon im PATH stand. - Die Gruppenrichtlinie ist auf dem Zielsystem nicht geprüft; der Betreiber nimmt an, dass sie sich analog verhält. - **Nachtrag zu D36:** Copilot führt unter Windows den `bash`-Zweig aus und öffnet damit den Dialog „App auswählen“. Das ist jetzt **#164** (neu, `prio/blocking`). - **Weitere Befunde ausgelagert:** - Die Ausgabe kommt in den Harnesses falsch kodiert an → #152, Punkt 8. - Die Warnung `session-id` unter Copilot und der Preflight-Aufruf ohne Bypass-Präfix → #153.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: torben/chemenu#151