Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
13accfc
docs(wiki): re-sync describe-round-trip-gaps after #923 closed out
claude Sep 14, 2026
60ff7f7
docs(plans): removal plan for the legacy engine
claude Sep 14, 2026
9ee0bcc
feat(workflow): author event handlers and on-created microflows
ako Sep 14, 2026
79e56c7
Merge pull request #467 from ako/docs/workflow-studio-pro-constructs
ako Sep 15, 2026
5a05766
Merge branch 'mendixlabs:main' into main
ako Sep 15, 2026
e0b4036
docs(plans): measure Phase 3 — it is a bypass problem, not a serializ…
claude Sep 15, 2026
5b600cb
Merge remote-tracking branch 'origin/main' into claude/mxcli-unit-tes…
claude Sep 15, 2026
9b39ec6
docs(plans): refresh the plan's measurements against current main
claude Sep 15, 2026
28ae3ea
feat(workflow): author AI agent tasks with `call agent microflow`
ako Sep 15, 2026
3b4df7c
refactor(api): route the fluent API through the backend abstraction
claude Sep 15, 2026
60bfd35
Point the MCP backend's local reads at the codec backend
claude Sep 15, 2026
5feb4b8
fix(layout): enforce the placeholder rule mxbuild actually applies
claude Sep 15, 2026
ba2c845
fix(layout): report a braced placeholder instead of dropping it silently
claude Sep 15, 2026
284fa6b
feat(layout): add DROP LAYOUT
claude Sep 15, 2026
884a2bf
docs(layout): correct the claim that `Main` is a naming convention
claude Sep 15, 2026
3d3ca1f
Delete the legacy sdk/mpr backend and the flag selecting it
claude Sep 15, 2026
8ad6584
Merge pull request #468 from ako/claude/mxcli-unit-test-perf-n7ggx8
ako Sep 15, 2026
7c7ae8b
Merge origin/main (#468: legacy engine retired, MCP reads via the cod…
ako Sep 15, 2026
de4b09e
docs(proposal): phase 2 engines paragraph after the legacy engine's r…
ako Sep 15, 2026
f06a855
Delete the dead FullBackend surface the census had mislabelled
claude Sep 15, 2026
15bfb20
Merge pull request #469 from ako/feat/workflow-ai-agent-task
ako Sep 15, 2026
44cbdc4
Merge origin/main into claude/mxcli-findings-nnl181
claude Sep 15, 2026
694b379
test(mcp): dial the fake PED at its listener, not through defaultDial
ako Sep 15, 2026
f990ff2
Merge origin/main (#469: AI agent tasks in workflows) into the dead-s…
claude Sep 15, 2026
898e78e
feat(workflow): multi-user task completion rules — participants, deci…
ako Sep 15, 2026
f9d2525
Merge origin/main (#469 merged) into feat/workflow-completion-rules
ako Sep 15, 2026
76fa138
Close Phase 3: accept the last six bypasses as deliberate
claude Sep 15, 2026
49beada
Re-measure Phase 4: it is two independent migrations, not one
claude Sep 15, 2026
03a3ef9
Merge pull request #470 from ako/claude/mxcli-findings-nnl181
ako Sep 15, 2026
7440631
Cut the root package off sdk/mpr (Phase 4a gate)
claude Sep 15, 2026
846d335
Merge origin/main (#470: layout placeholder rule, DROP LAYOUT) into t…
claude Sep 15, 2026
ccd92a2
feat(workflow): event sub-processes and notification events
ako Sep 15, 2026
353d5fd
Merge pull request #471 from ako/claude/mxcli-unit-test-perf-n7ggx8
ako Sep 15, 2026
9a3e3eb
Merge branch 'main' into fix/mcp-connect-tests-dial
ako Sep 15, 2026
ffa439d
Merge pull request #472 from ako/fix/mcp-connect-tests-dial
ako Sep 15, 2026
725f188
Merge branch 'main' into feat/workflow-completion-rules
ako Sep 15, 2026
7a9a6d6
Merge pull request #473 from ako/feat/workflow-completion-rules
ako Sep 15, 2026
90fb7c6
Port cmd/mxcli's readers off sdk/mpr (Phase 4a, first slice)
claude Sep 15, 2026
648e346
Merge pull request #475 from ako/feat/workflow-event-subprocesses
ako Sep 15, 2026
b071fcb
feat(workflow): notify workflow … target, and fix notify actions that…
ako Sep 15, 2026
e19ba2f
Merge origin/main (#475: workflow event sub-processes) into the Phase…
claude Sep 15, 2026
0a1490b
Merge branch 'main' into feat/workflow-notify-target
ako Sep 15, 2026
997af5b
Merge pull request #476 from ako/feat/workflow-notify-target
ako Sep 15, 2026
038f810
Merge pull request #477 from ako/claude/mxcli-unit-test-perf-n7ggx8
ako Sep 15, 2026
deb4dbe
Port cmd/mxcli/docker off sdk/mpr (Phase 4a, second slice)
claude Sep 15, 2026
0868aa7
docs(wiki): digest the 2026-09-15 findings into three bug-pattern pages
ako Sep 15, 2026
bbcfb45
Get mdl/executor off sdk/mpr (Phase 4a, third slice)
claude Sep 15, 2026
9885cc6
test(page): accept the quoted Target in the describe roundtrip
claude Sep 15, 2026
692bafa
fix(workflow): resolve ALTER WORKFLOW activity refs by name before ca…
ako Sep 15, 2026
cdd1305
fix: keep @position on workflow and mapping actions across a rewrite
ako Sep 15, 2026
78f4fcb
fix(mcp): create microflows against Studio Pro 11.14's skeleton const…
ako Sep 15, 2026
0c7ac6e
Merge remote-tracking branch 'origin/main' into fix/mcp-microflow-ske…
ako Sep 15, 2026
53fb048
fix(mcp): store timer boundary events correctly over MCP
ako Sep 15, 2026
2f7f6fd
fix(mcp): keep workflow list order in create-or-modify and ALTER over…
ako Sep 15, 2026
d54faa4
Merge pull request #478 from ako/claude/mxcli-unit-test-perf-n7ggx8
ako Sep 15, 2026
0693ed9
Merge origin/main into docs/wiki-bug-patterns-sync
ako Sep 15, 2026
f41c128
Merge pull request #479 from ako/docs/wiki-bug-patterns-sync
ako Sep 15, 2026
dfbf9cd
Merge remote-tracking branch 'origin/main' into fix/workflow-action-p…
ako Sep 15, 2026
7863f0b
test: drop target-less notify from the position bug-test script
ako Sep 15, 2026
894f23b
Port the rest of cmd/mxcli off sdk/mpr (Phase 4a, fourth slice)
claude Sep 15, 2026
ae88b54
Merge pull request #480 from ako/fix/workflow-action-position-roundtrip
ako Sep 15, 2026
6ca09e0
Merge remote-tracking branch 'origin/main' into fix/mcp-microflow-ske…
ako Sep 15, 2026
e76daaa
Merge pull request #481 from ako/fix/mcp-microflow-skeleton-constructor
ako Sep 15, 2026
2b20035
fix(workflow): keep @N counting every name-or-caption match
ako Sep 15, 2026
0687a3d
Merge remote-tracking branch 'origin/main' into claude/beautiful-grot…
ako Sep 15, 2026
7de4e70
Merge pull request #482 from ako/claude/beautiful-grothendieck-5a9a8b
ako Sep 15, 2026
7199443
Merge origin/main into feat/workflow-event-subprocesses
ako Sep 15, 2026
c88f506
test(mcp): give the jump-shadow fake a boundary-event store
ako Sep 15, 2026
a52937f
Merge pull request #483 from ako/feat/workflow-event-subprocesses
ako Sep 15, 2026
0dd7f51
Merge pull request #484 from ako/claude/mxcli-unit-test-perf-n7ggx8
ako Sep 15, 2026
5e32c06
Implement FindCustomWidgetType on the codec backend
claude Sep 15, 2026
bdb8fab
fix(check): resolve constraint associations through the generalizatio…
claude Sep 15, 2026
96b5f4e
Merge pull request #485 from ako/claude/mxcli-unit-test-perf-n7ggx8
ako Sep 15, 2026
f4a7655
Take the last seven off sdk/mpr — importers reach zero
claude Sep 15, 2026
4ec113b
Merge pull request #486 from ako/claude/mxcli-issues-ovfoxk
ako Sep 15, 2026
eda339d
Merge pull request #487 from ako/claude/mxcli-unit-test-perf-n7ggx8
ako Sep 15, 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
2 changes: 2 additions & 0 deletions .claude/skills/fix-issue/findings/cmd-mxcli.jsonl
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,5 @@
{"area": "cmd/mxcli", "date": "2026-09-11", "symptom": "`mxcli theme create --from <design.css>` seeds the palette and nothing else: the scaffolded brand theme still described itself in `theme list` as 'Cool slate, one teal signal colour' with Signal's six swatches, and vendored ~500 KB of IBM Plex woff2 the seeded --mxt-font never names, plus a SIL OFL licence for fonts it does not use. Separately, the primary button was never the brand colour: Atlas derives --btn-primary-bg from --brand-primary-600 = color-mix(brand, contrast 20%), so a brand blue #10069F rendered rgb(21,13,140)", "cause": "`manifest()` copied the base theme's Summary and Colorway verbatim and the walk copied every file unconditionally. The Atlas map pinned `--btn-primary-color` to `--mxt-brand-ink` \u2014 an ink each theme picks to sit on `--mxt-brand` (console pairs near-black #04211d with bright teal #2dd4bf) \u2014 while leaving the background to Atlas's derivative, so the pairing the theme designed for was never the pairing that rendered. The map's own comment already called it 'a brand-filled button'", "file": "`cmd/mxcli/theme/create_seeded.go`, `create.go` (`manifest`, the scaffold walk), `assets/*/files/theme/web/_mxcli-atlas-map.scss`", "insight": "**Inheriting a statement ABOUT the base theme into a theme whose palette is no longer the base's is a confident lie; derive it or drop it.** Two traps in the font half. (1) The decision must be made BEFORE the walk: it is taken by reading the partial and applied to files elsewhere in the tree, so doing it inline depended on WalkDir's lexical order putting `_mxcli-<name>.scss` before `mxcli-fonts/` \u2014 true only because of the leading underscore. (2) It touches two halves \u2014 the @font-face rules and the woff2 files \u2014 and getting either alone wrong is silent: a surviving rule for a deleted file 404s, a surviving file nothing loads is the dead weight being removed. Unit tests on each half cannot catch a mismatch; the guard is an integration assertion that a scaffolded theme ships exactly the fonts it loads (control: stubbing the file half fails it with 'X is shipped but no @font-face loads it'). Reported by ako/ChipCoV1", "refs": ["ako/ChipCoV1 FINDINGS.md"]}
{"area": "cmd/mxcli", "date": "2026-09-13", "symptom": "`mxcli run --local --ensure-db` cannot provision PostgreSQL in a non-root devcontainer (Debian/Ubuntu base, remoteUser vscode): reported as a bare \"PostgreSQL did not become ready at 127.0.0.1:5432 within 20s\", or as `exec: \"initdb\": executable file not found in $PATH`. Fires on every fresh Claude Code session in an initialized project, since `mxcli init` wires `run --local --setup --ensure-db` into the SessionStart hook", "cause": "THREE independent defects on one path, each sufficient to block it. (1) `service postgresql start` ran unelevated: Debian's /etc/init.d/postgresql runs under `set -e` and calls create_socket_directory FIRST, which chmods /var/run/postgresql — refused for a non-root user, so the script aborts before it looks at a single cluster. (2) The #823 user-owned-cluster fallback was INERT on Debian/Ubuntu: postgresql-common wraps only the CLIENT tools (psql, pg_isready, pg_ctlcluster) into /usr/bin, while initdb/pg_ctl live in /usr/lib/postgresql/<major>/bin — so the safety net for a failed service start could never deploy on the platform that needs it most. (3) `resolveSuperuser` used `sudo -n -u postgres psql`, but mcr.microsoft.com/devcontainers/base grants its user sudo to root ONLY (`vscode ALL=(root) NOPASSWD:ALL`, confirmed in devcontainers/features main.sh) — so the target is refused even though the user is effectively an administrator. Plus a diagnostic defect: the 20s readiness timeout discarded the service-manager output the package had already collected", "file": "`cmd/mxcli/docker/ensuredb.go` (`serviceStartAttempts`, `postgresServerBinDir`/`postgresTool`, `superuser.viaRoot`, `withServiceDiag`)", "insight": "mxcli GENERATES the broken environment — `generateDockerfile` emits that exact base image, installs postgresql, and runs as vscode — so this was not user misconfiguration, and fixing it in code (not the template) also repairs projects already scaffolded. Root may target any account, so `sudo -n -- sudo -n -u postgres` reaches postgres under a root-only sudoers policy; try the direct form first and nest only on refusal. Resolve initdb and pg_ctl from the SAME bin directory and rank majors NUMERICALLY — a lexical sort puts \"9\" above \"16\", and a data directory made by one major cannot be started by another. **Measurement trap that cost the most time**: reasoning about which error the user would see is unreliable here — four plausible code paths produce four different messages, and the reported wording was reproducible by none of them on Ubuntu 24.04/PG16. What settled it was building a harness that calls `EnsureDatabase` directly and running it as a real non-root user with the real sudoers rule, then isolating each defect with a one-variable control (widen sudoers to `(ALL)` and nothing else changes → provisioning succeeds; prepend /usr/lib/postgresql/16/bin → the fallback completes). Each of the four fixes was reverted individually and its test re-run: two controls initially failed to COMPILE rather than reproducing the symptom, which proves nothing — they were redone faithfully before being believed", "refs": ["mendixlabs/mxcli#984", "#823"]}
{"area": "cmd/mxcli", "date": "2026-09-13", "symptom": "`build-and-test` fails in CI on `TestSettleSourceReturnsPromptlyForOneChange` \u2014 \"a quiet source took 196.975373ms to settle, want under 100ms\" \u2014 while the SAME tree passes in another run of the same workflow minutes earlier", "cause": "The test bounded elapsed wall-clock time as a multiple of the poll interval (`poll * (sourceSettleWindow + 3)`, 100ms against a nominal 40ms). settleSource waits on `time.After(poll)`, which guarantees AT LEAST the duration and nothing about the upper bound, so a loaded runner blows the budget with no defect present.", "file": "cmd/mxcli/docker/runlocal.go (settleSourceWith, the injected tick), cmd/mxcli/docker/runlocal_settle_test.go", "insight": "The property being guarded was a POLL COUNT, not a duration \u2014 'a quiet source costs one extra poll' \u2014 so the fix is to make polls countable (inject the timer) rather than to widen the budget, which only moves the flake threshold. Diagnosis shortcut worth reusing: the same workflow ran twice on the same tree, once from the push event and once from the pull_request merge commit, and disagreed \u2014 two runs of one tree is direct evidence of nondeterminism and cheaper than reading the test. Two things the controls settled that reasoning did not: (1) the assertions are written in terms of `sourceSettleWindow`, so WIDENING that constant leaves both tests green \u2014 they assert the loop honours whatever window is declared, never the number itself, and the real control is a loop that costs one poll MORE than it declares (both fail). (2) Each tick call must return a freshly-armed channel; returning one shared channel makes the multi-file test HANG rather than miscount, so the re-arm is load-bearing and not a style choice. The seam also made a previously untestable guarantee expressible: the window must be sourceSettleWindow CONSECUTIVE quiet polls, and dropping `quiet = 0` from the change branch was green against every pre-existing test in the file.", "refs": ["ako/mxcli#449"]}
{"area":"cmd/mxcli","date":"2026-09-15","symptom":"Porting cmd/mxcli/docker off sdk/mpr moved two WRITE paths (ensureDemoUsers, applyHarvest) onto the codec backend. A baseline diff of `docker check` showed the project byte-identical across 421 files — which proved nothing, because the run had not written anything.","cause":"docker check's widget-update harvest is a no-op on an already-clean fixture, so an output+filetree diff against a pre-port binary exercises only the READ paths. Coverage then showed ensureDemoUsers at 0.0% — a write path the port touched that no test in the package ran.","file":"cmd/mxcli/docker/build.go","fix":"Added TestEnsureDemoUsers_CreatesAdminWhenNoneExist and _SkipsWhenUsersExist, plus a clearDemoUsers helper that establishes the precondition. Coverage 0.0% -> 76.5%. The read paths keep the baseline-diff evidence; applyHarvest was already at 76.9% via TestRunUpdateWidgets_RestoresV2AfterConversion.","insight":"A byte-identical baseline diff is strong evidence for a READ port and near-worthless for a WRITE port, because the natural control (nothing changed) is also what a no-op produces. The two need different instruments, and the cheap way to tell which you have is `go test -coverprofile` + `go tool cover -func` grepped for the functions you touched: it answers 'did my port's code even run' in one command, where a passing suite does not. Here it separated applyHarvest (76.9%, genuinely exercised including its UpdateRawUnit) from ensureDemoUsers (0.0%) inside the same package, so the gap was specific rather than a general absence of tests. Second trap, hit while fixing it: the shared v2 fixture ALREADY HAS two demo users, so the create-path test skipped and the idempotence test asserted the wrong count. Skipping on an unmet precondition is the #808 shape — set the precondition up instead (RemoveDemoUser in a helper, then assert the helper actually emptied it before proceeding). Third: read back through a FRESH connection, since asserting on the value the writer still holds passes against a write that never reached disk."}
{"area":"cmd/mxcli","date":"2026-09-15","symptom":"Porting the last cmd/mxcli readers off sdk/mpr, cmd_extract_templates.go compiled with a type error (RawType/RawObject are bson.D on sdk/mpr, any on types.RawCustomWidgetType). Casting past it would have compiled — and broken the command at runtime, because FindCustomWidgetType is UNIMPLEMENTED on the codec backend.","cause":"mdl/backend/modelsdk/unimplemented_gen.go carries FindCustomWidgetType; measured at runtime it returns 'FindCustomWidgetType is not implemented on the model engine. This should be unreachable'. cmd_extract_templates.go was calling it through a concrete *mpr.Reader, so it was reachable only by NOT going through the backend.","file":"cmd/mxcli/cmd_extract_templates.go","fix":"Left this one file on sdk/mpr with a comment saying why and what would fix it (implement FindCustomWidgetType on the codec backend), and ported the other five. cmd/mxcli is otherwise clean; importers 13 -> 8.","insight":"The type error was the lucky part. A compile error is the ONLY reason this did not ship as a runtime failure — the cast that silences it is one line, and nothing else would have objected. When a port hits a type mismatch at a backend boundary, check whether the backend method is implemented at all before reconciling the types: `grep -n '<Method>' mdl/backend/modelsdk/unimplemented_gen.go` answers it in one command, and a runtime probe (connect read-only, call it, log the error) confirms it in under a minute. Note the direction of the trap: the unimplemented method's own error says 'This should be unreachable', and porting a caller to the backend is precisely what MAKES it reachable — so the #477 census blind spot (callers holding a concrete reader are invisible) cuts both ways. Second, smaller measurement trap in the same slice: a baseline diff of `check --post-migration` showed 50 lines vanishing, which looked like a regression and was not — the FIRST run built and cached a catalog inside the project, so the second run reused it. Two binaries must each get their own fresh copy of the fixture, exactly as for a write port; a command that caches into the project directory makes consecutive runs non-independent even when nothing is being written on purpose."}
Loading
Loading