Teilpaket von #140 (D8: Windows nativ, PowerShell 7).
Erledigt (2026-10-01):d0f08d1, Kandidat 8.0.0-beta.19. CI grün: Run 484 (verify und pwsh), Run 485 (release). Lokal vor dem Publish: pytest (1969 bestanden, 3 übersprungen), docs verify und instructions verify grün. Die Handprüfung der Ausgabe auf dem Windows-Zielsystem führt der Nachlauf von #140 („Ausgabe ohne Kodierungsfehler“).
Warum
Der Python-Code setzte an mehreren Stellen POSIX voraus. Im analysierten Lauf (#140) scheiterte instructions verify unter Windows an allen 23 Instruktionen. Weitere Stellen rechneten unter Windows falsch, ohne dass es jemand bemerkt hätte.
Befund (erhoben auf 8.0.0-beta.18)
Pfadtrenner.str(<pfad>.relative_to(...)) stand an 15 Stellen außerhalb der Tests, darunter der Selbstreferenz-Vergleich in type_resolver.py, der jede Type-Spec-Validierung brach. Dazu kamen zwei Fehlermeldungen, die einen relativen Pfad erst später in einen String verwandelten.
Zeilenenden. Es gab keine .gitattributes. Mit core.autocrlf=true bekam der Bash-Launcher tools/wikitool CRLF (env: 'bash\r').
Text-Schreibzugriffe ohne newline="\n" schrieben unter Windows CRLF. Das betraf den Byte-Vergleich der Skill-Kopien und die sha256-Summen in dist upgrade.
Encoding beim Lesen. 13 subprocess-Aufrufe mit text=True dekodierten unter Windows mit der Locale (cp1252). Dazu kamen ein read_text() ohne encoding (run_budget._load_state) und sys.stdin in trace_ingest.py.
Encoding der eigenen Ausgabe.doctor zeigte unter Copilot (pwsh) und Claude Code (Git Bash) Fu�noten, direkt in einer Konsole dagegen richtig. Python schreibt unter Windows in eine Pipe mit cp1252.
Locks.fcntl in run_budget.py und telemetry/writer.py. Unter Windows fiel die Sperre still weg.
ripgrep.rg --json liefert unter Windows kb\\comparisons\\COLLECTION.md, auch mit --path-separator / (T3).
Umgesetzt
.gitattributes mit * text=auto eol=lf. Abweichung:raw/ und incoming/ sind -text, damit Quellen byte-genau bleiben (raw/CONTRACT.md, Regel „Immutable“). dist export liefert die Datei aus. Die Renormalisierung des Index änderte nichts.
Pfade: Alle Stellen nutzen .as_posix(), auch die Rückfallzweige und die Fehlermeldungen.
newline="\n" an jedem Text-Schreibzugriff. Abweichung: Es steht direkt am Aufruf, nicht in einem Helfer. Der Guard-Test hält es so oder so, und ein Helfer bräuchte denselben Guard.
encoding="utf-8" an jedem subprocess-Aufruf mit text=True.
chemenu/filelock.py:flock unter POSIX, msvcrt.locking unter Windows. Gesperrt wird ein Byte bei Offset 2³¹−2, weit hinter den Daten, weil Windows-Locks verpflichtend sind und trace_ingest.py die Trace sonst nicht lesen könnte. Bei Konkurrenz wird gewartet, wie bei flock. Die Lock-Datei des Budgets wird mit a geöffnet statt mit w.
search/ripgrep.py:_record_path wandelt \ in /, nur wenn os.sep == "\\". Das Flag kommt nicht hinzu. Die Umwandlung ist verlustfrei, weil kein Windows-Pfadbestandteil und seit #155 kein Seitentitel ein \ enthalten kann.
Guard-Tests in tests/test_portability.py, per AST über tools/chemenu und die Skripte daneben in tools/. Jeder Detektor wird zusätzlich mit seinem Defekt gefüttert, damit ein Guard nicht grün ist, nur weil er nichts findet. Sie schlagen fehl bei:
str(...relative_to(...)) und f"{...relative_to(...)}"
Text-Schreibzugriffen ohne newline=
Erweitert: jedem Text-Lese- oder -Schreibzugriff ohne encoding=
subprocess.*(text=True) ohne encoding=, dazu kein from subprocess import
import fcntl/msvcrt außerhalb von filelock.py
UTF-8 für die eigene Ausgabe, in tools/run_wikitool.py, der einen Stelle für beide Launcher. Dort stellt reconfigure stdout und stderr vor main() um.
Messung auf dem Zielsystem (2026-10-01): Natives pwsh hat [Console]::OutputEncoding = ibm850 und $OutputEncoding = utf-8. Unter Copilot sind beide utf-8. pwsh dekodiert abgefangene Kindprozess-Ausgabe mit [Console]::OutputEncoding, deshalb reicht unter Copilot UTF-8 aus Python. Git Bash reicht die Bytes unverändert durch.
Verworfen:PYTHONUTF8=1 in beiden Launchern. Das wären zwei Stellen, und der geänderte open()-Default würde ein fehlendes encoding= verdecken.
Mitgenommen:trace_ingest.py liest stdin als UTF-8-Bytes. Ein locale-dekodierter Read scheiterte an Bytes, die in cp1252 undefiniert sind (z. B. Ł = C5 81).
Entschieden (Betreiber, 2026-10-01): bleibt vorerst so. Wird tools/wikitool im nativen pwsh-Fenster gepiped (| Select-String), dekodiert pwsh mit ibm850. Das war vorher schon so. Die Alternative wäre, dass wikitool.ps1[Console]::OutputEncoding für die Dauer des Aufrufs umstellt; sie ist zurückgestellt. Ohne Pipe ist die Ausgabe richtig.
Akzeptanzkriterien
tools/wikitool wird mit LF ausgecheckt: git check-attr meldet text: auto und eol: lf (Test test_every_text_file_is_checked_out_with_lf). Der Index ist durchgehend i/lf.
rg -n 'str\([^)]*relative_to' tools/chemenu -g '!**/tests/**' findet nichts. Der Guard-Test schlägt bei str(...) und bei f-Strings fehl.
Jeder Text-Schreibzugriff unter tools/chemenu und in tools/*.py trägt newline= (Guard-Test).
Jeder subprocess-Aufruf mit text=True trägt encoding="utf-8" (Guard-Test).
Budget-Zähler und Telemetrie-Writer sperren auch ohne fcntl. Getestet mit ausgeblendetem fcntl-Import und einem Fake-msvcrt, einschließlich Offset, Positionserhalt und Warten bei Konkurrenz. Ein echter Windows-Lock läuft mangels Windows-Runner nicht (T12).
Die T3-JSON-Zeile ergibt bei simuliertem Windows-Trenner kb/comparisons/COLLECTION.md. Ein Treffer in derselben Form auf eine Fixture-Seite trägt Schlüssel, Titel, Art, Collection und Summary. Unter POSIX-Trenner bleibt der Pfad unverändert (test_search.py).
Unter Linux ist eine Ausgabe mit ß in eine Pipe UTF-8, auch unter simuliertem PYTHONIOENCODING=cp1252 (test_portability.py). Auf dem Windows-Zielsystem zeigt doctorFußnoten unter Copilot, Claude Code und in beiden Konsolen – diese Handprüfung führt der Nachlauf von #140 („Ausgabe ohne Kodierungsfehler (#152)“), nicht dieses Paket.
pytest, docs verify und instructions verify sind grün, lokal und in CI 484.
Restrisiko, nicht in diesem Paket
run_budget.status_command liest den Budget-Zustand ohne Lock. Unter Windows kann os.replace in _save_state scheitern, wenn genau dann ein Leser die Datei offen hat. Das Zeitfenster ist klein. Ein Paket entsteht erst, wenn es im Nachlauf auftritt.
Version
minor – Windows-Fähigkeit, drop-in. Im Kandidaten 8.0.0-beta.19.
Teilpaket von #140 (D8: Windows nativ, PowerShell 7).
**Erledigt (2026-10-01):** `d0f08d1`, Kandidat 8.0.0-beta.19. CI grün: Run 484 (`verify` und `pwsh`), Run 485 (`release`). Lokal vor dem Publish: `pytest` (1969 bestanden, 3 übersprungen), `docs verify` und `instructions verify` grün. Die Handprüfung der Ausgabe auf dem Windows-Zielsystem führt der Nachlauf von #140 („Ausgabe ohne Kodierungsfehler“).
## Warum
Der Python-Code setzte an mehreren Stellen POSIX voraus. Im analysierten Lauf (#140) scheiterte `instructions verify` unter Windows an allen 23 Instruktionen. Weitere Stellen rechneten unter Windows falsch, ohne dass es jemand bemerkt hätte.
## Befund (erhoben auf 8.0.0-beta.18)
- **Pfadtrenner.** `str(<pfad>.relative_to(...))` stand an 15 Stellen außerhalb der Tests, darunter der Selbstreferenz-Vergleich in `type_resolver.py`, der jede Type-Spec-Validierung brach. Dazu kamen zwei Fehlermeldungen, die einen relativen Pfad erst später in einen String verwandelten.
- **Zeilenenden.** Es gab keine `.gitattributes`. Mit `core.autocrlf=true` bekam der Bash-Launcher `tools/wikitool` CRLF (`env: 'bash\r'`).
- **Text-Schreibzugriffe** ohne `newline="\n"` schrieben unter Windows CRLF. Das betraf den Byte-Vergleich der Skill-Kopien und die sha256-Summen in `dist upgrade`.
- **Encoding beim Lesen.** 13 `subprocess`-Aufrufe mit `text=True` dekodierten unter Windows mit der Locale (cp1252). Dazu kamen ein `read_text()` ohne `encoding` (`run_budget._load_state`) und `sys.stdin` in `trace_ingest.py`.
- **Encoding der eigenen Ausgabe.** `doctor` zeigte unter Copilot (pwsh) und Claude Code (Git Bash) `Fu�noten`, direkt in einer Konsole dagegen richtig. Python schreibt unter Windows in eine Pipe mit cp1252.
- **Locks.** `fcntl` in `run_budget.py` und `telemetry/writer.py`. Unter Windows fiel die Sperre still weg.
- **ripgrep.** `rg --json` liefert unter Windows `kb\\comparisons\\COLLECTION.md`, auch mit `--path-separator /` (T3).
## Umgesetzt
1. **`.gitattributes`** mit `* text=auto eol=lf`. **Abweichung:** `raw/` und `incoming/` sind `-text`, damit Quellen byte-genau bleiben (`raw/CONTRACT.md`, Regel „Immutable“). `dist export` liefert die Datei aus. Die Renormalisierung des Index änderte nichts.
2. **Pfade:** Alle Stellen nutzen `.as_posix()`, auch die Rückfallzweige und die Fehlermeldungen.
3. **`newline="\n"`** an jedem Text-Schreibzugriff. **Abweichung:** Es steht direkt am Aufruf, nicht in einem Helfer. Der Guard-Test hält es so oder so, und ein Helfer bräuchte denselben Guard.
4. **`encoding="utf-8"`** an jedem `subprocess`-Aufruf mit `text=True`.
5. **`chemenu/filelock.py`:** `flock` unter POSIX, `msvcrt.locking` unter Windows. Gesperrt wird ein Byte bei Offset 2³¹−2, weit hinter den Daten, weil Windows-Locks verpflichtend sind und `trace_ingest.py` die Trace sonst nicht lesen könnte. Bei Konkurrenz wird gewartet, wie bei `flock`. Die Lock-Datei des Budgets wird mit `a` geöffnet statt mit `w`.
6. **`search/ripgrep.py`:** `_record_path` wandelt `\` in `/`, nur wenn `os.sep == "\\"`. Das Flag kommt nicht hinzu. Die Umwandlung ist verlustfrei, weil kein Windows-Pfadbestandteil und seit #155 kein Seitentitel ein `\` enthalten kann.
7. **Guard-Tests** in `tests/test_portability.py`, per AST über `tools/chemenu` und die Skripte daneben in `tools/`. Jeder Detektor wird zusätzlich mit seinem Defekt gefüttert, damit ein Guard nicht grün ist, nur weil er nichts findet. Sie schlagen fehl bei:
- `str(...relative_to(...))` und `f"{...relative_to(...)}"`
- Text-Schreibzugriffen ohne `newline=`
- **Erweitert:** jedem Text-Lese- oder -Schreibzugriff ohne `encoding=`
- `subprocess.*(text=True)` ohne `encoding=`, dazu kein `from subprocess import`
- `import fcntl`/`msvcrt` außerhalb von `filelock.py`
8. **UTF-8 für die eigene Ausgabe**, in `tools/run_wikitool.py`, der einen Stelle für beide Launcher. Dort stellt `reconfigure` stdout und stderr vor `main()` um.
- **Messung auf dem Zielsystem (2026-10-01):** Natives pwsh hat `[Console]::OutputEncoding` = `ibm850` und `$OutputEncoding` = `utf-8`. Unter Copilot sind beide `utf-8`. pwsh dekodiert abgefangene Kindprozess-Ausgabe mit `[Console]::OutputEncoding`, deshalb reicht unter Copilot UTF-8 aus Python. Git Bash reicht die Bytes unverändert durch.
- **Verworfen:** `PYTHONUTF8=1` in beiden Launchern. Das wären zwei Stellen, und der geänderte `open()`-Default würde ein fehlendes `encoding=` verdecken.
- **Mitgenommen:** `trace_ingest.py` liest stdin als UTF-8-Bytes. Ein locale-dekodierter Read scheiterte an Bytes, die in cp1252 undefiniert sind (z. B. `Ł` = C5 81).
- **Entschieden (Betreiber, 2026-10-01): bleibt vorerst so.** Wird `tools/wikitool` im nativen pwsh-Fenster gepiped (`| Select-String`), dekodiert pwsh mit `ibm850`. Das war vorher schon so. Die Alternative wäre, dass `wikitool.ps1` `[Console]::OutputEncoding` für die Dauer des Aufrufs umstellt; sie ist zurückgestellt. Ohne Pipe ist die Ausgabe richtig.
## Akzeptanzkriterien
- [x] `tools/wikitool` wird mit LF ausgecheckt: `git check-attr` meldet `text: auto` und `eol: lf` (Test `test_every_text_file_is_checked_out_with_lf`). Der Index ist durchgehend `i/lf`.
- [x] `rg -n 'str\([^)]*relative_to' tools/chemenu -g '!**/tests/**'` findet nichts. Der Guard-Test schlägt bei `str(...)` und bei f-Strings fehl.
- [x] Jeder Text-Schreibzugriff unter `tools/chemenu` und in `tools/*.py` trägt `newline=` (Guard-Test).
- [x] Jeder `subprocess`-Aufruf mit `text=True` trägt `encoding="utf-8"` (Guard-Test).
- [x] Budget-Zähler und Telemetrie-Writer sperren auch ohne `fcntl`. Getestet mit ausgeblendetem `fcntl`-Import und einem Fake-`msvcrt`, einschließlich Offset, Positionserhalt und Warten bei Konkurrenz. Ein echter Windows-Lock läuft mangels Windows-Runner nicht (T12).
- [x] Die T3-JSON-Zeile ergibt bei simuliertem Windows-Trenner `kb/comparisons/COLLECTION.md`. Ein Treffer in derselben Form auf eine Fixture-Seite trägt Schlüssel, Titel, Art, Collection und Summary. Unter POSIX-Trenner bleibt der Pfad unverändert (`test_search.py`).
- [x] Unter Linux ist eine Ausgabe mit `ß` in eine Pipe UTF-8, auch unter simuliertem `PYTHONIOENCODING=cp1252` (`test_portability.py`). ~~Auf dem Windows-Zielsystem zeigt `doctor` `Fußnoten` unter Copilot, Claude Code und in beiden Konsolen~~ – diese Handprüfung führt der Nachlauf von #140 („Ausgabe ohne Kodierungsfehler (#152)“), nicht dieses Paket.
- [x] `pytest`, `docs verify` und `instructions verify` sind grün, lokal und in CI 484.
## Restrisiko, nicht in diesem Paket
`run_budget.status_command` liest den Budget-Zustand ohne Lock. Unter Windows kann `os.replace` in `_save_state` scheitern, wenn genau dann ein Leser die Datei offen hat. Das Zeitfenster ist klein. Ein Paket entsteht erst, wenn es im Nachlauf auftritt.
## Version
minor – Windows-Fähigkeit, drop-in. Im Kandidaten 8.0.0-beta.19.
Changelog: T3 aus #140 eingearbeitet (2026-09-30): --path-separator / wirkt nicht auf rg --json.
Punkt 6: normalisiert jetzt in Python beim Parsen, nur unter Windows. Die Invariante, dass dabei nichts verloren geht, stützt sich auf die Titelregel aus #155. Das Flag entfällt.
Neues Kriterium: ein Test mit den JSON-Zeilen aus T3.
Hinweis: Die Zeilennummern im Befund sind Stand dd885db und werden vor dem Umbau neu erhoben.
Abhängigkeit auf T3 entfernt; alle Punkte sind startbar.
**Changelog:** T3 aus #140 eingearbeitet (2026-09-30): `--path-separator /` wirkt nicht auf `rg --json`.
- **Punkt 6:** normalisiert jetzt in Python beim Parsen, nur unter Windows. Die Invariante, dass dabei nichts verloren geht, stützt sich auf die Titelregel aus #155. Das Flag entfällt.
- **Neues Kriterium:** ein Test mit den JSON-Zeilen aus T3.
- **Hinweis:** Die Zeilennummern im Befund sind Stand `dd885db` und werden vor dem Umbau neu erhoben.
- **Abhängigkeit auf T3** entfernt; alle Punkte sind startbar.
Changelog: Befund aus der Handprüfung von #151 auf dem Windows-Zielsystem (2026-10-01).
Neu: Die eigene Ausgabe von wikitool kommt unter Copilot (pwsh) und unter Claude Code (Git Bash) falsch kodiert an: Fu�noten in doctor. Direkt in einem Konsolenfenster ist sie richtig. Dazu kommen Punkt 8 im Umfang (UTF-8 an einer Stelle, Kodierung von pwsh zuerst messen) und ein Kriterium auf dem Zielsystem.
Korrigiert: Den Pfad zu rg liefert schon .wikitool-tools.json aus #151. Der Satz „bis dahin weiter aus PATH“ in Punkt 6 und die Abhängigkeit auf #151 sind entfallen.
**Changelog:** Befund aus der Handprüfung von #151 auf dem Windows-Zielsystem (2026-10-01).
- **Neu:** Die eigene Ausgabe von `wikitool` kommt unter Copilot (pwsh) und unter Claude Code (Git Bash) falsch kodiert an: `Fu�noten` in `doctor`. Direkt in einem Konsolenfenster ist sie richtig. Dazu kommen Punkt 8 im Umfang (UTF-8 an einer Stelle, Kodierung von pwsh zuerst messen) und ein Kriterium auf dem Zielsystem.
- **Korrigiert:** Den Pfad zu `rg` liefert schon `.wikitool-tools.json` aus #151. Der Satz „bis dahin weiter aus PATH“ in Punkt 6 und die Abhängigkeit auf #151 sind entfallen.
Changelog (2026-10-01): Punkt 8 gemessen und entschieden, Umbau begonnen.
Punkt 8: UTF-8 wird in tools/run_wikitool.py gesetzt. Grundlage ist die Messung: natives pwsh ibm850/utf-8, pwsh unter Copilot utf-8/utf-8. PYTHONUTF8 in den Launchern ist verworfen.
Offen (D-neu): Wird tools/wikitool … | Select-String im nativen pwsh-Fenster gepiped, dekodiert pwsh mit ibm850 – vorher wie nachher falsch. Möglich wäre: wikitool.ps1 setzt [Console]::OutputEncoding für die Dauer des Aufrufs auf UTF-8 und stellt es danach wieder her. Entscheidung beim Operator.
Abweichungen vom Umfang:
.gitattributes setzt raw/ und incoming/ auf -text, damit Quellen byte-genau bleiben (Unveränderlichkeit laut raw/CONTRACT.md).
newline= steht direkt am Aufruf, nicht in einem Helfer. Der Guard-Test hält das ohnehin, und ein Helfer bräuchte denselben Guard.
Mitgenommen: Der Guard prüft auch encoding= an jedem Text-Lese- und -Schreibzugriff. Dabei kam eine Fundstelle zutage (run_budget._load_state).
Mitgenommen: trace_ingest.py liest stdin als UTF-8-Bytes. Ein locale-dekodierter Read scheiterte unter Windows an Bytes, die in cp1252 undefiniert sind.
Restrisiko, nicht in diesem Paket:run_budget.status_command liest den Budget-Zustand ohne Lock. Unter Windows kann os.replace scheitern, wenn genau dann ein Leser die Datei offen hat. Das Zeitfenster ist klein.
**Changelog (2026-10-01):** Punkt 8 gemessen und entschieden, Umbau begonnen.
- **Punkt 8:** UTF-8 wird in `tools/run_wikitool.py` gesetzt. Grundlage ist die Messung: natives pwsh `ibm850`/`utf-8`, pwsh unter Copilot `utf-8`/`utf-8`. `PYTHONUTF8` in den Launchern ist verworfen.
- **Offen (D-neu):** Wird `tools/wikitool … | Select-String` im nativen pwsh-Fenster gepiped, dekodiert pwsh mit `ibm850` – vorher wie nachher falsch. Möglich wäre: `wikitool.ps1` setzt `[Console]::OutputEncoding` für die Dauer des Aufrufs auf UTF-8 und stellt es danach wieder her. Entscheidung beim Operator.
- **Abweichungen vom Umfang:**
- `.gitattributes` setzt `raw/` und `incoming/` auf `-text`, damit Quellen byte-genau bleiben (Unveränderlichkeit laut `raw/CONTRACT.md`).
- `newline=` steht direkt am Aufruf, nicht in einem Helfer. Der Guard-Test hält das ohnehin, und ein Helfer bräuchte denselben Guard.
- Mitgenommen: Der Guard prüft auch `encoding=` an jedem Text-Lese- und -Schreibzugriff. Dabei kam eine Fundstelle zutage (`run_budget._load_state`).
- Mitgenommen: `trace_ingest.py` liest stdin als UTF-8-Bytes. Ein locale-dekodierter Read scheiterte unter Windows an Bytes, die in cp1252 undefiniert sind.
- **Restrisiko, nicht in diesem Paket:** `run_budget.status_command` liest den Budget-Zustand ohne Lock. Unter Windows kann `os.replace` scheitern, wenn genau dann ein Leser die Datei offen hat. Das Zeitfenster ist klein.
Changelog: abgeschlossen (2026-10-01). Body auf den Endzustand gebracht.
d0f08d1 (8.0.0-beta.19), CI 484/485 grün.
Die native pwsh-Pipe bleibt laut Betreiber vorerst so.
Die Handprüfung auf dem Zielsystem (Fußnoten) liegt beim Nachlauf von #140.
**Changelog:** abgeschlossen (2026-10-01). Body auf den Endzustand gebracht.
- `d0f08d1` (8.0.0-beta.19), CI 484/485 grün.
- Die native pwsh-Pipe bleibt laut Betreiber vorerst so.
- Die Handprüfung auf dem Zielsystem (`Fußnoten`) liegt beim Nachlauf von #140.
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 (D8: Windows nativ, PowerShell 7).
Erledigt (2026-10-01):
d0f08d1, Kandidat 8.0.0-beta.19. CI grün: Run 484 (verifyundpwsh), Run 485 (release). Lokal vor dem Publish:pytest(1969 bestanden, 3 übersprungen),docs verifyundinstructions verifygrün. Die Handprüfung der Ausgabe auf dem Windows-Zielsystem führt der Nachlauf von #140 („Ausgabe ohne Kodierungsfehler“).Warum
Der Python-Code setzte an mehreren Stellen POSIX voraus. Im analysierten Lauf (#140) scheiterte
instructions verifyunter Windows an allen 23 Instruktionen. Weitere Stellen rechneten unter Windows falsch, ohne dass es jemand bemerkt hätte.Befund (erhoben auf 8.0.0-beta.18)
str(<pfad>.relative_to(...))stand an 15 Stellen außerhalb der Tests, darunter der Selbstreferenz-Vergleich intype_resolver.py, der jede Type-Spec-Validierung brach. Dazu kamen zwei Fehlermeldungen, die einen relativen Pfad erst später in einen String verwandelten..gitattributes. Mitcore.autocrlf=truebekam der Bash-Launchertools/wikitoolCRLF (env: 'bash\r').newline="\n"schrieben unter Windows CRLF. Das betraf den Byte-Vergleich der Skill-Kopien und die sha256-Summen indist upgrade.subprocess-Aufrufe mittext=Truedekodierten unter Windows mit der Locale (cp1252). Dazu kamen einread_text()ohneencoding(run_budget._load_state) undsys.stdinintrace_ingest.py.doctorzeigte unter Copilot (pwsh) und Claude Code (Git Bash)Fu�noten, direkt in einer Konsole dagegen richtig. Python schreibt unter Windows in eine Pipe mit cp1252.fcntlinrun_budget.pyundtelemetry/writer.py. Unter Windows fiel die Sperre still weg.rg --jsonliefert unter Windowskb\\comparisons\\COLLECTION.md, auch mit--path-separator /(T3).Umgesetzt
.gitattributesmit* text=auto eol=lf. Abweichung:raw/undincoming/sind-text, damit Quellen byte-genau bleiben (raw/CONTRACT.md, Regel „Immutable“).dist exportliefert die Datei aus. Die Renormalisierung des Index änderte nichts..as_posix(), auch die Rückfallzweige und die Fehlermeldungen.newline="\n"an jedem Text-Schreibzugriff. Abweichung: Es steht direkt am Aufruf, nicht in einem Helfer. Der Guard-Test hält es so oder so, und ein Helfer bräuchte denselben Guard.encoding="utf-8"an jedemsubprocess-Aufruf mittext=True.chemenu/filelock.py:flockunter POSIX,msvcrt.lockingunter Windows. Gesperrt wird ein Byte bei Offset 2³¹−2, weit hinter den Daten, weil Windows-Locks verpflichtend sind undtrace_ingest.pydie Trace sonst nicht lesen könnte. Bei Konkurrenz wird gewartet, wie beiflock. Die Lock-Datei des Budgets wird mitageöffnet statt mitw.search/ripgrep.py:_record_pathwandelt\in/, nur wennos.sep == "\\". Das Flag kommt nicht hinzu. Die Umwandlung ist verlustfrei, weil kein Windows-Pfadbestandteil und seit #155 kein Seitentitel ein\enthalten kann.tests/test_portability.py, per AST übertools/chemenuund die Skripte daneben intools/. Jeder Detektor wird zusätzlich mit seinem Defekt gefüttert, damit ein Guard nicht grün ist, nur weil er nichts findet. Sie schlagen fehl bei:str(...relative_to(...))undf"{...relative_to(...)}"newline=encoding=subprocess.*(text=True)ohneencoding=, dazu keinfrom subprocess importimport fcntl/msvcrtaußerhalb vonfilelock.pytools/run_wikitool.py, der einen Stelle für beide Launcher. Dort stelltreconfigurestdout und stderr vormain()um.[Console]::OutputEncoding=ibm850und$OutputEncoding=utf-8. Unter Copilot sind beideutf-8. pwsh dekodiert abgefangene Kindprozess-Ausgabe mit[Console]::OutputEncoding, deshalb reicht unter Copilot UTF-8 aus Python. Git Bash reicht die Bytes unverändert durch.PYTHONUTF8=1in beiden Launchern. Das wären zwei Stellen, und der geänderteopen()-Default würde ein fehlendesencoding=verdecken.trace_ingest.pyliest stdin als UTF-8-Bytes. Ein locale-dekodierter Read scheiterte an Bytes, die in cp1252 undefiniert sind (z. B.Ł= C5 81).tools/wikitoolim nativen pwsh-Fenster gepiped (| Select-String), dekodiert pwsh mitibm850. Das war vorher schon so. Die Alternative wäre, dasswikitool.ps1[Console]::OutputEncodingfür die Dauer des Aufrufs umstellt; sie ist zurückgestellt. Ohne Pipe ist die Ausgabe richtig.Akzeptanzkriterien
tools/wikitoolwird mit LF ausgecheckt:git check-attrmeldettext: autoundeol: lf(Testtest_every_text_file_is_checked_out_with_lf). Der Index ist durchgehendi/lf.rg -n 'str\([^)]*relative_to' tools/chemenu -g '!**/tests/**'findet nichts. Der Guard-Test schlägt beistr(...)und bei f-Strings fehl.tools/chemenuund intools/*.pyträgtnewline=(Guard-Test).subprocess-Aufruf mittext=Trueträgtencoding="utf-8"(Guard-Test).fcntl. Getestet mit ausgeblendetemfcntl-Import und einem Fake-msvcrt, einschließlich Offset, Positionserhalt und Warten bei Konkurrenz. Ein echter Windows-Lock läuft mangels Windows-Runner nicht (T12).kb/comparisons/COLLECTION.md. Ein Treffer in derselben Form auf eine Fixture-Seite trägt Schlüssel, Titel, Art, Collection und Summary. Unter POSIX-Trenner bleibt der Pfad unverändert (test_search.py).ßin eine Pipe UTF-8, auch unter simuliertemPYTHONIOENCODING=cp1252(test_portability.py).Auf dem Windows-Zielsystem zeigt– diese Handprüfung führt der Nachlauf von #140 („Ausgabe ohne Kodierungsfehler (#152)“), nicht dieses Paket.doctorFußnotenunter Copilot, Claude Code und in beiden Konsolenpytest,docs verifyundinstructions verifysind grün, lokal und in CI 484.Restrisiko, nicht in diesem Paket
run_budget.status_commandliest den Budget-Zustand ohne Lock. Unter Windows kannos.replacein_save_statescheitern, wenn genau dann ein Leser die Datei offen hat. Das Zeitfenster ist klein. Ein Paket entsteht erst, wenn es im Nachlauf auftritt.Version
minor – Windows-Fähigkeit, drop-in. Im Kandidaten 8.0.0-beta.19.
torben referenced this issue2026-09-30 13:22:48 +00:00
Changelog: T3 aus #140 eingearbeitet (2026-09-30):
--path-separator /wirkt nicht aufrg --json.dd885dbund werden vor dem Umbau neu erhoben.Changelog: Befund aus der Handprüfung von #151 auf dem Windows-Zielsystem (2026-10-01).
wikitoolkommt unter Copilot (pwsh) und unter Claude Code (Git Bash) falsch kodiert an:Fu�notenindoctor. Direkt in einem Konsolenfenster ist sie richtig. Dazu kommen Punkt 8 im Umfang (UTF-8 an einer Stelle, Kodierung von pwsh zuerst messen) und ein Kriterium auf dem Zielsystem.rgliefert schon.wikitool-tools.jsonaus #151. Der Satz „bis dahin weiter aus PATH“ in Punkt 6 und die Abhängigkeit auf #151 sind entfallen.Changelog (2026-10-01): Punkt 8 gemessen und entschieden, Umbau begonnen.
tools/run_wikitool.pygesetzt. Grundlage ist die Messung: natives pwshibm850/utf-8, pwsh unter Copilotutf-8/utf-8.PYTHONUTF8in den Launchern ist verworfen.tools/wikitool … | Select-Stringim nativen pwsh-Fenster gepiped, dekodiert pwsh mitibm850– vorher wie nachher falsch. Möglich wäre:wikitool.ps1setzt[Console]::OutputEncodingfür die Dauer des Aufrufs auf UTF-8 und stellt es danach wieder her. Entscheidung beim Operator..gitattributessetztraw/undincoming/auf-text, damit Quellen byte-genau bleiben (Unveränderlichkeit lautraw/CONTRACT.md).newline=steht direkt am Aufruf, nicht in einem Helfer. Der Guard-Test hält das ohnehin, und ein Helfer bräuchte denselben Guard.encoding=an jedem Text-Lese- und -Schreibzugriff. Dabei kam eine Fundstelle zutage (run_budget._load_state).trace_ingest.pyliest stdin als UTF-8-Bytes. Ein locale-dekodierter Read scheiterte unter Windows an Bytes, die in cp1252 undefiniert sind.run_budget.status_commandliest den Budget-Zustand ohne Lock. Unter Windows kannos.replacescheitern, wenn genau dann ein Leser die Datei offen hat. Das Zeitfenster ist klein.Changelog: abgeschlossen (2026-10-01). Body auf den Endzustand gebracht.
d0f08d1(8.0.0-beta.19), CI 484/485 grün.Fußnoten) liegt beim Nachlauf von #140.