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 .sha256desselben 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 ✔).
Manifesttools/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.
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)
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.
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.
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).
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).
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Teilpaket von #140 (Installation neu schneiden, Windows nativ). Die Entscheidungen dazu sind getroffen: D13 (Ort der Regel), D14 (
.wikitool-tools.jsonauf 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.
e4b2b6d, Kandidat 8.0.0-beta.14, CI-Lauf 469 grün.210e0c8, Kandidat 8.0.0-beta.15 (Imagechemenu-ci-pwshin4035b1b), CI-Lauf 476 grün, Release-Lauf 477 grün.c33e8cd(8.0.0-beta.16) und der Nachzugd6e973c(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:
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):Der Agent installiert nie selbst, auch nicht mit Zustimmung (#140 D6).
Die Prüfung kann kein
wikitool-Befehl sein: ohne Python startetwikitoolnicht.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.txtund das Ziel für.wikitool-tools.jsongibt es dann noch nicht.Entschieden: ein Skript je Plattform mit zwei Modi. Welcher gilt, entscheidet, ob neben dem Skript ein Stack-Baum liegt.
tools/preflight.*im entpackten Baum aufrufen.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,tarundsha256sumodershasum. 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 pertar -xOzf <archiv> <oberster>/tools/prerequisites.txtaus dem Archiv gelesen; das geht mit GNU tar wie mittar.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/.venvan:<python> -m venv, dann<venv-python> -m pip install -r tools/requirements.txt. Das läuft idempotent bei jedem Lauf und bringt damit nachdist upgradeauch 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.jsonExit 42“ startet nach dem Update auf 8.0.0 bei keiner bestehenden Instanzwikitool, 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 "…"upgrade-instance.mdbekommt den Preflight als Schritt vorinstructions sync, und die Abschlussmeldung vondist upgradenennt 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.jsonund.vibe/hooks.toml. Sie können.wikitool-tools.jsonnicht 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.tools/trace-hookwählt das Layout (.venv/bin/pythonoder.venv/Scripts/python.exe). Claude Code, Vibe und Copilotsbash-Zweig rufen es auf.powershell-Zweig ruft.\tools\.venv\Scripts\python.exedirekt auf.|| 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-hookauf.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 denpowershell-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-slimhat 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.dashist unkritisch, er ist dort/bin/sh.Entschieden: ein Image
gitea.nehmer.net/torben/chemenu-ci-pwsh(trixie-slim + pwsh + PSScriptAnalyzer), gebaut nach dem Muster vonchemenu-sp-live(#156). Ein eigener Job inci.ymlnutzt 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.ymlhängte bis dahin nur Tarball und.sha256an. 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.ymlhängt zusätzlichpreflight.shundpreflight.ps1an, 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.ymlschreibt beim Anhängen die URLs von Tarball und.sha256desselben 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/latestab. Unter pwsh ginge das sauber, unter sh nur per sed über JSON, und das ist fragil.D40 – Zielordner
chemenuneben dem Skript,--intoüberschreibtEntschieden: Standardziel ist
<Ordner des Skripts>/chemenu, mit--into <pfad>überschreibbar. Ablauf:_extract_single_top_level_dirindist_cmd.py;Ein schon vorhandenes Ziel wird verweigert.
Warum: Ein Ordnername mit Version (
chemenu-stack-<version>) führt nach dem erstendist upgradein 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 ArchivEntschieden:
--archive <pfad>nimmt einen schon vorhandenen Tarball;<pfad>.sha256muss 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-WebRequestkann keinfile://; 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)
tools/wikitoolzuerst auf.ps1auf, 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 doctorstartet in pwshwikitool.ps1.tools/wikitool doctorgibt nichts aus und endet ohne Fehler.wikitool.ps1ist Pflicht, nicht Komfort.python=C:\Python314\python,python3= Store-Alias.python3zuerst nehmen. Der Claude-Code-Hook (python3-Shebang) lief dort nachweislich ins Leere (behoben mit D36).python.exeundpython3.exegibt es als Store-Aliase unterWindowsApps, dazuC:\Windows\py.exe. Punkt 1 (veralteter PATH) wurde nicht nachgestellt.pip.exeblockiert Defender ASR. Der Betreiber lässt es freischalten und arbeitet unter dieser Annahme.-m pipbleibt, damit der Stack die Freischaltung gar nicht braucht.LocalMachine = RemoteSigned, keine Gruppenrichtlinie.Invoke-WebRequestsetzt keine Markierung, der Browser schon;tar -xfgibt sie nicht weiter.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--archiveträgt kein entpacktes Skript eine Markierung.LongPathsEnabled = 0,core.longpathsnicht gesetzt.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|95und je Tooltool|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 überchemenu/prerequisites.py.tools/preflight.shin 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 percygpath -win native Windows-Form gebracht. Die Markierungsprüfung macht nur der pwsh-Preflight.tools/preflight.ps1mit#Requires -Version 7(B ✔ Baum-Modus, C ✔ Asset-Modus). Windows PowerShell 5.1 wird nicht unterstützt (#140 D8);#Requiresliefert dort eine klare Absage. Schreibt byteidentisches JSON zupreflight.sh(CI vergleicht percmp).Zwei Modi je Skript (D33; C ✔): Welcher gilt, entscheidet allein, ob
tools/prerequisites.txtneben dem Skript liegt. Im Baum-Modus werden--into/--archivemit 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 unterRemoteSignedein markierter Preflight sonst gar nicht startet und seine eigene Markierung nicht melden kann. Auf dem Zielsystem bestätigt:.\tools\preflight.ps1ohne 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):
python,py -3,python3. Sonst:python3,python.…\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.<kandidat> -c "import sys; print(…version_info[:2]…, sys.executable)"mit Exit 0 läuft..wikitool-tools.jsonstehtsys.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 mitWhy:,Fix:(Befehl für den erkannten Paketmanager, sonst alle),Next:. Die Ausgabe ist englisch;instructions/preflight.mdlä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 PolicyRestricted/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
*.ps1untertools/aufZone.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/AllSignedist ein Stoppfall; eine Gruppenrichtlinie bekommt „Admin fragen / Git Bash“, sonstSet-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned. Prüft der Preflight unddoctor.Release-Download beim Erstinstall (D27, D33, D38–D41; C ✔):
tar -xOzf <archiv> <oberster>/tools/prerequisites.txtaus dem Archiv und prüft den endgültigen Zielpfad (D40)..chemenu-unpack.<pid>, verlangt genau einen obersten Ordner und benennt um.tools/preflight.*im neuen Baum auf.--setund der Exit-Code werden durchgereicht: unter sh perexec, unter pwsh per Kindprozess mit demselben Bypass.Invoke-WebRequest,Get-FileHashundtar.exe; unter shcurl,tarundsha256sum/shasum.--archive/--intopercygpath -uumgesetzt, weil GNU tarC:als Host liest.--archive(D41) ersetzt den Download.version.py(chemenu-stack-<version>.tar.gz+.sha256).release.ymlerzeugt die Asset-Kopien persed, prüft pergrep -qFbeide URLs in beiden Kopien und lädtpreflight.sh/preflight.ps1in derselben Schleife wie Tarball und.sha256hoch.Ordnerlänge (D32 Teil 2; A ✔ für sh und
doctor, B ✔ für pwsh, C ✔ für den Asset-Modus):LongPathsEnabled = 0darf der Installationsordner – das Verzeichnis, dastools/enthält, als absoluter Windows-Pfad – höchstens 95 UTF-16-Einheiten lang sein.preflight.shfragtLongPathsEnabledperreg queryab (ein nicht lesbarer Schlüssel gilt als aus);doctorperwinreg. Für Tests stehenCHEMENU_PREFLIGHT_PLATFORMundCHEMENU_PREFLIGHT_LONGPATHSbereit; B ergänztCHEMENU_PREFLIGHT_POLICYundCHEMENU_PREFLIGHT_MARKED.titles.PATH_BUDGET, #163) ≤ 259. Die 95 steht nur im Manifest;test_manifest_limit_and_path_budget_fit_max_path_togetherhält die Summe..wikitool-tools.json(D14; A ✔): gitignored, pro Checkout,{"schema": 1, "complete": true|false, "tools": {…}}.completewird erst nach dem venv-Schritttrue. Nach einem Stopp stehen die gefundenen Tools mitcomplete: falsein 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.pylöst die Pfade auf; gelesen wird nebentools/(config._PACKAGE_ROOT), nicht unterCHEMENU_ROOT. Alle Aufrufstellen gehen darüber:git_publish._runund der Scratch-Index-Lauf,config.default_author,corpus_cache,dist_cmd,migrate_cmd(2×),doctor,docs_verify,search/ripgrep.build_argv.upstream_cmd.pybleibt unberührt (entfällt mit #153).ToolPathError(keinOSError), vom CLI alsERROR-Zeile mit Verweis auf den Preflight ausgegeben.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, startettools/run_wikitool.pystatt-mmitPYTHONPATH. Der Name beginnt bewusst nicht mitwikitool.(PATHEXT/.PY).tools/wikitool.ps1mit#Requires -Version 7(B ✔). Keintools/wikitool.cmd(T1, T4). Die Meldungen von Launcher,toolpaths.PREFLIGHTunddoctor.PREFLIGHT_FIXnennen 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 Stempeltools/.venv/.chemenu-requirements.sha256überspringt pip, solange sichrequirements.txtnicht geändert hat.Hooks (D36; A ✔, unter Windows mit Copilot fehlerhaft → #164):
.claude/settings.json, derbash-Zweig in.github/hooks/wiki-trace.jsonund.vibe/hooks.tomlrufen./tools/trace-hookauf; Copilotspowershell-Zweig.\tools\.venv\Scripts\python.exe tools\trace_ingest.py. EVALS.md beschreibt es.Bugreport-Sammler (Nachzug aus #157; B ✔):
instructions/bug-report.mdverweist darauf, dass die Preflight-Ausgabe der Bericht ist, wenn kein Python startet.tools/bugreport.pystartetwikitoolunter Windows perpwsh -NoProfile -ExecutionPolicy Bypass -File tools/wikitool.ps1(launcher_command), abgeglichen mit dem gebauten Launcher._collect_tools_config) ist gegen eine echteschema: 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-pathsundinstall-dir(A ✔); Execution Policy samt Gruppenrichtlinie und Mark of the Web an Stack-Skripten (B ✔).Test ohne Windows-Runner
preflight.shläuft intest_preflight.pyunter jeder vorhandenen Shell aus dash und bash, gegen einen PATH aus einzeln verlinkten Hilfsprogrammen plus Stubs. Die Stub-Python spielt auch-m venvund-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 shund indebian:trixie-slimper 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/1geprüft, im Preflight und indoctor. (A ✔)CI:
ci.ymlrichtet sich per Preflight ein, lässt ihn zweimal laufen und vergleicht die Datei; das Replay im exportierten Baum prüft zuerst, dasstools/wikitool doctormit 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): Jobpwshinci.ymlmit PSScriptAnalyzer (ohnePSAvoidUsingPositionalParameters, im Workflow begründet),preflight.ps1zweimal pluscmpgegenpreflight.sh,tools/wikitool version showaus pwsh, undtest_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:--into(auch relativ) und ein vorhandenes Ziel;.sha256, zwei oberste Ordner, leere Platzhalter;--setund Exit-Code;Der Download läuft unter sh gegen einen
curl-Stub und unter pwsh gegen einen lokalenThreadingHTTPServer, jeweils auch als fehlgeschlagener Download.test_the_release_workflow_fills_exactly_the_placeholders_the_scripts_keepleitet diesed-Ausdrücke aus den Platzhaltern ab und hält sie gegenrelease.yml.test_preflight_pwsh.pywird ohne lokales pwsh komplett übersprungen (pytestmark).instructions/dev/testing-conventions.mdsagt, wie man das erkennt und die Tests per Docker im Imagechemenu-ci-pwshlaufen lässt. Für C liefen sie mit lokalem pwsh 7.6.6 (54 grün) und im CI-Jobpwsh. 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:
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, LocalMachineRemoteSigned). Für den Asset-Modus lag ein Tarball vor, dendist exportauf dem Zielsystem gebaut hatte.doctorin pwsh (Copilot, auch direkt) und in Git Bash (Claude Code, auch direkt)reg queryaus Git BashLongPathsEnabled = 0x0tools/preflight.sh-Lauf mit Exit 0.C:\Python314\python.exe,C:\Program Files\Git\cmd\git.exe,C:\ProgramData\chocolatey\bin\rg.exeundC:\Program Files\PowerShell\7\pwsh.exewerden als ausführbar erkannt.choco uninstall ripgrepmeldet der Preflight in Copilot Exit 42 mitMISSING rg. Der Agent installiert nichts. Nachchoco install ripgrependet 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.Restricted(CurrentUser)Set-ExecutionPolicy … RemoteSigned,doctor(aus Git Bash) meldetFAIL execution-policy.ZoneId=3)wikitool.ps1und die ZeileUnblock-File. Nach dem Ausführen dieser Zeile endet der Preflight mit 0.--archivefolgensha256 OK, das Entpacken nachchemenu\neben dem Skript und der Baum-Preflight mit 0; dort keine Markierung. Ein zweiter Lauf endet mit Exit 1 „already exists“. Mit--intoauf 103 Zeichen Exit 42, nichts entpackt.--archiveund--intoin Windows-Form (C:\…) wie in POSIX-Form (/c/…), jeweils Exit 0 (cygpath)Befunde außerhalb von #151:
trace-hook→ #164.doctorgibtFu�notenaus, wenn die Ausgabe über die Harness läuft (Copilot und Claude Code); direkt in der Konsole stimmt sie → #152.session-id, weil keine Harness-Variable gesetzt ist → gehört zu #153 (D26)..\tools\preflight.ps1ohne den Bypass-Präfix gestartet und den Anleitungsblock übersetzt wiedergegeben, statt eine Übersetzung darunter zu setzen.instructions/preflight.mdhatte 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; allegit/rg-Aufrufstellen; CLI-Behandlung vonToolPathError;doctor(tool-paths,install-dir);.gitignore.ci,release,nightly,tracker-liveund CI-Replay (D35).instructions/preflight.md(neu), AGENTS.md § Bootstrap,bootstrap.md,setup-instance.mdSchritt 7,upgrade-instance.mdSchritt 8, Abschlussmeldung vondist upgrade.doctor-Record, regeneriert), INSTALL.md (Voraussetzungen, Weg C, § Konfiguration, Troubleshooting), EVALS.md (Hooks).--major --impact highmit dem--breaking-Satz (D35), Changeset in CHANGES.md.docs verify,instructions verify,lint --fail-on-error, Replay des CI-Schritts gegen einen frischendist export; danach CI 469 und Release-Workflow 470 (überspringt die Beta) grün.B – pwsh-Hälfte, Baum-Modus – erledigt: Image
4035b1b, Code210e0c8, 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.toolpaths.PREFLIGHT,doctor.PREFLIGHT_FIX,cli.py,dist_cmdundinstructions/preflight.mdnennen den pwsh-Aufruf.doctor:execution-policyundscript-marks.chemenu-ci-pwsh(.gitea/pwsh-ci/Dockerfile,pwsh-ci-image.yml) und -Job; Paket vom Betreiber verknüpft.bugreport.py(launcher_command, echtesschema: 1im Test),instructions/bug-report.md.docs/why-gates-are-code.md.--minor, Changeset in CHANGES.md.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-errorgrün;dist exportliefert beide.ps1.C – Asset-Modus (D27/D33, D38–D41), beide Plattformen – erledigt:
c33e8cd(8.0.0-beta.16) undd6e973c(8.0.0-beta.17), CI-Lauf 480 (verify+pwsh) und Release-Lauf 481 grün (2026-10-01)preflight.shundpreflight.ps1: Asset-Modus, wenn kein Manifest daneben liegt. Optionen--into <pfad>(D40) und--archive <pfad>(D41);--setwird an die Kopie im Baum durchgereicht, ihr Exit-Code ebenso.RELEASE_ARCHIVE_URL/RELEASE_CHECKSUM_URL(sh) bzw.$ReleaseArchiveUrl/$ReleaseChecksumUrl(pwsh), leer im Baum (D39).release.yml:preflight.shundpreflight.ps1mit eingetragenen URLs angehängt (D38, D39). Ein Test hält Platzhalter und Workflow zusammen.instructions/dev/testing-conventions.md: Entscheidungspunkt, dasstest_preflight_pwsh.pyohne pwsh still übersprungen wird und wie die Tests dann per Docker laufen.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.--minor(8.0.0-beta.16), Changeset in CHANGES.md.d6e973c(8.0.0-beta.17,--patch): CI-Lauf 478 aufc33e8cdwar im Jobpwshrot. PSScriptAnalyzer (PSUseShouldProcessForStateChangingFunctions) liest das VerbStopin der HilfsfunktionStop-Assetals zustandsändernd. Sie heißt jetztExit-Asset, nebenExit-WithGuide; das Verhalten ist unverändert. Lokal per Docker im Imagechemenu-ci-pwshgeprüft: 0 Funde.tools/1918 grün, 3 übersprungen. Darintest_preflight.py59 undtest_preflight_pwsh.py54 grün, mit lokalem pwsh 7.6.6.docs verify,instructions verifyundlint --fail-on-errorgrün.sed-Ersetzung ausrelease.ymllokal mit dem herausgelösten Schnipsel nachgestellt.Akzeptanzkriterien
rgendettools/preflight.shmit Exit 42 und einerMISSING rg-Zeile; mit vollständigem PATH endet es mit Exit 0 und schreibt.wikitool-tools.jsonmit absoluten Pfaden. (A:test_missing_rg_…,test_complete_path_…)tools/preflight.ps1unter pwsh 7 (Linux-CI). (B:test_preflight_pwsh.py, Jobpwsh)…/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).--set-Pfad, Ordnerlänge, venv, pip, Markierung, Gruppenrichtlinie; C ✔ für fehlendescurl/tar/sha256sum(sh) und Ordnerlänge am Asset-Ziel (beide).LongPathsEnabled = 0ergibt ein Installationsordner mit 96 Einheiten Exit 42, mit 95 geht es, mitLongPathsEnabled = 1auch 96;doctormeldet den 96er-Fall als FAIL. sh, pwsh unddoctor✔; 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.tools/.venv; ein zweiter Lauf ändert nichts und endet mit Exit 0 (D34). (Test + CI-Doppellauf, sh und pwsh)<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.sha256daneben; ohne.sha256Exit 1 (D41). (C; auf dem Zielsystem bestätigt)--archivemit Exit 1 und sagt, dass sie nicht aus einem Release stammt;release.ymlhängtpreflight.shundpreflight.ps1mit 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/wikitoolohne.wikitool-tools.jsonoder ohne venv endet mit Exit 42, nennt den Preflight und druckt keinen Traceback. sh ✔ (auch beicomplete: false);wikitool.ps1✔ (B).tools/wikitoolundtools/wikitool.ps1, aber keintools/wikitool.cmd. (test_there_is_a_powershell_launcher_and_no_cmd)wikitoolstartetgitundrgüber die Pfade aus.wikitool-tools.json(test_git_and_rg_start_from_the_recorded_paths_not_from_path, PATH leer)..wikitool-tools.jsonist gitignored;doctormeldet einen verschwundenen Pfad als FAIL.upgrade-instance.mdund die Abschlussmeldung vondist upgradenennen den Preflight. CI-Lauf 469 grün, einschließlich der Exit-42-Verweigerung im Replay.CHANGES.md-Eintrag des Kandidaten trägt den--breaking-Satz aus D35.trace_ingest.pyper Shebang oder mit bloßempython/python3auf;tools/trace-hookstartet es mit beiden venv-Layouts und bleibt ohne venv still (D36). (Was Copilot unter Windows davon tatsächlich ausführt, korrigiert #164.)chemenu-ci-pwsh(D37). (B, Lauf 476; nach C wieder grün in Lauf 480; die RegelPSAvoidUsingPositionalParametersist im Workflow ausgenommen und dort begründet)instructions/bug-report.mdverweist auf die Preflight-Ausgabe, und die Windows-Startlogik sowie die Pfadprüfung vontools/bugreport.pystimmen mit dem gebauten Launcher und.wikitool-tools.jsonüberein. (B)wikitool.ps1meldet der Preflight mit Exit 42 samt Anleitung.tools/wikitool doctorgibt in pwsh (Copilot) und in Git Bash (Claude Code) Ausgabe aus, statt still zu enden.reg queryliefertLongPathsEnabled, und aufgezeichnete Windows-Pfade (C:\…\python.exe) werden als ausführbar erkannt.preflight.ps1erkennt die Execution PolicyRestrictedals Stoppfall, unddoctormeldet dasselbe. Die Gruppenrichtlinie ist auf dem Zielsystem nicht geprüft; der Betreiber nimmt an, dass sie sich analog verhält.--archiveaus pwsh und aus Git Bash: Installation neben dem Skript bzw. per--into, vorhandenes Ziel mit Exit 1, zu langer--intomit Exit 42 ohne Entpacken, keine Markierung im entpackten Baum.preflight.ps1aus pwsh undpreflight.shaus Git Bash von der Release-Seite laden und ohne--archiveausführen. Beide laden den Tarball selbst, prüfen die sha256 und installieren inchemenu/neben sich.Abhängigkeiten
Keine offenen. Das Pfadbudget aus #163 ist im Baum (
titles.PATH_BUDGET); die Summenprüfung liest es. #152 fasst dieselbensubprocess-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).
--majorgebumpt (8.0.0-beta.14) und den--breaking-Text des Kandidaten ergänzt; eskaliert hat damit nichts.--minorgebumpt (8.0.0-beta.15), C ebenfalls (8.0.0-beta.16).--patch(8.0.0-beta.17).Changelog:
kind/decision→kind/build.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.mdund um den Abgleich der Windows-Startlogik und Pfadprüfung vontools/bugreport.pymit dem gebauten Launcher und.wikitool-tools.json. Sonst ist nichts geändert.Changelog: T1, T2 und T4–T8 aus #140 eingearbeitet (2026-09-30). Neuer Abschnitt mit einer Tabelle der Ergebnisse. Dazu:
.cmd(T1);wikitool.ps1ist Pflicht, weil die Datei ohne Endung in pwsh still nichts tut (T10).python,py -3,python3.WindowsApps-Pfade werden ohne Ausführung verworfen, und in der Datei stehtsys.executable(T4/T5). Dazu ein neues Kriterium mit einem Store-Alias-Stub.-m pipmacht die Freischaltung für den Stack überflüssig.doctormuss in pwsh und in Git Bash Ausgabe liefern.Changelog: D32 Teil 2 entschieden (2026-09-30). Die Prüfung der Ordnerlänge ist jetzt fest spezifiziert:
LongPathsEnabled = 0doctorNeu 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: 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:
Darum
kind/build→kind/decision. Nach der Entscheidung geht es zurück aufkind/build.Außerdem:
git/rgsind aufgezählt, dazu die Überschneidung mit #152, die Vibe-Hooks und die Namensregel für das Einstiegsskript (PATHEXT).Changelog: D33–D37 entschieden (Betreiber, 2026-09-30, alle wie empfohlen). Darum
kind/decision→kind/build; das Paket ist startbar.tools/trace-hook(D36), Imagechemenu-ci-pwsh(D37).--breaking-Satz, Hooks, CI-Image. Die Stoppfall-Liste ist um Download-Werkzeug und venv/pip erweitert.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).complete, der Leseort_PACKAGE_ROOT,ToolPathErrorund der pip-Stempel.tar -xOfvor dem Entpacken zu lesen.reg queryund Windows-Pfade unter Git Bash.Changelog: stack-close nach Abschnitt A (2026-10-01).
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 übrigendocs/-Seiten sind von A nicht betroffen.Abschnitt B ist publiziert (
4035b1bImage,210e0c8Code, 8.0.0-beta.15). CI-Lauf 476 mitverifyund dem neuenpwsh-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.Changelog: Abschnitt C (Asset-Modus) ist publiziert (2026-10-01):
c33e8cd(8.0.0-beta.16) und der Nachzugd6e973c(8.0.0-beta.17).c33e8cdwar im Jobpwshrot. PSScriptAnalyzer stieß sich am VerbStopinStop-Asset; die Funktion heißt jetztExit-Asset. Danach sind CI-Lauf 480 (verify+pwsh) und Release-Lauf 481 grün.docs/-Prüfung:docs/why-gates-are-code.mdbleibt gültig. Der Asset-Modus fügt Exit-42-Fälle hinzu, ändert aber nicht die Begründung. Anderedocs/-Seiten sind nicht betroffen.Changelog: Die Handprüfung auf dem Windows-Zielsystem ist eingearbeitet (Betreiber, 2026-10-01, Stand 8.0.0-beta.17).
bash-Zweig aus und öffnet damit den Dialog „App auswählen“. Das ist jetzt #164 (neu,prio/blocking).session-idunter Copilot und der Preflight-Aufruf ohne Bypass-Präfix → #153.