Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ three commits past it), and a bug report can name a release instead of a sha nob
Sections dated before 2026-09-19 predate the cycle and stay as they are.

## Unreleased
- fix(project-bin/_common.sh): **Studio Pro and JDK discovery now match the model instead of always taking the newest thing installed.** `find_sp_app` used to `sort -V | tail -1` over every installed Studio Pro root regardless of the model's own Mendix version, so a project built against a newer Studio Pro's mxbuild than it targets; it now reads the model's version straight from the `.mpr` (a new `project_mendix_version`, SQLite via the existing `resolve_py`, with a self-verifying `strings` fallback for a Python-less machine) and prefers the matching install when more than one exists, falling back to newest with a named `WARNING:` only when no match is found. `find_java` accepted the first directory that merely existed, with no check that it was a JDK rather than a JRE, so a javac-less JRE could be returned while a real JDK sat unused; every tier from Studio Pro's bundled runtime onward now requires `bin/javac` (`_mtk_has_javac`), and a new well-known-JDK-roots tier (macOS `/Library/Java/JavaVirtualMachines`, Windows Adoptium/Java/Microsoft install dirs, Linux `/usr/lib/jvm`) is probed before the PATH fallback, preferring JDK 21 for a Mendix 11.x model (the only version mapping this repo documents) and saying so (`WARNING:`/`NOTE:`) when it has to guess. `bin/doctor.sh` now echoes that reasoning in its report instead of only naming the path chosen. Verified against a real Mendix 11.12.1 `.mpr` (exact SQLite schema check) and fake multi-install/multi-JDK fixtures on this machine (Linux); the macOS `java_home`/`/Applications` and Windows `Program Files` branches are exercised only by env-var simulation here, not a real Mac or Windows box — doctor.sh field report, macOS with several Studio Pro versions
- learn(skills/learned-file-upload-widget.md): **a file upload mxcli can author, with proof that it uploads.** The Mendix File Uploader 2.5.0 bound to a `System.FileDocument` specialisation: the MDL shape (entities, grants, create/delete microflows, advanced formats), which upload widgets mxcli cannot author (classic FileManager, PDS uploader), the two traps with workarounds (a simple-mode `allowedfileformat` passes exec and fails `mx check` with CE0463; an uploader DESCRIBE will not re-exec, `exposes 2 datasources`), and the six-step upload instrument. Field run on stock v0.24.0: the section-4 MDL taken verbatim from the skill gave `mx check` 0 errors, 2/2 files stored, 2/2 downloads sha256-equal, `.csv` rejected with 0 rows; both traps reproduce unchanged on v0.24.0 — a Mendix app-rebuild project
- new(skills/mendix-best-practices-index.md): **one row per Mendix best-practice area: the Mendix docs page, the bundled `assess-quality` section, the toolkit skill that applies it before the write, and the `mxcli lint` rule that catches it after exec.** An index, not a copy — the practice text stays on the Mendix pages (17 URLs verified HTTP 200 on 2026-09-25) and in the mxcli-bundled skill; Mendix's own Best Practice Recommender rules (MXP001–016) anchor the performance rows, and four rows say out loud that no lint rule exists and the preflight checklist is the only check. Routed `all` agents, stages 3/5/6, group reference — Maurits Visser
- learn(skills/microflow-preflight.md, agents/mdl-agent.md): **a microflow now gets a tier before any MDL — Simple, Guided or Split-first — and Split-first means a posted split plan (thin orchestrator + one `SUB_` per responsibility, with signatures) that the user confirms first.** Prompted by a colleague's session refusing a long microflow as "too difficult" while the same task went through on a stronger model: the piece was too big, not the task. mdl-agent gains two rules — never hand back "too difficult", hand back the split plan; escalate one failing `SUB_` by name after one retry, never the whole script. Also records the mxcli team's answer on positioning: a standalone `mxcli layout` command — which on v0.24.0 and upstream main (2026-09-25) arranges domain models only (`--dry-run` on a scratch copy of a PoC model: 10 entity moves, no microflow), so the no-`@position` rule and the if-branch workaround stand until a microflow mode ships; noted in the bug ledger and `learned-microflow-patterns.md` — Maurits Visser
Expand Down
31 changes: 27 additions & 4 deletions bin/doctor.sh
Original file line number Diff line number Diff line change
Expand Up @@ -376,9 +376,23 @@ PROJECT_ROOT="${PROJECT_DIR:-$TOOLKIT_ROOT}"
# shellcheck disable=SC1091
. "$TOOLKIT_ROOT/project-bin/_common.sh"

SP_APP="$(find_sp_app 2>/dev/null || true)"
# doctor_find <outvar> <errvar> <cmd...> — one invocation, stdout (the path chosen) into
# <outvar> and stderr (find_sp_app/find_java's own WARNING/NOTE reasoning, when more than one
# candidate existed) into <errvar> — so the report below can say which root was picked and
# WHY in the discovery code's own words, rather than a second explanation that could drift
# from it. Two calls would risk exactly that drift for no benefit, since both are read-only.
doctor_find() {
local __ov="$1" __ev="$2" __ef __out; shift 2
__ef=$(mktemp "${TMPDIR:-/tmp}/doctor-find.XXXXXX")
__out=$("$@" 2>"$__ef") || true
eval "$__ov=\$__out"
eval "$__ev=\$(cat \"\$__ef\")"
rm -f "$__ef"
}

doctor_find SP_APP SP_APP_WHY find_sp_app
MXBUILD="$(find_mxbuild 2>/dev/null || true)"
JAVA_HOME_FOUND="$(find_java 2>/dev/null || true)"
doctor_find JAVA_HOME_FOUND JAVA_WHY find_java
JAVA_EXE="$(find_java_exe 2>/dev/null || true)"

# toolkit.env — the human-editable answer to "doctor guessed the wrong Studio Pro / Java".
Expand Down Expand Up @@ -410,9 +424,9 @@ install_toolchain() {
fi
note "downloading the mxbuild toolchain (mxcli setup mxbuild — same as the container build)..."
if (cd "$PROJECT_DIR" && "$PMXCLI" setup mxbuild -p "$(basename "$INSTALL_MPR")"); then
SP_APP="$(find_sp_app 2>/dev/null || true)"
doctor_find SP_APP SP_APP_WHY find_sp_app
MXBUILD="$(find_mxbuild 2>/dev/null || true)"
JAVA_HOME_FOUND="$(find_java 2>/dev/null || true)"
doctor_find JAVA_HOME_FOUND JAVA_WHY find_java
JAVA_EXE="$(find_java_exe 2>/dev/null || true)"
ok "toolchain downloaded to ~/.mxcli/mxbuild/ (shared cache, reused by every project)"
else
Expand Down Expand Up @@ -558,6 +572,10 @@ GATE_OK=1
# Studio Pro install (the root mxbuild and the bundled JRE are discovered under).
if [ -n "$SP_APP" ]; then
ok "Studio Pro install: $SP_APP"
# find_sp_app only writes to stderr when there was more than one install to choose between
# and it had to explain the choice (matched-version pick is silent; a mismatch/fallback
# names itself) — echo that reasoning here so the report says WHY, not just WHICH.
[ -n "${SP_APP_WHY:-}" ] && printf '%s\n' "$SP_APP_WHY" | while IFS= read -r l; do note "$l"; done
elif [ "$PLATFORM" = linux ]; then
warn "no Studio Pro install (none exists for Linux)."
note "A standalone mxbuild works instead: bin/doctor.sh --install <project-dir> downloads"
Expand Down Expand Up @@ -614,6 +632,11 @@ if [ -n "$JAVA_EXE" ] && [ -x "$JAVA_EXE" ]; then
JV="$("$JAVA_EXE" -version 2>&1 | grep -i 'version' | head -1)" || JV=""
if [ -n "$JV" ]; then
ok "java runs: $JV ($JAVA_EXE)"
# find_java only writes to stderr when it had to explain itself: JAVA_HOME/PATH lacking
# javac, a well-known JDK root chosen over others for matching Mendix's required major
# version, or a NOTE that no such mapping is documented for this model's version. Silence
# means the pick needed no explanation (JAVA_HOME set and fine, or Studio Pro's own JRE).
[ -n "${JAVA_WHY:-}" ] && printf '%s\n' "$JAVA_WHY" | while IFS= read -r l; do note "$l"; done
# mxbuild compiles the model's Java actions, which takes javac — a JRE has none. Studio
# Pro's bundled runtime is a JRE that mxbuild is paired with, so only flag a system Java.
case "$JAVA_HOME_FOUND" in
Expand Down
Loading
Loading