From b9f6adb18311ed7c5df0d6a226f5e683032879a5 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 20 Oct 2026 12:45:25 +0000 Subject: [PATCH 1/2] fix(tests): match the non-ASCII line by exact bytes in look-ledger hook-repair H7 Under LC_ALL=C the u-umlaut is two bytes and grep "f.r" matched one, so H7 failed with the settings file intact. Match the whole line by exact bytes (grep -qxF with an octal-escaped printf). 13/13 under C, POSIX and C.UTF-8; master is 12/13 under C. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01VJgWP5vEoAsNsJYqCDMGNw --- CHANGELOG.md | 1 + tests/wave2/test-look-ledger-hook-repair.sh | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e3d036a8..9adba8af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ Sections dated before 2026-09-19 predate the cycle and stay as they are. Named m ## Unreleased +- fix(tests): **`test-look-ledger-hook-repair.sh` H7 no longer fails under `LC_ALL=C`.** It checked the kept non-ASCII line with `grep '^ "note": "f.r"'`; under the C locale `ü` is two bytes and `.` matches one, so H7 failed with the file intact (seen while scoping #487's fixtures). It now matches the exact bytes of the whole line (`grep -qxF` with an octal-escaped `printf`). Before: 12/13 under `LC_ALL=C`, 13/13 under `C.UTF-8`; after: 13/13 under C, POSIX and C.UTF-8. — MendixMau - fix(gates): **a decision taken during a stage no longer reads as that stage's approval** (#477). The #207 flag prefixed a FAIL with `APPROVED OVER A FAILING GATE` whenever any CONFIRMED row carried the stage's number, so a Stage-5 build with `| 5 | Sub-agents run on Sonnet | CONFIRMED |` was flagged, and `status.sh` told the lead to re-open an approval nobody gave while the real gap (PENDING obligations) sat underneath. The register has no dedicated exit row, so `gate-check.sh` now counts a stage as approved on either of two pieces of evidence in the Decisions table: an explicit exit row ("Stage N approved", "Stage 4 — approved with conditions", "Approved: Stage N …", "Gate approved", or " approved" for a fixed artifact list such as "Build plan approved"), or the stage having CONFIRMED rows of its own plus a CONFIRMED decision for a later stage up to 6 (the #207 field case); an early Stage-7 "no cutover" row or an N/A/skip row is not evidence. The Stage 3/4 gate checks and every verdict and exit code are unchanged. `test-bug03-gates.sh` T17 (16 cases, checked under gawk, mawk and original-awk): 7 FAIL on master, 47/47 with the fix. — MendixMau - fix(progress-report): **the build plan is shown once: the phase cards are the plan.** Expanding a card now shows its full rows (#, Kind, Step, Produces/Proves, Depends on, State, Scripts) and Claims, which only the duplicate "Full plan tables" block carried; that block is gone and views A (script folders) and B (module proof) are their own section. The `now` phase renders open with a selected style, opening another phase closes the previous one (accordion; `#phase-N` links still open their card), and a viewer's saved open/closed state survives the 30 s reload and wins over the default (#474) — field feedback from a requirements-driven project at Stage 5 — MendixMau (field feedback 2026-10-20) diff --git a/tests/wave2/test-look-ledger-hook-repair.sh b/tests/wave2/test-look-ledger-hook-repair.sh index 3a08a312..7eebf937 100755 --- a/tests/wave2/test-look-ledger-hook-repair.sh +++ b/tests/wave2/test-look-ledger-hook-repair.sh @@ -86,7 +86,9 @@ out="$("$TK/bin/sync-project.sh" "$D" 2>&1)" E="$WORK/fmt"; mkdir -p "$E/.claude" printf '{\n "note": "f\xc3\xbcr",\n "hooks": {}\n}\n' > "$E/.claude/settings.json" "$TK/bin/install-claude-permissions.sh" "$E" --hooks-only >/dev/null 2>&1 -{ ! grep -q '"permissions"' "$E/.claude/settings.json" && grep -q '^ "note": "f.r"' "$E/.claude/settings.json" \ +# Exact bytes, whole line: `f.r` matched only where the locale is UTF-8 (under LC_ALL=C the ü is +# two bytes, `.` matches one, and H7 failed with the file intact). +{ ! grep -q '"permissions"' "$E/.claude/settings.json" && grep -qxF "$(printf ' "note": "f\303\274r",')" "$E/.claude/settings.json" \ && grep -q 'look-ledger.sh seen' "$E/.claude/settings.json" && ! ls "$E/.claude"/*.bak* >/dev/null 2>&1; } \ && ok "H7: --hooks-only adds no empty allow/deny, no .bak, keeps 4-space indent and non-ASCII" \ || bad "H7: --hooks-only reformatted or added keys" "$(cat "$E/.claude/settings.json")" From 44bd3cde0911a672ea74235944a1c05e692e55bc Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 20 Oct 2026 12:56:21 +0000 Subject: [PATCH 2/2] fix(tests): strip CRs before the exact-bytes H7 match (#491 review) The settings writer emits CRLF on native Windows Python; grep -x then misses the line on its trailing CR. Strip CRs first, through a here-string because the fixture runs under pipefail. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01VJgWP5vEoAsNsJYqCDMGNw --- CHANGELOG.md | 2 +- tests/wave2/test-look-ledger-hook-repair.sh | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9adba8af..711e3b3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,7 @@ Sections dated before 2026-09-19 predate the cycle and stay as they are. Named m ## Unreleased -- fix(tests): **`test-look-ledger-hook-repair.sh` H7 no longer fails under `LC_ALL=C`.** It checked the kept non-ASCII line with `grep '^ "note": "f.r"'`; under the C locale `ü` is two bytes and `.` matches one, so H7 failed with the file intact (seen while scoping #487's fixtures). It now matches the exact bytes of the whole line (`grep -qxF` with an octal-escaped `printf`). Before: 12/13 under `LC_ALL=C`, 13/13 under `C.UTF-8`; after: 13/13 under C, POSIX and C.UTF-8. — MendixMau +- fix(tests): **`test-look-ledger-hook-repair.sh` H7 no longer fails under `LC_ALL=C`.** It checked the kept non-ASCII line with `grep '^ "note": "f.r"'`; under the C locale `ü` is two bytes and `.` matches one, so H7 failed with the file intact (seen while scoping #487's fixtures). It now matches the exact bytes of the whole line (`grep -qxF` with an octal-escaped `printf`), with CRs stripped first, so it holds under any locale and CRLF (the settings writer emits CRLF on native Windows Python). Before: 12/13 under `LC_ALL=C`, 13/13 under `C.UTF-8`; after: 13/13 under C, POSIX and C.UTF-8. — MendixMau - fix(gates): **a decision taken during a stage no longer reads as that stage's approval** (#477). The #207 flag prefixed a FAIL with `APPROVED OVER A FAILING GATE` whenever any CONFIRMED row carried the stage's number, so a Stage-5 build with `| 5 | Sub-agents run on Sonnet | CONFIRMED |` was flagged, and `status.sh` told the lead to re-open an approval nobody gave while the real gap (PENDING obligations) sat underneath. The register has no dedicated exit row, so `gate-check.sh` now counts a stage as approved on either of two pieces of evidence in the Decisions table: an explicit exit row ("Stage N approved", "Stage 4 — approved with conditions", "Approved: Stage N …", "Gate approved", or " approved" for a fixed artifact list such as "Build plan approved"), or the stage having CONFIRMED rows of its own plus a CONFIRMED decision for a later stage up to 6 (the #207 field case); an early Stage-7 "no cutover" row or an N/A/skip row is not evidence. The Stage 3/4 gate checks and every verdict and exit code are unchanged. `test-bug03-gates.sh` T17 (16 cases, checked under gawk, mawk and original-awk): 7 FAIL on master, 47/47 with the fix. — MendixMau - fix(progress-report): **the build plan is shown once: the phase cards are the plan.** Expanding a card now shows its full rows (#, Kind, Step, Produces/Proves, Depends on, State, Scripts) and Claims, which only the duplicate "Full plan tables" block carried; that block is gone and views A (script folders) and B (module proof) are their own section. The `now` phase renders open with a selected style, opening another phase closes the previous one (accordion; `#phase-N` links still open their card), and a viewer's saved open/closed state survives the 30 s reload and wins over the default (#474) — field feedback from a requirements-driven project at Stage 5 — MendixMau (field feedback 2026-10-20) diff --git a/tests/wave2/test-look-ledger-hook-repair.sh b/tests/wave2/test-look-ledger-hook-repair.sh index 7eebf937..33a85d87 100755 --- a/tests/wave2/test-look-ledger-hook-repair.sh +++ b/tests/wave2/test-look-ledger-hook-repair.sh @@ -87,8 +87,10 @@ E="$WORK/fmt"; mkdir -p "$E/.claude" printf '{\n "note": "f\xc3\xbcr",\n "hooks": {}\n}\n' > "$E/.claude/settings.json" "$TK/bin/install-claude-permissions.sh" "$E" --hooks-only >/dev/null 2>&1 # Exact bytes, whole line: `f.r` matched only where the locale is UTF-8 (under LC_ALL=C the ü is -# two bytes, `.` matches one, and H7 failed with the file intact). -{ ! grep -q '"permissions"' "$E/.claude/settings.json" && grep -qxF "$(printf ' "note": "f\303\274r",')" "$E/.claude/settings.json" \ +# two bytes, `.` matches one, and H7 failed with the file intact). CRs stripped first: the +# settings writer emits CRLF on native Windows Python, and -x would then miss the line. A +# here-string, not `tr | grep -q`: this file runs under pipefail (test-pipefail-grep-q.sh). +{ ! grep -q '"permissions"' "$E/.claude/settings.json" && grep -qxF "$(printf ' "note": "f\303\274r",')" <<<"$(tr -d '\r' < "$E/.claude/settings.json")" \ && grep -q 'look-ledger.sh seen' "$E/.claude/settings.json" && ! ls "$E/.claude"/*.bak* >/dev/null 2>&1; } \ && ok "H7: --hooks-only adds no empty allow/deny, no .bak, keeps 4-space indent and non-ASCII" \ || bad "H7: --hooks-only reformatted or added keys" "$(cat "$E/.claude/settings.json")"