Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
85da9d6
fix(page-fidelity): credit ALTER PAGE image bindings, skip CUT rows i…
claude Sep 23, 2026
21bf74e
Merge remote-tracking branch 'origin/master' into claude/keen-euler-3…
claude Sep 26, 2026
c326d13
Bug ledger: MPR012 flags legacy dynamic images as React-only errors o…
claude Sep 26, 2026
c84f694
learn(bug-logs): partial revoke on association members is a silent no-op
claude Sep 26, 2026
f134bcd
learn(bug-logs): check --references misses a queue created in the sam…
claude Sep 27, 2026
1ae795f
Inbox: create or modify association ignores owner change
claude Sep 27, 2026
48e7534
Inbox: marketplace-rnd guest-groups harvest (exec gate, v1 restore, u…
claude Sep 27, 2026
f3d7b98
fix(exec gate): a refused mxbuild is unverified, not clean; pick the …
claude Sep 27, 2026
7b96f31
fix(exec.sh): auto-restore a failed gate through restore-mpr.sh, v1 s…
claude Sep 27, 2026
103538b
learn(skills): CE0639 on validation feedback no longer reproduces; fe…
claude Sep 27, 2026
588056a
learn(bug-logs): four upstream drafts from the guest-groups build
claude Sep 27, 2026
79f02ba
fix(e2e helpers): fall back to PW_EXECUTABLE, then /opt/pw-browsers/c…
claude Sep 27, 2026
7392b03
exec.sh --patch: run a one-off model patch through snapshot, gate, re…
claude Sep 27, 2026
c88ddf6
install-claude-permissions: record why autoMode is not written from a…
claude Sep 27, 2026
6f9fd73
Merge remote-tracking branch 'origin/master' into claude/keen-euler-3…
claude Sep 27, 2026
9b4dd5d
Allow mxcli PRs with a proven fix; add File Uploader #1198 PR package
claude Sep 27, 2026
f690449
Log September upstream work: 4 filed issues, 1 PR package, 7 drafts
claude Sep 28, 2026
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
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,19 @@ 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
- log(bug-logs/upstream-log-2026-09.md, bug-logs/pending-github-issues/2026-09-27-*.md): **one index of what went upstream this month.** It lists 4 filed mxcli issues (#1198–#1201; #1199 is already fixed upstream), 1 PR package ready to send, and 7 issue drafts that are not filed yet. The drafts use placeholders for project names. — marketplace-rnd, 2026-09-27 guest-groups build
- rule(skills/upstream-feedback.md): **mxcli may now get a PR, not only an issue, when we hold a proven fix.** §3a sets five conditions: the issue is filed, the patch is rebased on current upstream `main` with anything already fixed dropped, the full `make test` passes there, there is field proof on a real model, and the PR has one concern. PR packages live under `bug-logs/submitted-prs/mxcli/`. The first one is the File Uploader simple-mode CE0463 fix (#1198): 84/84 packages pass on upstream `main` 95091765, and on Mendix 11.12.2 it gives 0 errors and 2/2 uploads stored with matching sha256. The rebase showed #1199 was already fixed upstream, and our version of it failed 2 upstream tests, so it was dropped. That is why condition 2 exists. — marketplace-rnd, 2026-09-27 guest-groups build
- learn(install-claude-permissions.sh, skills/agent-permission-friction.md): **a project cannot widen Claude Code's auto-mode classifier, so the installer does not write `autoMode`.** The docs (https://code.claude.com/docs/en/auto-mode-config and settings-reference, checked 2026-09-27) say `autoMode` is read only from user settings (`~/.claude/settings.json`), managed settings and `--settings`, never from `.claude/settings.json` or `.claude/settings.local.json`, so that a repo cannot allow-list itself. The script header records this and points at `/auto-mode-setup` (the user's own call) and at `./bin/exec.sh --patch` (the project-level route). The skill adds the refused-patch case to Step 2 check 2. Field-run on a scratch copy of marketplace-rnd's `.claude/`: install added 11 + 2 entries, jq validated both files, `--check` went from exit 1 to exit 0, a reinstall changed nothing, and `--uninstall` removed exactly the inserted entries. It left an empty `"deny": []` key in each file (pre-existing behaviour). — marketplace-rnd, 2026-09-27 guest-groups build
- feat(project-bin/exec.sh): **`./bin/exec.sh --patch <script>` runs a one-off model patch (a Python BSON patch, a shell script) through the same chain as MDL: snapshot, baseline, run as `<interpreter> <script> <model.mpr>`, version-matched mxbuild gate, restore, BUILD-LOG row.** Run bare, such a patch had no snapshot, no gate and no log row, and Claude Code's auto-mode classifier refused `python3 patch.py Marketplace.mpr` as "Irreversible Local Destruction". A patch is opaque, so it is kept only on a verified gate: a non-zero exit is restored at once, and a gate that fails, cannot run or reads `unverified` is restored too (`ALLOW_UNVERIFIED` does not apply). The chain guards the model file only, and `./bin/exec.sh` is allow-listed, so the classifier does not review the script. The header says to read what a patch does outside the `.mpr`. `sync-project.sh` flags an installed exec.sh that predates `--patch`; `learned-mdl-preflight.md` Step 0 points at it. Field-run on a scratch copy of the Marketplace-RnD model (Mendix 11.12.2, v1 `.mpr`): the idempotent `14-one-to-one-guestgroup-app.py` wrote 0 units, the gate passed and the model stayed byte-identical (182s). A script that deleted 50 units and exited 2 was restored byte-identical without an mxbuild. A script that exited 0 after writing garbage into 20 units failed the gate ("Expected '$ID' as the first property") and was restored byte-identical (84s). — marketplace-rnd, 2026-09-27 guest-groups build
- fix(project-tests/e2e/helpers.js): **e2e launches no longer die when the pinned Chromium is not installed.** `launchBrowser` and `launchBrowserAt` now take `PW_EXECUTABLE` first. Otherwise, when the binary this Playwright pins is missing, they fall back to `/opt/pw-browsers/chromium` if it exists. A configured channel is left alone. Field run: in a cloud container the pinned headless shell (1243) was absent and only chromium-1194 existed. The pre-fix helper failed with "Executable doesn't exist"; the patched one launched Chromium 141 — marketplace-rnd
- learn(bug-logs): **four upstream drafts from the guest-groups build (v0.23.0, Mendix 11.12.2)**: `BUG-DRAFT-xpath-system-member-case` (an XPath system member in the wrong case, `[CreatedDate >= $Since]`, passes `check --references` and fails the build with CE0161); `BUG-DRAFT-association-owner-ignored` (`create or modify association … owner Both` reports "Modified" and leaves the owner unchanged); `BUG-DRAFT-association-owner-both-cross-module-ce0066` (drop + create with `owner Both` across modules leaves the other module's access rules stale, so CE0066); `BUG-DRAFT-audit-member-access-ce0066` (grants inject `System.owner`/`System.changedBy` member access on entities without those members, so CE0066; fixed upstream in v0.22+, with the process point: record `mxcli --version` in every BUILD-LOG row). All four are findable with `bin/bug-lookup.sh` — marketplace-rnd
- learn(skills/learned-microflow-patterns.md): **CE0639 on `validation feedback` is stamped as not reproducing, and the feedback moves out of `ACT_`.** The rule said CE0639 was "unavoidable via mxcli" and needed Studio Pro re-wiring. BUG-47 was resolved on 2026-08-03, and a `SUB_` carrying `validation feedback $Obj/Attr` built clean on v0.23.0. The old workaround is kept as history, and the object-only CE0091 form is still flagged. The "correct pattern" section recommended feedback directly in `ACT_OrderDetail_Save`, which CONV010 lints red: `ValidationFeedbackAction` is on neither the toolkit's nor upstream's allowlist (87 in the field catalog). Now `VAL_`/`SUB_` gives the feedback and returns a verdict, and `ACT_` calls it and branches. There is a WRONG/RIGHT pair, both passing `mxcli check` v0.23.0. The same stale rule is corrected in `mdl-cookbook-microflows.md` and dropped from `iterative-build-loop.md`'s Studio Pro handoff table. The toolkit's `conv010` replacement is not obsolete: it still carries the de-noising and allowlist fixes that upstream lacks. — marketplace-rnd
- fix(project-bin/exec.sh): **a failed gate on a v1 single-file model is rolled back.** exec.sh had an inline copy of the restore with only the `mprcontents/` arm. On a v1 `.mpr` it printed "Snapshot has no mprcontents/ — refusing to restore from it" and left the broken model in place. The attribution rebuild then measured that same broken model and blamed the error on `PRE-EXISTING`. Now the restore goes through `restore-mpr.sh`, which handles v1, v2 and two-tree. When no restore happens, the row says `NOT rolled back` and no attribution is run. `sync-project.sh` names the fix for older installed copies. `test-bug07-08.sh` case L: a v1 model ends byte-identical to its snapshot. The pre-fix script fails all three assertions. Field: Marketplace-RnD, a 152 MB v1 model, Mendix 11.12.2, mxcli v0.23.0, 2026-09-27 guest-groups build. — marketplace-rnd
- fix(project-bin/exec.sh, _common.sh, verify-model.sh): **the mxbuild gate no longer reads a refused build as clean, and it picks the mxbuild that matches the model.** mxbuild of another Mendix version refuses the model: it exits 3, puts its reason in `errors[]` and leaves `problems[]` empty. The gate counted 0 Error problems and logged `pass · mxbuild clean`. Now 0 problems with a non-zero exit is `?`. exec.sh logs the run as `unverified` with mxbuild's own reason and names the remedy, and verify-model.sh says the same. `find_mxbuild` reads the model's version from `_MetaData._ProductVersion` and prefers a Studio Pro or mxcli-cache mxbuild of that version over the newest. When none is installed, it warns and falls back to the newest. `find_java` on mac prefers JDK 21, because JDK 25 breaks the Mendix 11 deploy build. `sync-project.sh` flags installed copies that lack the fix. New fixture `test-mxbuild-version-match.sh` uses the captured errors file, and `test-bug07-08.sh` gains case K. Field run: Marketplace-RnD, Mendix 11.12.2, mxcli v0.23.0, 2026-09-27 guest-groups build. There, 29 of 29 Mac rows were false greens, one hiding 2×CE0066. The patched gate picked 11.12.2 and reported the CE0066. — marketplace-rnd
- learn(bug-logs): **`BUG-DRAFT-check-references-misses-same-script-queue`**: in v0.23.0, `check --references` does not see a task queue created earlier in the same script. Workaround: put the queue in its own script and run it first. From the Marketplace-RnD guest-groups scan.
- learn(bug-logs): **`BUG-DRAFT-partial-revoke-association-noop`**: in v0.23.0, `revoke R on E (write (<association>))` reports success and leaves the association `ReadWrite`. The same statement on an attribute works. Workaround: revoke the whole role, re-grant from `DESCRIBE ENTITY` output, and verify with `SHOW ACCESS`. From the Marketplace-RnD guest-groups scan.
- learn(bug-logs): **`BUG-DRAFT-mpr012-assumes-react-client`**: in v0.23.0, lint MPR012 reports every legacy dynamic image as a React-only CE0582 error. On a Mendix 11.12.2 model that still builds for the Dojo client, `mx check` reports 0 errors for the same widgets. That added 57 findings to the ratchet with no model change. Marketplace-RnD guest-groups scan.
- fix(project-bin/page-fidelity.js): **two sources of false binding misses, found re-scoring CatalogView_v5.** (1) mxcli DESCRIBE (v0.23.0) prints an IMAGE widget's `ImageUrl` as a bare `'{1}'` and drops the attribute parameters the model holds, so an image bound by `alter page … set ImageUrl = [Attr]` scored as missed — indistinguishable from the unbound page, so the scorer does not guess: it now reads `ALTER PAGE` bodies from any extra input (`… - binding-script.mdl < describe.mdl`, logged as source `describe+script`), accepts `Class =`/`DynamicClasses =` from them, and prints a note naming the blind spot when an IMAGE-row binding misses over bare `'{n}'` templates. (2) `bindRows` scored struck-through / CUT / NOT BUILDABLE bind-table rows that the contract reader already skipped — both now share one `notOwed()` test. Measured on marketplace-rnd CatalogView_v5: bindings 13/18 -> 14/16, fidelity 78% -> 82%; Skill_Details and UserGroupsAdmin_Overview unchanged (86%, 95%). The project copy's contract dimension (not in this copy) also stopped harvesting `css` from "ds.css" as an owed class. Pinned in `tests/wave2/test-page-fidelity-mocks.sh` (+ `bind-contract*` fixtures) — marketplace-rnd
- fix(bin/wire-company-brain.sh): **a heredoc built inside `$(cat <<EOF ...)` does not parse under bash 3.2** — the `$(...)` scanner reads the heredoc body as shell text and an apostrophe in it ("company's") opens a quote it never closes, so `doctor.sh` reported the script unparseable on macOS's stock bash while bash 5 here parsed it fine. Rebuilt with `IFS= read -r -d '' block <<EOF` (no heredoc inside `$(...)`), byte-identical output verified. The same trap was live in two more places, `claude-hooks/hooks/context-ceiling.sh` and `context-watch.sh` (a heredoc feeding python's stdin inside `$(...)`), fixed the same way with output re-verified against a synthetic transcript. Added a `bin/check-portability.sh` check for the pattern (excludes `<<<` here-strings and `$((...))` arithmetic shift, which false-triggered the raw grep) — workshop field report, macOS bash 3.2
- learn(bug-logs): **7 new drafts, 3 addenda and one feature-ask note from a module-rename field run, each re-checked on v0.24.0 where a probe was cheap.** New: `rename module` leaves XPath naming the old module; `rename page` renames a same-named folder instead (reproduced; root cause is a name match with no type check); a case-only `move` leaves an empty folder twin; a quoted DataGrid 2 association path passes `check` and fails CE1613; `check --references` ignores an in-script `rename module`; `diff-local` misses new (untracked) units; and `diff-local` prints a UUID for the module. Addenda: BUG-62 (no `rename snippet`), BUG-63 (`microflow_type` case, SQL-vs-Starlark entity types, `activity_count` scope; title widened), BUG-102 (legacy grid XPath has no offline route). Paste-ready upstream drafts for four, not filed. — field report from a colleague's naming-conventions project (mxcli v0.23.0, Mendix 11.12.4)
- learn(skills/learned-mdl-preflight.md): **STOP row 26: DataGrid 2 column and `sort by` paths over an association.** Write the column path unquoted, and do not sort over an association on ≤ v0.24.0. Both wrong forms pass `check --references` and fail CE1613 at build. — field report from a colleague's naming-conventions project (mxcli v0.23.0, Mendix 11.12.4)
Expand Down
17 changes: 17 additions & 0 deletions bin/install-claude-permissions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,23 @@
# ignores it the same way it ignores `.mxtk/`. The other nine entries are all relative (no
# machine-specific path) and stay in the shared `.claude/settings.json`, same as before.
#
# NOT WRITTEN, ON PURPOSE: `autoMode` (2026-09-27). In auto permission mode a second gate, the
# safety classifier, runs after these rules and can refuse a command they allow (field: a Python
# BSON patch of a git-tracked, snapshotted .mpr refused as "Irreversible Local Destruction").
# `autoMode.environment` is the documented way to give it trusted context, so this script was
# going to merge some. It cannot, from here. https://code.claude.com/docs/en/auto-mode-config
# ("Where the classifier reads configuration", fetched 2026-09-27): the classifier reads
# `autoMode` only from ~/.claude/settings.json, managed settings and the --settings flag / Agent
# SDK, and "doesn't read `autoMode` from project settings in `.claude/settings.json` or
# `.claude/settings.local.json`", because a checked-in repo or a build step could otherwise
# inject its own allow rules. https://code.claude.com/docs/en/settings-reference (`autoMode`,
# same date) agrees: Scope "User or managed". Writing it here would be inert, and writing the
# operator's user-wide ~/.claude/settings.json from a per-project installer is not this script's
# business. The per-user route is Claude Code's own `/auto-mode-setup`, which writes that file
# after the user accepts. The project-level route that works is the command's shape: a model
# patch goes through `./bin/exec.sh --patch <script>`, which the allow rules above already cover
# and which snapshots, gates and restores. See skills/agent-permission-friction.md.
#
# Usage:
# bin/install-claude-permissions.sh <project-root> # merge, write, back up first
# bin/install-claude-permissions.sh <project-root> --check # report only; exits 1 if any
Expand Down
16 changes: 16 additions & 0 deletions bin/sync-project.sh
Original file line number Diff line number Diff line change
Expand Up @@ -879,11 +879,27 @@ known_fix_note() {
page-scope.sh)
echo "bin/page-scope.sh predates the HEADER_WORDS fix (F-042, 2026-08-28): SHOW PAGES header columns Excluded/Folder/Params were parsed as page rows, inflating the page denominator (measured: 6 real pages counted as 13), so every consumer of page-scope.json graded against furniture. One-line fix — recommended upgrade." ;;
_common.sh)
if grep -q 'mxtk_ensure_mxbuild' "$PROJECT_DIR/bin/_common.sh" 2>/dev/null \
&& ! grep -q 'mxtk_model_version' "$PROJECT_DIR/bin/_common.sh" 2>/dev/null; then
echo "bin/_common.sh predates the VERSION-MISMATCH FALSE GREEN fix (toolkit, 2026-09-27, marketplace-rnd): find_mxbuild picked the NEWEST mxbuild, which refuses a model of another Mendix version (exit 3, reason in errors[], problems[] empty), and the gate counted that as 0 errors — 29 of 29 execs logged 'mxbuild clean' on one machine and a CE0066 shipped. Now: the mxbuild matching the model's _ProductVersion is preferred, and a non-zero exit with 0 problems is unverified, never clean. Upgrade BOTH: --upgrade-bin _common.sh --upgrade-bin exec.sh (and verify-model.sh)."; return
fi
if ! grep -q 'mxtk_ensure_mxbuild' "$PROJECT_DIR/bin/_common.sh" 2>/dev/null; then
echo "bin/_common.sh predates the GATE-MUST-RUN fix (toolkit, 2026-09-17): mxtk_ensure_mxbuild downloads a missing mxbuild through ./mxcli, on any machine or cloud container, so exec.sh can refuse to write when the gate cannot run instead of writing unverified. Also missing native_path (Windows errors-file fix, 2026-09-15) if this copy is older still. Upgrade BOTH: --upgrade-bin _common.sh --upgrade-bin exec.sh."; return
fi
echo "bin/_common.sh predates the WINDOWS MXBUILD GATE fix (toolkit, 2026-08-25). This is where find_sp_app/find_mxbuild, JAVA_HOME resolution and mxtk_platform actually live — exec.sh only calls them. So upgrading exec.sh ALONE does not deliver the fix, and grepping exec.sh for mxtk_platform reports 0 even on a fully patched project: grep _common.sh instead. Without this file the mxbuild gate is skipped on every Windows exec and nothing checks your builds. Upgrade BOTH: --upgrade-bin _common.sh --upgrade-bin exec.sh." ;;
exec.sh)
if grep -q 'RESTORER=' "$PROJECT_DIR/bin/exec.sh" 2>/dev/null \
&& ! grep -q 'PATCH_MODE' "$PROJECT_DIR/bin/exec.sh" 2>/dev/null; then
echo "bin/exec.sh predates --patch (toolkit, 2026-09-27, marketplace-rnd): a one-off script that edits the .mpr directly (a Python BSON patch) had no guarded path — no snapshot, no mxbuild gate, no restore, no BUILD-LOG row — and Claude Code's auto-mode classifier refused it run bare. Now: ./bin/exec.sh --patch <script> [args] runs it through the same chain and keeps it only on a verified gate. Upgrade: --upgrade-bin exec.sh."; return
fi
if grep -q 'MXTK_MXBUILD_WHY' "$PROJECT_DIR/bin/exec.sh" 2>/dev/null \
&& ! grep -q 'RESTORER=' "$PROJECT_DIR/bin/exec.sh" 2>/dev/null; then
echo "bin/exec.sh predates the V1 AUTO-RESTORE fix (toolkit, 2026-09-27, marketplace-rnd): its inline restore had only the mprcontents/ arm, so on a v1 single-file .mpr a failed gate printed 'Snapshot has no mprcontents/ — refusing to restore', left the broken model in place, and then blamed the error on PRE-EXISTING. Now the restore goes through bin/restore-mpr.sh (v1 and v2). Upgrade: --upgrade-bin exec.sh (restore-mpr.sh installs with it)."; return
fi
if grep -q 'model-stamp' "$PROJECT_DIR/bin/exec.sh" 2>/dev/null \
&& ! grep -q 'MXTK_MXBUILD_WHY' "$PROJECT_DIR/bin/exec.sh" 2>/dev/null; then
echo "bin/exec.sh predates the VERSION-MISMATCH FALSE GREEN fix (toolkit, 2026-09-27, marketplace-rnd): an mxbuild that refused the model (exit 3, reason in errors[], empty problems[]) was logged 'pass · mxbuild clean' — 29 of 29 execs on one machine, one of them shipping a CE0066. Now it is unverified, with mxbuild's own reason in the BUILD-LOG row. This copy also lacks the V1 AUTO-RESTORE fix (a failed gate on a single-file .mpr was never rolled back). Needs the matching _common.sh: --upgrade-bin _common.sh --upgrade-bin exec.sh."; return
fi
if ! grep -q 'model-stamp' "$PROJECT_DIR/bin/exec.sh" 2>/dev/null; then
echo "bin/exec.sh predates the GATE-MUST-RUN fix (toolkit, 2026-09-17): a missing mxbuild is downloaded, a gate that still cannot run REFUSES the write (ALLOW_UNVERIFIED=1 to override), and a passing gate writes the verification stamp the pre-commit hook checks. Without it every exec on a machine with no mxbuild is applied unverified — on any OS, cloud containers included. Needs the matching _common.sh (mxtk_ensure_mxbuild): --upgrade-bin _common.sh --upgrade-bin exec.sh."; return
fi
Expand Down
Loading
Loading