Skip to content
Merged
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
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ Kinds: `new` · `fix` · `learn` (a skill/learning) · `process` (rules, templat
Credit the person or project that surfaced the change — the credit line is the thank-you.

## 2026-09-08
- fix(bug-logs): re-probed the two workflow blockers on mxcli **v0.21.0** (released 2026-09-06, Mendix 11.13.0) — **both still open**, and BUG-76's diagnosis in this log was wrong. BUG-121 (`PARALLEL SPLIT`): the same script executed through v0.20.0 and v0.21.0 on two throwaway copies produces a **byte-identical** workflow unit (zero diff from `bson dump` after blanking the `$ID` GUIDs), so the runtime behaviour cannot have changed — and the path contents *are* present in the stored BSON on both versions, so the entry's own title ("writes the paths but not their contents") names the symptom, not the mechanism, which is still unidentified. BUG-76 (`DECISION`): not unconditional storage corruption but a **pincer between two spellings** — a bare outcome passes `mxcli check` and makes the model unloadable (`StorageLoadException`, "not a valid EnumerationValueIdentifier"), while a qualified one is rejected by mxcli's own `MDL-WF03` and loads clean via `exec --no-check` with a single `CE0117` for the empty expression; mxcli mandates the spelling the loader rejects and rejects the one it accepts, which implies two independent fixes rather than one. The correction was made on the source project on 2026-09-02 and never promoted here; it is already filed upstream as mendixlabs/mxcli#1031, so it goes into the draft as a comment to post rather than a rewritten body — a topbar-titled portal project · at merge: the three "disputed" `DECISION` notes on master (`mxcli-bugs.md` v0.20.0 clearance table, `learned-workflow-patterns.md` §1 pointer, §8 version table, §21 verdict table) now cite the resolved pincer diagnosis and the v0.21.0 re-probe instead of "shape-dependent, not isolated" — the toolkit merge queue

## 2026-09-07
- new(bug-logs): seven mxcli defects harvested from a topbar-titled portal project's build (mxcli v0.20.0, Mendix 11.13.0), each with an upstream draft — BUG-120 (three write-path asymmetries; the serious one: `ALTER ENTITY … ADD ATTRIBUTE` reconciles only the widest access rule and silently skips narrower ones — a valid model with wrong security), BUG-121 (`PARALLEL SPLIT` writes its paths but drops their contents: loads, passes every gate, deadlocks at run time — `workflow-structure-rules.md` §11's *proven* row retracted, plus a new CE6681 forward-`JUMP TO` row and the `$WorkflowUserTask`-not-in-call-microflow limit), BUG-122 (`ALTER PAGE … SET PageSize` rejects what `CREATE` accepts on the same widget), BUG-123 (`SHOW CALLERS OF` indexes neither page-button actions nor `show page` targets), BUG-124 (`DESCRIBE MICROFLOW` omits `without events`, so a round-trip silently re-enables event handlers), BUG-125 (`check --references` cannot resolve any enumeration — four A/B probes), BUG-126 (`ALTER PAGE … SET Label` prints "Altered page" and discards the value while `SET Class` applies and `SET Caption` errors by name). Renumbered at merge from 113–119, all seven of which master had taken while the branch was open; `bug-submission-checklist.md` §0 now states the merge-queue rule (`BUG-DRAFT-<slug>` in PRs) instead of "grep the toolkit and take the next number", which this branch did and still collided — a topbar-titled portal project, merged by the toolkit queue
- fix(gate-check): the stage Surface check now also looks in `<project>/analysis/` — `source-sufficiency.sh report` and `triage-report.sh` write there by default, but the check only probed the project root and the knowledge-base parent, so every fresh project reported both Stage 0 surfaces MISSING while they existed (seen on the first Stage 0 gate of a MOC/PSSR rebuild POC, 2026-09-08; verified `Surface present` after the fix) — a MOC/PSSR rebuild POC

## 2026-09-04
Expand All @@ -24,7 +28,6 @@ Credit the person or project that surfaced the change — the credit line is the

## 2026-09-03
- new(bug-logs): `pending-github-issues/render-paste-ready.sh` renders every NOT-YET-FILED draft into `paste-ready/<NN>-<slug>.md` (line 1 = title, rest = body, local header stripped mechanically) plus an `INDEX.md` in worst-first filing order with labels and the duplicate check done per issue; eight new drafts from the ledger's unfiled entries — BUG-102 (DataGrid `SET DataSource` silent no-op), BUG-104 (quoted `"$Param"` keeps the sigil), BUG-106 (widget names burned after rollback), BUG-107 (workflow `WITH` unquoted value segfault), BUG-109 (`JUMP TO` in boundary event), BUG-112 (`mxcli new` hangs on over-length path), BUG-100 (`docker init` without `COMPOSE_PROJECT_NAME`), STOP row 22 as an `exec` partial-application issue — and one feature request, `mxcli doctor`, written from `bin/doctor.sh`'s probe table. 22 issues paste-ready, 0 filed from this session (no `mendixlabs/*` access) — toolkit field review 2026-09-03
## 2026-09-08
- process(routing): the always-on word budget now counts what an agent READS — skill documents — not the scripts it runs by their usage line: the tier held 97,769 words of which 21,216 were `.sh` (verify-module, source-sufficiency, source-ledger, status …) and 3,527 a `.js`, none of which ever enter a context window. Documents-only total 73,026; ratchet set to 80,000 and the check is **strict again** (the same-day advisory detour existed only because the number was wrong); `MXTK_BASELINE_BUDGET_ADVISORY=1` for a deliberate re-ratcheting pass. Tier-membership questions (`learned-stylegallery`, `design-spacing`, `ui-loop` baseline for every mdl session?) are left for the maintainers — this PR fixes the metric, not the roster — the toolkit merge queue
- fix(tests): both fixture suites green again — `run-tests.sh` 19/19 and all 30 wave2 fixtures. Bisected, not patched over: every failure was a fixture left behind by two deliberate 2026-08-20 exit-code changes (`40c63ac` PENDING → exit 3; `cec7a1e` Stage 0 advisory → exit 0) that updated only the fixtures their authors ran — `test-surface-column` now asserts the verdict word is *unchanged* rather than a literal FAIL, `test-bug04-subscripts` expects the documented codes and discriminates PASS/FAIL by the verdict word, `run-tests.sh`'s project now has an examined question file so the open-questions guard has something to examine, `test-triage-report` asserts `Stage 0 (Triage): FAIL` with exit 0 and the reworded reason. `test-bug05` T7 depended on a pre-fix gate copy that only existed on its author's Mac; it now materialises `778c3ff^:bin/gate-check.sh` from history. No gate behaviour changed. Also found by wiring them in: `init-project.sh` registers a scaffolded project's name in the *toolkit's* gitignored denylist, so fixtures scaffolding `t0`..`t10` had been appending `\bt0\b`… to the developer's real list on every run (and created one in CI, where the guard then flagged 200 files); `MXTK_LEAKGUARD_DENYFILE` now overrides the target, every scaffolding fixture points it at scratch, and `run-all.sh` refuses if a root denylist appears. **process(ci):** both suites now run in `checks.yml`, after the guard — they were red for nineteen days while every PR showed green because nothing ran them — the toolkit merge queue
- fix(bin/sync-project.sh, bin/lib/triage-template.sh): **`sync-project.sh` overwrote a signed-off `triage.md`, destroying 73 lines of Stage 0 decisions** — recovered only because the project had committed it. Two independent defects in `mxtk_triage_is_pristine()`, either sufficient: (1) the completion marker a filler writes, `MXTK-TRIAGE-STUB-FILLED`, is a **substring** of the `grep -q 'MXTK-TRIAGE-STUB'` guard, so the suffix that exists to say "done" said nothing — now anchored, and `-FILLED` is checked first as an explicit *not pristine* signal; (2) the header-strip `awk` needed `<!--` **and** the marker on one line, and the shipped template does put them there — but an agent filling the file in naturally *reformats* that header (wrapping it, adding a "filled in" note), after which `skip` never turns on and the header's own explanatory `{{PLACEHOLDER}}` counts as a live unfilled slot, so the file tests pristine forever. Skip now triggers on the marker alone. Plus the guard that does not depend on a regex being right: **sync refuses to overwrite a `triage.md` git reports as modified**, before the predicate is consulted. This is the third instance of one bug class in this function (the `{{DOUBLE_BRACE}}` false positive, ~33 KB of agent files; the unstripped one-line header, 2026-08-20; this) — each fix narrowed the inference, none replaced it, which is what the git guard is for. `tests/wave2/test-triage-report.sh` gains 7 assertions built by *reformatting the real template* rather than inventing a header: the suite already claimed to cover "sync must not clobber work" and its worked-on fixture carried **no marker at all**, so it was kept for the trivial reason and never reached the logic where the defect lived — hand-written input encoding the same assumption as the code. Scoped run: 62 passed / 2 failed, the same 2 failing before the change — Maurits Visser, from a no-code app replacement project
Expand Down Expand Up @@ -55,7 +58,6 @@ Credit the person or project that surfaced the change — the credit line is the
- fix(gate-check --closeout): an early exit between the output capture and the emit point (nonexistent project dir, ambiguous register, --adopt/--waive misuse) used to vanish into the temp log — exit 1 with nothing on screen and the file left behind; an EXIT trap now restores the fds, prints what was captured, removes the file and keeps the exit code (probed: bad project path → message shown, rc=1, no temp file). Stage 7 no longer carries a hard-gate mark the runbook header does not — the toolkit merge queue, reviewing the stage-feedback-transition branch
- process(bug-logs): filed the BUG-120..126 harvest upstream — #1067 (write-path asymmetries), #1068 (parallel split writes paths without contents), #1069 (`ALTER PAGE SET PageSize`, citing #414 as the general case), #1070 (`DESCRIBE MICROFLOW` omits `without events`), #1071 (`check --references` cannot resolve enumerations). Dedupe redirected two: BUG-126 is mendixlabs/mxcli#292, open since April and the same bug, and BUG-123 is #773, closed as completed 2026-08-12 and still reproducing — both posted as reproductions on the existing issues rather than re-filed. Every draft carried a Mendix version but no mxcli version; v0.20.0 (from `mxcli-bugs.md`) is now in each Environment section, in the drafts as well as upstream. BUG-117 stays held pending its v0.20.0 retest, BUG-118 pending BUG-114 having an upstream issue at all — it has none — Maurits Visser, via the toolkit merge queue

## 2026-09-07
- learn(bug-logs): BUG-133 — **MDL cannot author a microflow that applies entity access**, and because CE0114 restricts the *caller*, that means no MDL-authored flow can call one that does, from anywhere: not a startup flow, not a button handler. Whole marketplace features become unreachable headlessly — the field case is Excel Importer 11.2.2's own `_USE_ME` startup check, which re-syncs Model Reflection and validates every import template, and which took two apply-and-restore cycles to establish was a wall rather than a wiring mistake. Ask: a grammar property plus rendering it in DESCRIBE, or failing that raise CE0114 in `check --references` where the callee's flag is readable. Plus BUG-131's fourth and fifth cases, whose new information is that the snapshot restore is **partial across document types** — two failed applies left the page edits and the startup-microflow edit while none of the three microflows the same script created survived, leaving a model more broken than either endpoint; "2122 units verified" is the one measure that cannot see it — a sales-coaching build (renumbered from BUG-120/118 at merge; master had taken 113–126 while the branch was open)
- learn(skills/bug-logs): control-bar buttons bind the grid selection, not `$currentObject` — `learned-page-patterns.md` gains the rule with both failure codes (CE0117 for `$currentObject`, CE1571 for omitting the argument) and the tell that costs an hour: a module's OWN control-bar button describes with no argument at all while its microflow takes a parameter, because `DESCRIBE PAGE` does not render the stored argument — so copy the `-- Context: … $grid1 (selection)` comment, not the neighbouring button. Plus BUG-132: `mxcli fix design-properties` aborts on a duplicate GUID shipped inside a marketplace package (Mx Model Reflection 9.1.0), losing the rename pass for the other 2,467 units — and the half that matters, mxbuild reports 0 errors on the same model, so FAILED there is not "the install is broken" — a sales-coaching build (renumbered from BUG-119 at merge)
- fix(skills/conversion-runbook.md): the Stage-0 applicability table said the reuse-vs-build extraction call and the coverage matrix are **`N/A` for requirements-driven**, flatly — while `source-triage.md` and the shipped `triage.md` header say `N/A` only where the corpus holds no extractable structure, "on evidence, never on the entry-mode label". The runbook is the file every session must read first, so the unconditional version won: on a requirements-driven project whose corpus included a platform data export, following it literally would have left that export unparsed — and that parser went on to correct the documents written about the app (53 stored columns vs 128–175 documented, four spellings of one foreign key across four sheets, 15 sheets vs 17). Same shape as the `toolkit-guide.html` first-touch incident: conditional in its owning file, unconditional in the front door. Runbook now defers to `source-triage.md`, and gains a `document-discovery.md` row that was named in the entry-mode prose but missing from the table — Maurits Visser, from a no-code app replacement project
Expand Down
57 changes: 56 additions & 1 deletion bug-logs/mxcli-bugs.md
Original file line number Diff line number Diff line change
Expand Up @@ -2844,6 +2844,41 @@ DECISION"` returns no help text at all. Neither the wrong docs nor the missing h
this specific corruption (the corruption reproduces with correct arrow syntax too), but both should
be fixed alongside it.

### Re-diagnosed 2026-09-02, and re-probed on mxcli v0.21.0 (2026-09-08) — still open

**The "unconditional storage corruption" characterisation in this entry's title is wrong.** It was
corrected on a client project on 2026-09-02 (v0.20.0) but never promoted here until now. The defect
is narrower than the title claims, and it has a workaround.

It is a **pincer between two spellings**, both jaws of which are still closed on v0.21.0
(re-probed 2026-09-08, Mendix 11.13.0, on a throwaway full project copy):

| Outcome spelling | `mxcli check` | Native `mx check` | Net |
|---|---|---|---|
| Bare — `'Yes'` | **passes** | **fails to load** — `Mendix.Modeler.Storage.StorageLoadException`: *"Enumeration value condition outcome in has an invalid value '' for property Value. The text 'Yes' is not a valid EnumerationValueIdentifier."* | unloadable model |
| Qualified — `'MyModule.MyEnum.MyValue'` | **rejected**, rule `MDL-WF03` | **loads clean**, 1 x `CE0117` at the decision | works, via `exec --no-check` |

So mxcli's own `MDL-WF03` mandates the one spelling the loader rejects and rejects the one spelling
the loader accepts. Following the tool's guidance guarantees the unloadable model — which is
exactly why this read as unconditional corruption when it was first filed.

`bson dump` confirms the mechanism directly: the bare outcome string is written verbatim into
`Workflows$EnumerationValueConditionOutcome.Value`, a slot the loader parses as an
`EnumerationValueIdentifier`.

**The residual real gap** is separate and smaller: MDL's `DECISION` has no expression clause (`ON`,
`EXPRESSION`, `CONDITION` and `RULE` were all probed and none parse), so a decision written from
MDL lands with an empty condition and the model reports exactly one `CE0117` — an ordinary,
visible modelling error a human fixes by picking the expression in the Studio Pro canvas.

Incidental confirmation that the qualified form really binds rather than merely being tolerated: a
deliberately non-existent value produced `CE1613` *"The selected enumeration value ... no longer
exists"* while the valid sibling in the same decision resolved silently.

**Two fixes are needed, and they are independent**: (1) resolve the outcome string to an
`EnumerationValueIdentifier` on write, or at minimum stop `MDL-WF03` mandating the unloadable
spelling; (2) give `DECISION` an expression clause.

## BUG-77: BUG-75's "create/change attribute values are safe" scope claim is wrong — quoted attribute segments (`$Var/"Attr"`) DO cause CE0117 in create/change statements too, just not consistently

**Project:** PROJECT-A, script 64 (`Approval.ACT_ApprovalRun_CreateVersion`, part of the same
Expand Down Expand Up @@ -5095,6 +5130,26 @@ Open. No scripted workaround found. The split must be built in Studio Pro by han
an MCP write session (`learned-mcp-patterns.md` — untested for this activity), until mxcli's
parallel-split writer attaches path contents.

### Re-probed on mxcli v0.21.0 (2026-09-08) — NOT fixed

The same two-path probe script was executed through v0.20.0 and v0.21.0 on two separate throwaway
copies of the same project, and the stored workflow unit dumped from each with
`mxcli bson dump --type workflow`.

**The two versions write a byte-identical workflow unit** — zero diff lines after blanking the
`$ID` GUIDs. So v0.21.0 produces the identical runtime deadlock, and no live run was needed to
settle the version question.

Worth recording for whoever fixes this: the path contents *are* present in the BSON, on both
versions — `Workflows$ParallelSplitActivity` -> `Workflows$ParallelSplitOutcome` ->
`Workflows$Flow` -> `Workflows$SingleUserTaskActivity`. That is why `DESCRIBE` round-trips and why
no gate objects. Whatever the runtime reads as empty, **it is not the activity nesting**, so this
entry's title describes the symptom rather than the mechanism. The mechanism is still
unidentified; a maintainer diffing this unit against a Studio-Pro-authored split would likely
find it in one field.

The v0.21.0 changelog names no parallel-split fix.

**Related:** BUG-76 (scripted `DECISION` corrupts the `.mpr` on load). Both are workflow
*structure* writers producing models the runtime will not execute as written; BUG-76 fails loudly
at load, BUG-121 fails silently at run, which makes it the worse of the two.
Expand Down Expand Up @@ -5367,7 +5422,7 @@ row the two disagree.

| Defect | Entry | Status on v0.20.0 |
|---|---|---|
| `DECISION` corrupts the `.mpr` | BUG-76 | **Disputed.** This probe's `ExclusiveSplitActivity` stored and natively loaded; the same-day retest reproduced the byte-exact corruption with `decision '1 = 1'`. Shape not isolated — STOP rule stays (note under BUG-76). |
| `DECISION` corrupts the `.mpr` | BUG-76 | **Resolved 2026-09-08 — not shape-dependent, spelling-dependent.** The two v0.20.0 probes differed in outcome spelling, not shape: a bare outcome (`'Yes'`) passes `mxcli check` and makes the model unloadable; a qualified one (`Module.Enum.Value`) is rejected by `MDL-WF03` yet loads clean via `exec --no-check` with one `CE0117`. Re-probed on v0.21.0: both jaws still closed. See "Re-diagnosed 2026-09-02" under BUG-76; STOP rule stays until upstream (mendixlabs/mxcli#1031) fixes either jaw. |
| MDL-written non-interrupting `BOUNDARY EVENT … TIMER` always malformed (`CE0105`) | a project-local finding, no toolkit entry | **Fixed for the non-interrupting form.** Timer wrote and loaded, reading a context attribute. The interrupting form is still unusable — BUG-109 and `learned-workflow-patterns.md` §19. |
| pre-11.9 `Workflows$CallMicroflowTask` `$Type` | BUG-WF06 (archived, fixed v0.17.0) | **Re-confirmed fixed.** 14/14 stored as `CallMicroflowActivity`. |

Expand Down
Loading
Loading