diff --git a/CHANGELOG.md b/CHANGELOG.md index 07ed1ea4..fb8f992f 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(_common): **an `export KEY=value` line in `toolkit.env` now sets KEY**: `mxtk_load_env` squeezed all whitespace out of the key, so `export MENDIX_APP=...` set a variable named `exportMENDIX_APP` and the override did nothing, although the function's own comment says that form works. `KEY = "value"` also kept its quotes (the quote strip ran before the trim); the trim now runs first. Pure bash, no extra process per line. Fixture `tests/wave2/test-common-windows.sh` case 4b (#579). — triage of #579 - fix(exec): **a write no longer leaves units that changed only in XPath whitespace for the reviewer to read.** mxcli v0.27.0's `alter entity … rename attribute` rewrote 135 units in 20 unrelated modules that way (mendixlabs/mxcli#1596; fixed upstream in v0.29.0, ako/mxcli#1506, so this is insurance for projects on v0.27–v0.28). `exec.sh` now runs `model-scope.py restore` after the write (MDL and `--patch`) and before the mxbuild gate, so the gate checks the final model; it prints the real changes per module and puts a `scope:` note in the BUILD-LOG row. It never blocks: a failure is a warning, `MXTK_NO_SCOPE=1` skips it, and it is skipped when `FORCE_EXEC` let the write run over uncommitted model changes. No pre-commit refusal (maintainer decision on #593): `model-scope.py check --staged` stays available to run by hand. Fixture `tests/wave2/test-model-scope.sh` section F. Ported from #593 onto current master — saingge - learn(demo): **`skills/live-demo-autopilot.md` — run the demo live, not as a video**: Playwright drives the real app through scripted scenes, captions carry a WHY line, a control panel lets the presenter pause and take over, redo or skip; plus the traps that each broke a run (trial licence stops the runtime 2–4 h after start, 6-session cap and proving a logout freed its slot by the `System.Session` count, demo sign-in tiles kept out of any deployed build, focus-stealing panel pausing the run, SIGTERM closing the browser before sign-out). Field: a desktop+phone offline manufacturing demo (4/4 scenes) and a three-app process-hub demo (28/28 with an app killed mid-run and an 11 min pause), 2026-10 — Maurits Visser - docs(bug-ledger): **32 ledger entries now say what mxcli v0.22–v0.29 changed about them, before anyone re-runs an old workaround**: 22 are fixed upstream per the mxcli changelog or source (among them BUG-121 terminators, BUG-141 workflow PersistentId, BUG-151 `rest call body $Var`, BUG-100 shared Docker stack, BUG-94 role visibility, BUG-128 module-role idempotence) and 10 changed shape or are partly fixed (BUG-154; BUG-04 no automatic module role since v0.27, BUG-WF04/WF05 named call arguments since v0.25, BUG-130/131 vs the v0.27 `exec` rollback). Each gets an "Upstream status" line naming the version, the issue and what to retest; none is closed or archived, because none was retested — the ledger archives only after a retest. Also corrects `BUG-DRAFT-audit-member-access-ce0066`: commit `2455ee9f` first shipped in v0.23.0, not v0.22. Source: mxcli v0.29 compatibility audit 2026-10-30 diff --git a/project-bin/_common.sh b/project-bin/_common.sh index 551e0956..290a3e5c 100755 --- a/project-bin/_common.sh +++ b/project-bin/_common.sh @@ -162,12 +162,16 @@ mxtk_load_env() { line=${line%$'\r'} case "$line" in ''|'#'*) continue ;; esac case "$line" in *=*) ;; *) continue ;; esac - key=$(printf '%s' "${line%%=*}" | tr -d '[:space:]'); val=${line#*=} + # Drop a leading `export ` before squeezing whitespace, or the key reads as exportKEY. + key=${line%%=*}; key=${key#"${key%%[![:space:]]*}"} + case "$key" in export[[:space:]]*) key=${key#export} ;; esac + key=$(printf '%s' "$key" | tr -d '[:space:]'); val=${line#*=} case "$key" in [A-Za-z_]*) ;; *) continue ;; esac case "$key" in *[!A-Za-z0-9_]*) continue ;; esac # export KEY=value and "KEY = value" both work; surrounding quotes are stripped. - case "$val" in \"*\") val=${val#\"}; val=${val%\"} ;; \'*\') val=${val#\'}; val=${val%\'} ;; esac + # Trim first, so `KEY = "value"` still has its quotes at the edges when they are stripped. val=$(printf '%s' "$val" | sed 's/^[[:space:]]*//; s/[[:space:]]*$//') + case "$val" in \"*\") val=${val#\"}; val=${val%\"} ;; \'*\') val=${val#\'}; val=${val%\'} ;; esac val=$(mxtk_posix_path "$val") # Already set (by the shell, or by the project file on the previous pass) — keep it. eval "[ -n \"\${$key:-}\" ]" && continue diff --git a/tests/wave2/test-common-windows.sh b/tests/wave2/test-common-windows.sh index 700eff23..0264e7a0 100644 --- a/tests/wave2/test-common-windows.sh +++ b/tests/wave2/test-common-windows.sh @@ -78,6 +78,16 @@ OUT=$(run_in "$P" "$T/user-home" "" 'echo "$MENDIX_APP"') [ "$OUT" = "/c/Program Files/Mendix/11.11.0" ] && ok "converted (-> $OUT)" || fail "not converted (-> $OUT)" rm -f "$P/.claude/toolkit.env" +# ── 4b: mxtk_load_env — `export KEY=value` lines, quoted values (#579) ─────── +# The key used to be read with all whitespace squeezed out, so `export MENDIX_APP=...` set a +# variable named exportMENDIX_APP and MENDIX_APP stayed empty. Quotes after `= ` were kept too. +echo "== 4b: mxtk_load_env — export KEY=value, quoted, and spaced forms ==" +printf 'export MENDIX_APP=/from/export\n export\tMXCLI_VERSION="0.29.0"\nPYTHON = "/q/py"\nexportX=1\n' > "$P/.claude/toolkit.env" +OUT=$(run_in "$P" "$T/user-home" "" 'echo "${MENDIX_APP:-}|${MXCLI_VERSION:-}|${PYTHON:-}|${exportX:-}|${exportMENDIX_APP:-}"') +[ "$OUT" = "/from/export|0.29.0|/q/py|1|" ] && ok "export/quoted/spaced keys read (-> $OUT)" \ + || fail "export/quoted/spaced keys misread, want '/from/export|0.29.0|/q/py|1|' (-> $OUT)" +rm -f "$P/.claude/toolkit.env" + # ── 5: mxtk_is_elf — a real ELF binary is reported true ────────────────────── echo "== 5: mxtk_is_elf — a real ELF binary ==" OUT=$(run_in "$P" "$T/user-home" "" "mxtk_is_elf '$REAL_ELF' && echo yes || echo no")