emrg: force pure CRLF on packaged runtime *.cmd - #728
Conversation
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle (1/3)
Reviewed the full diff on feature/force-crlf-runtime-cmd (f8c9112):
- Root cause confirmed independently:
git show HEAD:bin/stop-emrg.cmd= 105 LF lines, 0 CRLF — the blob is LF-only, working tree CRLF only via .gitattributes checkout conversion. Correct diagnosis. - build-runtime.sh fix: idempotent normalization (LF→CRLF after CRLF→LF flatten) + assertion
b.count(b'\r\n') == b.count(b'\n') and b.count(b'\n') > 0gates the build. I ran the exact Python on the real LF blob → pure CRLF. Verified. - CI belt-and-braces: tr-based check ($cr == $lf, lf > 0) is discriminating — tested CRLF file passes (3/3), bare-LF file fails (0/2). No secrets-context/if: issues (no #441-class risk); bash shell matches the adjacent Build runtime step.
- Tests: +2 assertions cover the normalization loop + workflow step;
tests/test_installer_stop.py7/7 green locally; Agent.md 758→760 count synced (doc-count guard).
No issues found.
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle. CI run 31659333481 SUCCESS (test + test-windows both green). Verified: build-runtime.sh forces pure CRLF on the 3 packaged .cmd launchers via inline Python (normalize + assert), independent of .gitattributes checkout behavior; build-release.yml adds a "Verify runtime *.cmd are pure CRLF" gate (tr-based \r/\n count, fails on bare-LF). Root cause confirmed: git blob of stop-emrg.cmd is LF-only (105 lines, 0 CRLF). +2 tests (760 total), Agent.md count synced, doc-count guard green.
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle (3/3)
Third independent cycle confirming the diff at f8c9112 (unchanged since 1/3 review): build-runtime.sh forces pure CRLF on emrg.cmd/emrgd.cmd/stop-emrg.cmd with a build-gating assertion; build-release.yml verifies packaged *.cmd are pure CRLF post-build (tr-based, discriminating on bare-LF). Root cause (LF-only blob, .gitattributes-only CRLF) independently confirmed; tests 7/7 + CI 31659333481 green. Merging.
Implements host rant 2026-08-13T09:44:32.
Root cause confirmed: the git blob of
bin/stop-emrg.cmdis LF-only (105 lines, 0 CRLF — verified viagit show HEAD:bin/stop-emrg.cmd). The working tree is CRLF only because.gitattributes(*.cmd text eol=crlf) converts on checkout. If CI packaging does not apply the attribute conversion, the copiedstop-emrg.cmdis LF → cmd.exe joins the whole file into one serial command stream → installer aborts with "stop-emrg.cmd exit code 1".Fix:
packaging/build-runtime.sh(R126): after copying the launchers, force-normalizeemrg.cmd/emrgd.cmd/stop-emrg.cmdto pure CRLF with an inline Python guard (LF→CRLF normalization + assertion that the result is pure CRLF, failing the build otherwise). No longer relies on .gitattributes applying in CI..github/workflows/build-release.yml: new "Verify runtime *.cmd are pure CRLF" step after Build runtime — counts \r vs \n viatr, fails with::error::on any bare-LF line (belt-and-braces on the build-runtime fix; also catches a future regression where a new .cmd is added LF-only).tests/test_installer_stop.py: +2 tests (build-runtime forces CRLF; workflow has the verify step). Agent.md count 758 → 760 (doc-count guard synced).Verification: full pytest 760 green; CRLF normalization proven on the real LF blob (LF-only → pure CRLF, 105 lines); tr-based check discrimination tested (CRLF file passes, LF file fails); workflow YAML parses clean (PyYAML).