diff --git a/CHANGELOG.md b/CHANGELOG.md index 0922df5..7f65597 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -84,6 +84,7 @@ Sections dated before 2026-09-19 predate the cycle and stay as they are. - learn(skills/lint-that-actually-runs.md): **three more lint vocabulary facts, verified on v0.24.0, with a before/after rule.** `microflow_type` is `MICROFLOW`/`NANOFLOW`/`RULE`, and `microflows()` yields all three. SQL `PERSISTENT` is Starlark `Persistent`. `activity_count` counts top-level objects (splits, loops, annotations), not actions, and `activities_for()` does not see loop bodies. — field report from a colleague's naming-conventions project (mxcli v0.23.0, Mendix 11.12.4) - learn(skills/learned-microflow-patterns.md): **expression functions take positional arguments only — `toString(from: $X)` is not a syntax error, it's a silent misparse.** MDL's expression grammar has no named-argument form for function calls; `label: value` parses as `label` (a bare unresolved identifier) COLON-divided by `value` — COLON being the OQL division operator. Verified on mxcli v0.24.0 / Mendix 11.12.1, scratch copy of a PoC model: `toString(from: $Temperature)` and `formatDateTime($D, pattern: 'yyyy-MM-dd')` both pass `mxcli check --references` silently (exit 0) because the collapsed argument count still matches the function's arity; `substring(from: $S, index: 0, length: 3)` fails, but with a misleading `E006` ("expects 2 to 3 argument(s), got 1") that never names labelled arguments as the cause. The likely source: labelled-colon syntax is genuine MDL elsewhere (page `Attribute:`/`Action: MICROFLOW Name(Param: val)`, `@anchor(from: bottom, to: top)`) — just never inside an expression — workshop feedback, Sep 2026 - fix(bin/doctor.sh): **the gate self-test's scratch copy now carries the whole model directory, not just `.mpr` + `mprcontents/`.** A `--target=deploy` build (the same target the real gate runs, in place, against the project as it sits on disk) resolves widget/theme/design-property references out of `theme/`, `resources/`, `widgets/` and `javasource/` sitting beside the `.mpr`; a thin copy reported hundreds to over a thousand `Could not find widget` / design-property errors as a "dirty baseline" while the real gate passed with 0 errors on the identical model. Now copies the directory holding the `.mpr` (single-tree root or `app/` on a two-tree checkout) minus `.git/`, `deployment/`, `node_modules/` and `.mpr-snapshots/`, and prints the copied size (`du -sh`) so the cost is visible. Keeps the existing real-basename fix. A sibling `.mpr` in the project's own directory was ruled out (collides with the project's own `mprcontents/`); `mxbuild --target=check` was ruled out (no evidence it exists anywhere in this toolkit's usage) — field reports, issue #127 and a macOS custom-theme project +- fix(project-bin/exec.sh): **the mxbuild delta gate now keeps a write when the post-exec error set is a strict subset of the pre-flight baseline, not just when it is identical.** A script that took 34 pre-existing errors down to 1 was being rolled back and logged `blocked: PRE-EXISTING CE1613`, because the gate could only recognise "unchanged," never "reduced." The comparison key is unchanged (`err_set`'s per-message string); a new `is_subset_of` helper checks membership, and a set containing anything NEW still restores the snapshot exactly as before. The kept-write BUILD-LOG row now reads `⚠️ applied (dirty model, reduced)` with detail `errors 34→1 (pre-existing, reduced); remaining [...] still blocks deploy` — field report from a colleague's naming-conventions project (mxcli v0.23.0) - 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 diff --git a/README.md b/README.md index 35d27d6..a3cdd5b 100644 --- a/README.md +++ b/README.md @@ -313,7 +313,7 @@ Use this before every write. Full per-rule detail (root causes, bug IDs, retest | Drop an attribute that has security grants | Studio Pro GUI | N/A | | After any MPR corruption or load error | `bin/restore-mpr.sh` | Closed | -**The crash net.** An MPR is two parts: `Project.mpr` (SQLite index) and `mprcontents/` (BSON units). `bin/exec.sh` snapshots both before every batch; 5 rotate; `bin/restore-mpr.sh` rolls back both together (either alone is useless). Git commits at phase gates are the real history. Ad-hoc `.mpr.backup` copies are banned. +**The crash net.** An MPR is two parts: `Project.mpr` (SQLite index) and `mprcontents/` (BSON units). `bin/exec.sh` snapshots both before every batch; 5 rotate; `bin/restore-mpr.sh` rolls back both together (either alone is useless). Git commits at phase gates are the real history. Ad-hoc `.mpr.backup` copies are banned. By design, `exec.sh` refuses to run at all while the model has uncommitted changes — its snapshot would not cover them, so a later auto-restore could silently lose that work; commit the model first (`FORCE_EXEC=1` overrides, at your own risk). ### Something went wrong? Don't panic. diff --git a/project-bin/exec.sh b/project-bin/exec.sh index fc361b0..4f091c3 100755 --- a/project-bin/exec.sh +++ b/project-bin/exec.sh @@ -2,7 +2,15 @@ # exec.sh — the guard chain around a model write. # # concurrent-writer guard → module-brief advisory → mxcli check → snapshot → baseline → exec -# → mxbuild gate → auto-restore on regression → lint ratchet → SP reopen +# → mxbuild delta gate → auto-restore only on a NEW error → lint ratchet → SP reopen +# +# The mxbuild gate is a DELTA gate, not an absolute "0 errors" one: a write is kept +# when the post-exec error set is the pre-flight baseline exactly, or a strict +# SUBSET of it (every post-exec error message already existed before this script +# ran — nothing new, even if some were cleared). Only a set containing something +# new triggers the snapshot restore. See "Delta gate" below. +# Known limit: errors are compared by message text only, so a new error whose +# message matches one already in the baseline is not seen as new. # # Usage: ./bin/exec.sh # ./bin/exec.sh --patch