PowerShell 5.1 reads a .ps1 with no BOM using the ANSI code page. Every
byte of a UTF-8 Chinese character is >= 0x80, so GBK pairs them up two at
a time; a comment line carrying an odd number of those bytes pairs its
last byte with the trailing newline and swallows it, folding the next
line into the comment. That commented out the `try {` I had added and
left `} catch { }` orphaned, which is the parse error reported at
startup — and it shifted the line numbers, which is why the earlier
PowerShell error positions never matched the file.
My previous Chinese comment survived only because its byte count happened
to be even. Both scripts are back to ASCII, matching the English already
used throughout them, with a note saying why it matters.
Also restores CRLF: .gitattributes marks *.ps1 eol=crlf, and rewriting
these files from Python had left them LF in the working tree.
Verified this time rather than handed over untested: Windows PowerShell
is reachable from WSL, so both scripts were parse-checked and run with
-ValidateConfigOnly, and the chcp block was executed on its own
(code page 65001, console encoding utf-8).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The startup output was dominated by two upstream behaviours. Migrate
printed a bare count for every already-applied migration — a lone "1"
with no version, no explanation — through the standard logger, hence
stderr, which the launcher's `2>&1 |` renders as a red PowerShell error
block that looks like a failed migration. And the version-existence check
echoed one SELECT count(*) per version. Both replaced: a Warn-level
session for the check, and one summary line on stdout.
Console encoding needed more than [Console]::OutputEncoding: PowerShell
5.1 decodes child-process output by the console code page, so chcp 65001
goes with it.
The regression test capture was wrong twice and mutation testing caught
both. It captured only stdout while the bug wrote to stderr, and it
compared lines to "1" when the logger prefixes a timestamp, so the
assertion could never fail. It now captures the standard logger too and
matches with a pattern that allows the prefix — verified by reinstating
the bug and watching the test fail.
Not verified: the PowerShell edits, which need a Windows run.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The startup log proved config.yaml was not being found during migrate.
Lookup covered the working directory and the executable's directory, but
the server runs from server/ while config.yaml sits at the repository
root — so it was found only when a launcher happened to export
GOAUTO_CONFIG. Anyone running `go run .` by hand got no local config at
all. Search the parent directory too, with the working directory still
winning.
The diagnostics also wrote to stderr, and the launcher pipes the server
through `2>&1 | Tee-Object`, which turns every stderr write into a
PowerShell NativeCommandError. The informational line I added to make
this debuggable was itself rendering as a red error block. They go to
stdout now.
Launchers set the console to UTF-8: Go writes UTF-8 while the console
decodes as the ANSI code page, which turned every Chinese log line into
mojibake.
Verified by running the built binary from server/ with no GOAUTO_CONFIG
set: it loads ../config.yaml and the lines survive 2>/dev/null.
Not verified: the two PowerShell edits, which need a Windows run.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>