From 54cd0324ea426c512e44ff839dffe12099bebe7c Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 30 Oct 2026 23:31:42 +0000 Subject: [PATCH 1/3] Fix mxcli v0.29 compatibility; doctor advises the latest mxcli On mxcli v0.29.0, which doctor --install fetches by default, four instruments misread the new output: - fix property-sets MIXED rows: doctor now classifies them as "mixed" instead of rc 4 "could not classify". - The repair exits 1 while only MIXED remains. The apply step no longer lets exec.sh --patch roll back a repair that landed. - fix hashes now verifies MPR v1 with new wording. exec.sh reads both forms, so --patch on Mendix < 10.18 is verified again. - SHOW/list modules "Protected AddOn|Solution" in Source (v0.28+): page-scope and the rehost module list keep first-party Protected modules. Also in this change: - wf-add-path-terminators.py refuses below Mendix 10.21. - module-close notes the v0.29 docker check default. - The stale v0.24 pin advice is gone. - New: the normal doctor run advises when the project mxcli is behind the latest release, respects MXCLI_VERSION pins, stays quiet offline and never fails. Golden input was captured from the real v0.28.0/v0.29.0 binaries (CAPTURE files hold the sha256s and mutation steps). Against master the new cases fail: exec-hash-verify 4, property-sets 7, mxpatch 1, page-scope-protected 3, rehost-list-modules 1, doctor-mxcli-latest 8. Field run: page-scope.sh and doctor.sh against the real v0.29.0 and v0.28.0 binaries on the captured model. Master page-scope FAULTs on the Protected model and the fix counts its page. The doctor advice read v0.29.0 from the live release redirect. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_018LeNWZV2sVH62vkgfYh5u5 --- CHANGELOG.md | 1 + bin/doctor.sh | 102 +++++++++++++++--- bin/sync-project.sh | 9 +- pipelines/mendix-mpr/lib/own-modules.awk | 9 +- project-bin/exec.sh | 9 +- project-bin/module-close.sh | 3 + project-bin/page-scope.sh | 14 ++- project-bin/wf-add-path-terminators.py | 33 +++++- skills/harness-architecture.md | 2 +- skills/rehost-app.md | 2 +- skills/report-schema.md | 2 +- tests/wave2/fixtures/mxpatch/CAPTURE.txt | 18 ++++ .../fixtures/mxpatch/verify-stale-v0.29.0.err | 1 + .../mxpatch/verify-stale-v0.29.0.exit | 1 + .../fixtures/mxpatch/verify-stale-v0.29.0.out | 6 ++ .../mxpatch/verify-v1-mismatch-v0.29.0.err | 1 + .../mxpatch/verify-v1-mismatch-v0.29.0.exit | 1 + .../mxpatch/verify-v1-mismatch-v0.29.0.out | 6 ++ .../fixtures/mxpatch/verify-v1-v0.29.0.err | 1 + .../fixtures/mxpatch/verify-v1-v0.29.0.exit | 1 + .../fixtures/mxpatch/verify-v1-v0.29.0.out | 4 + .../fixtures/property-sets/CAPTURE-v0.29.txt | 31 ++++++ .../property-sets/fix-help-v0.28.0.txt | 23 ++++ .../property-sets/fix-help-v0.29.0.txt | 23 ++++ .../fix-property-sets-help-v0.28.0.txt | 41 +++++++ .../fix-property-sets-help-v0.29.0.txt | 60 +++++++++++ .../ps-after-apply-both-v0.29.0.err | 1 + .../ps-after-apply-both-v0.29.0.exit | 1 + .../ps-after-apply-both-v0.29.0.out | 5 + .../property-sets/ps-apply-both-v0.29.0.err | 1 + .../property-sets/ps-apply-both-v0.29.0.exit | 1 + .../property-sets/ps-apply-both-v0.29.0.out | 8 ++ .../property-sets/ps-dryrun-both-v0.29.0.err | 1 + .../property-sets/ps-dryrun-both-v0.29.0.exit | 1 + .../property-sets/ps-dryrun-both-v0.29.0.out | 9 ++ .../property-sets/ps-dryrun-mixed-v0.29.0.err | 1 + .../ps-dryrun-mixed-v0.29.0.exit | 1 + .../property-sets/ps-dryrun-mixed-v0.29.0.out | 5 + .../property-sets/version-v0.28.0.txt | 1 + .../property-sets/version-v0.29.0.txt | 1 + .../fixtures/rehost-list-modules/CAPTURE.txt | 6 ++ ...-modules-marketplace-protected-v0.29.0.txt | 8 ++ .../list-modules-protected-v0.29.0.txt | 8 ++ tests/wave2/fixtures/show-modules/CAPTURE.txt | 15 +++ ...modules-marketplace-protected-v0.29.0.exit | 1 + ...-modules-marketplace-protected-v0.29.0.out | 6 ++ .../show-modules-protected-v0.28.0.exit | 1 + .../show-modules-protected-v0.28.0.out | 6 ++ .../show-modules-protected-v0.29.0.exit | 1 + .../show-modules-protected-v0.29.0.out | 6 ++ .../show-modules-source-v0.29.0.exit | 1 + .../show-modules-source-v0.29.0.out | 6 ++ .../show-pages-in-myfirstmodule-v0.29.0.out | 5 + tests/wave2/test-doctor-mxcli-latest.sh | 82 ++++++++++++++ tests/wave2/test-exec-hash-verify.sh | 22 +++- tests/wave2/test-mxpatch.sh | 8 ++ tests/wave2/test-page-scope-protected.sh | 59 ++++++++++ tests/wave2/test-property-sets.sh | 37 ++++++- tests/wave2/test-rehost-list-modules.sh | 5 + 59 files changed, 690 insertions(+), 34 deletions(-) create mode 100644 tests/wave2/fixtures/mxpatch/verify-stale-v0.29.0.err create mode 100644 tests/wave2/fixtures/mxpatch/verify-stale-v0.29.0.exit create mode 100644 tests/wave2/fixtures/mxpatch/verify-stale-v0.29.0.out create mode 100644 tests/wave2/fixtures/mxpatch/verify-v1-mismatch-v0.29.0.err create mode 100644 tests/wave2/fixtures/mxpatch/verify-v1-mismatch-v0.29.0.exit create mode 100644 tests/wave2/fixtures/mxpatch/verify-v1-mismatch-v0.29.0.out create mode 100644 tests/wave2/fixtures/mxpatch/verify-v1-v0.29.0.err create mode 100644 tests/wave2/fixtures/mxpatch/verify-v1-v0.29.0.exit create mode 100644 tests/wave2/fixtures/mxpatch/verify-v1-v0.29.0.out create mode 100644 tests/wave2/fixtures/property-sets/CAPTURE-v0.29.txt create mode 100644 tests/wave2/fixtures/property-sets/fix-help-v0.28.0.txt create mode 100644 tests/wave2/fixtures/property-sets/fix-help-v0.29.0.txt create mode 100644 tests/wave2/fixtures/property-sets/fix-property-sets-help-v0.28.0.txt create mode 100644 tests/wave2/fixtures/property-sets/fix-property-sets-help-v0.29.0.txt create mode 100644 tests/wave2/fixtures/property-sets/ps-after-apply-both-v0.29.0.err create mode 100644 tests/wave2/fixtures/property-sets/ps-after-apply-both-v0.29.0.exit create mode 100644 tests/wave2/fixtures/property-sets/ps-after-apply-both-v0.29.0.out create mode 100644 tests/wave2/fixtures/property-sets/ps-apply-both-v0.29.0.err create mode 100644 tests/wave2/fixtures/property-sets/ps-apply-both-v0.29.0.exit create mode 100644 tests/wave2/fixtures/property-sets/ps-apply-both-v0.29.0.out create mode 100644 tests/wave2/fixtures/property-sets/ps-dryrun-both-v0.29.0.err create mode 100644 tests/wave2/fixtures/property-sets/ps-dryrun-both-v0.29.0.exit create mode 100644 tests/wave2/fixtures/property-sets/ps-dryrun-both-v0.29.0.out create mode 100644 tests/wave2/fixtures/property-sets/ps-dryrun-mixed-v0.29.0.err create mode 100644 tests/wave2/fixtures/property-sets/ps-dryrun-mixed-v0.29.0.exit create mode 100644 tests/wave2/fixtures/property-sets/ps-dryrun-mixed-v0.29.0.out create mode 100644 tests/wave2/fixtures/property-sets/version-v0.28.0.txt create mode 100644 tests/wave2/fixtures/property-sets/version-v0.29.0.txt create mode 100644 tests/wave2/fixtures/rehost-list-modules/list-modules-marketplace-protected-v0.29.0.txt create mode 100644 tests/wave2/fixtures/rehost-list-modules/list-modules-protected-v0.29.0.txt create mode 100644 tests/wave2/fixtures/show-modules/CAPTURE.txt create mode 100644 tests/wave2/fixtures/show-modules/show-modules-marketplace-protected-v0.29.0.exit create mode 100644 tests/wave2/fixtures/show-modules/show-modules-marketplace-protected-v0.29.0.out create mode 100644 tests/wave2/fixtures/show-modules/show-modules-protected-v0.28.0.exit create mode 100644 tests/wave2/fixtures/show-modules/show-modules-protected-v0.28.0.out create mode 100644 tests/wave2/fixtures/show-modules/show-modules-protected-v0.29.0.exit create mode 100644 tests/wave2/fixtures/show-modules/show-modules-protected-v0.29.0.out create mode 100644 tests/wave2/fixtures/show-modules/show-modules-source-v0.29.0.exit create mode 100644 tests/wave2/fixtures/show-modules/show-modules-source-v0.29.0.out create mode 100644 tests/wave2/fixtures/show-modules/show-pages-in-myfirstmodule-v0.29.0.out create mode 100755 tests/wave2/test-doctor-mxcli-latest.sh create mode 100755 tests/wave2/test-page-scope-protected.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b057dda..fcdf4954 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(doctor, exec, page-scope, rehost, wf-add-path-terminators, module-close): **mxcli v0.29 compatibility, and doctor advises the latest mxcli**: on v0.29.0 (which `--install` fetches by default) four instruments read new output wrong. (1) `fix property-sets` prints `MIXED` rows and exits 1: doctor reported "could not classify" (rc 4, shown as info by sync) — now result `mixed`, a WARN naming the rows and saying the repair cannot clear them; (2) the repair also exits 1 while a MIXED name remains, so `--fix-property-sets` rolled back a repair that had landed — the apply step now passes when only MIXED is left (FAILED still fails); (3) `fix hashes` now verifies MPR v1 with new text, which exec.sh read as an error, so every `--patch` on a Mendix < 10.18 project went unverified — both v1 forms are read; (4) since v0.28 `SHOW MODULES` / `list modules` write `Protected AddOn|Solution` in Source, so a first-party module set to Protected dropped out of page-scope (FAULT, 0 modules) and out of the rehost module list — the export level no longer counts as an origin. `wf-add-path-terminators.py` refuses below Mendix 10.21 (the terminator type does not exist there; written in, the project will not load), module-close notes that v0.29 `docker check` checks the stored project (a CE0463 it now reports is real), and the stale "stay on v0.24" pin advice is replaced. **New:** the normal doctor run compares the project mxcli with the latest release (redirect of the asset URL, 5 s, nothing downloaded): WARN with release link and upgrade path when behind, a note when `MXCLI_VERSION` pins it, one quiet note offline, never a FAIL; `MXTK_NO_LATEST_CHECK=1` skips it. Golden input captured from the real v0.28.0/v0.29.0 binaries on the mxpatch fixture model and mutated copies (CAPTURE files); against master the new cases fail (exec-hash-verify 4, property-sets 7, mxpatch 1, page-scope-protected 3, rehost-list-modules 1, doctor-mxcli-latest 8). Field run: page-scope and doctor against real v0.29.0/v0.28.0 binaries in a cloud session — mxcli v0.29 audit (2026-10-30) - fix(doctor, sync-project, speed-setup): **doctor says when the speed fixes never reached a project**: `bin/exec.sh`, `bin/_common.sh` or `bin/lint-gate.sh` without the 2026-10-29 speed code (marker per file) gives a Machine health warning "speed fixes not active", and the Recommended fix leads with the exact `sync-project.sh --upgrade-bin ...` command (exec.sh always with its `_common.sh`; each copy backed up) before any other advice, because every other number measures the old scripts; `sync-project.sh` names the speed fixes on a hand-edited exec.sh / _common.sh that has the exit-code fix but not the speed work; `skills/speed-setup.md` has Claude show each local edit in one line and ask before replacing. Field: an English colleague's ExpenseTracker analysis after the toolkit update still showed a full mxbuild on every change (45.5 min, 57% of all exec time) with 15 drifted scripts in bin/; reproduced here with the real pre-#587 exec.sh / _common.sh / lint-gate.sh — doctor names all three, sync names exec.sh and refreshes the two unedited ones — Maurits (mauritscgvisser) - fix(doctor, speed-setup): **doctor no longer says "None needed" next to a verdict of "5x slower"**: when process starts are fast but one bench step is 5x+ the reference and 2 s+ slower, the Recommended fix names that step (slow git status: `git config core.untrackedCache true` / `core.fsmonitor true`, no admin rights); a project inside a OneDrive / Dropbox / Google Drive / iCloud folder gets a Machine health warning and "move the project to a local folder" as the fix; low-memory advice now offers "restart the computer" before `--cleanup`; the bench's git step runs one untimed warm-up so a stale index after a copy or clone no longer reads as slow (field, ab-581/gk: 18.3 s cold, 31 ms warm); `skills/speed-setup.md` tells Claude never to say deno, mxbuild or helper process to a user. Field run: ab-581/gk on Linux, bench 14.7 s vs 10.9 s, "None needed" correctly; a project under a OneDrive path, move advice shown — Maurits (mauritscgvisser) - fix(gate-check, gate-cache): **the closeout verdict cache also keys on file CONTENT, so an overwrite that keeps an old mtime (`cp -p`, `rsync -t`, `tar x`, `unzip`, `touch -d`) can no longer replay a stale verdict**: a signed triage.md copied over a FAIL one still printed the cached Stage 0 FAIL (PR #589 review); the cache now stores one `find | sort | xargs cksum | cksum` signature of the project files (skipping .git, node_modules, .mxtk, mprcontents, deployment, *.mpr, files over 1 MB) and any difference, or a signature that cannot be computed, re-evaluates; new `tests/wave2/test-gate-cache.sh` (hit, edit/delete/waiver miss, cp -p miss, TTL 0, 'not evaluated' line); `MXTK_GATE_CACHE_TRACE=1` prints `gate-cache: hit|miss` on --closeout. Field run: ab-581/base copy (197 MB, 633 hashed files) - signature 28 ms, cache hit 1464 -> 1498 ms vs 2567-2786 ms full evaluation - PR #589 reviewer, OlafFede (#583) — OlafFede (#583) diff --git a/bin/doctor.sh b/bin/doctor.sh index 4601ae8d..1c3e0ae5 100755 --- a/bin/doctor.sh +++ b/bin/doctor.sh @@ -83,7 +83,18 @@ set -u # script and the repair inherits exec.sh's snapshot, mxbuild gate and restore. if [ "${2:-}" = "--property-sets-apply-step" ]; then { [ -n "${3:-}" ] && [ -x "$3" ]; } || { echo "--property-sets-apply-step: no runnable mxcli given" >&2; exit 2; } - exec "$3" fix property-sets -p "$1" + # mxcli v0.29.0+ also exits 1 while a MIXED name remains (cmd_fix_property_sets.go: "Exits 1 + # when a unit could not be repaired, when a MIXED name remains"), even when every repair it made + # landed. mxcli leaves MIXED units untouched, so that exit is not a failed repair: report 0 and + # let the gate decide, else exec.sh --patch rolls the good repairs back. FAILED still exits 1. + _psa_o="$("$3" fix property-sets -p "$1" 2>&1)"; _psa_r=$? + printf '%s\n' "$_psa_o" + if [ "$_psa_r" -eq 1 ] && printf '%s\n' "$_psa_o" | grep -q '^ MIXED ' \ + && ! printf '%s\n' "$_psa_o" | grep -qE '^ FAILED |could not be normalized'; then + echo "(exit 1 was for the MIXED name(s) above only — mxcli leaves those as they are; the repair stands)" + exit 0 + fi + exit "$_psa_r" fi TOOLKIT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" @@ -201,6 +212,10 @@ probe_runs() { # What the dry-run prints and how it exits is mxcli's cmd/mxcli/cmd_fix_property_sets.go at # v0.26.0: exit 0 = nothing to do; exit 1 = a ` NEEDS ` or ` FAILED ` row per unit, OR an # error such as "project not found" (both exit 1, so the rows decide, never the code alone). +# v0.29.0 adds ` MIXED ` rows (ako/mxcli#1505): a property name some elements of a type carry and +# others lack — Mendix's merge engine cannot compare those revisions, and mxcli leaves them alone +# (no measured value fills them). Exit 1 with only MIXED rows is result "mixed": a merge hazard +# the repair cannot clear, reported, never "could not classify" (captured 2026-10-30). # Anything else is "could not classify", never clean. Support is read from `mxcli fix --help` # listing the subcommand: `mxcli fix property-sets --help` exits 0 on v0.24/v0.25 too (cobra # prints the parent's help for an unknown subcommand), so it cannot be the probe. Golden @@ -209,7 +224,7 @@ probe_runs() { # The result is recorded in /.claude/.property-sets-receipt (machine-local, like the # doctor receipt): line 1 "