Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
aa52320
test(run-local): count settle polls instead of timing them
ako Sep 13, 2026
40b2ecd
fix: provision PostgreSQL as a non-root user (closes mendixlabs/mxcli…
claude Sep 13, 2026
af97445
docs(record-narrated-demo): conform the capture overlay to the video …
claude Sep 13, 2026
e098cdc
Merge pull request #453 from ako/claude/mxcli-findings-nnl181
ako Sep 13, 2026
a61a6ec
Merge pull request #454 from ako/claude/gallant-curie-4vivo0
ako Sep 13, 2026
990e941
docs: record the error-handler population MDL-FLOW01 cannot see
claude Sep 13, 2026
c5faf94
docs: plan for error-handler rejoins (Phase E)
claude Sep 13, 2026
c2503ae
feat(microflow): MERGE / JOIN named join points, and DESCRIBE that us…
claude Sep 13, 2026
55e9714
Merge pull request #456 from ako/claude/mxcli-unit-test-perf-n7ggx8
ako Sep 13, 2026
ec3cc44
Merge remote-tracking branch 'origin/main' into claude/bootstrap-prom…
claude Sep 13, 2026
277e0fe
Merge pull request #455 from ako/claude/bootstrap-prompt-smaller-37u3fu
ako Sep 13, 2026
be28539
fix(workflow): end every parallel split path, or the engine skips it
ako Sep 13, 2026
7792eec
docs(skills): two reference entries that taught a failing form
ako Sep 13, 2026
6d05f3f
fix(workflow): end every boundary event path, and count events by suffix
ako Sep 13, 2026
0964395
fix(workflow): refuse a boundary timer that names no kind (MDL-WF07)
ako Sep 13, 2026
68a5f29
Merge pull request #457 from ako/fix/workflow-findings
ako Sep 13, 2026
a2cdc3c
fix(view-entity): refuse an attribute that tries to hold an object (M…
ako Sep 13, 2026
337b232
Merge pull request #458 from ako/fix/view-entity-declared-association
ako Sep 13, 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 @@ -105,3 +105,5 @@
{"area": "cmd/mxcli", "date": "2026-09-11", "symptom": "Two opposite `brain plan` failures with one root cause. A requirement anchored at a bare MODULE (`@Maintenance`) reports BUILT the moment the module exists, with none of its work done. A requirement anchored at a MODULE ROLE (`@Maintenance.Coordinator`) reports PLANNED forever, even once the roles exist \u2014 `describe` refuses it ('no describable document named \u2026') and `mxcli refs` finds nothing", "cause": "`catalogResolver.Resolve` in `cmd/mxcli/cmd_brain.go`. A module has a row in the catalog's `objects` view, so it resolves immediately \u2014 fine for a decision (anchors point backward) and useless for a requirement (anchors point forward, so resolution IS the progress signal). A module role is in NEITHER the objects view NOR `FindDocumentUnit`, because it is not a document \u2014 so both lookups miss and it falls through to NotFound, which for a requirement means 'not built yet' permanently", "file": "`cmd/mxcli/cmd_brain.go` (`catalogResolver.Resolve`, `moduleRoleExists` via `GetModuleSecurity`), `cmd/mxcli/brain/entry.go` (`requirementAnchorsArePlannable`)", "insight": "**A resolver's vocabulary has to cover what people actually anchor at, and the two failure directions need opposite fixes.** The module-role gap is a LOOKUP gap \u2014 fixed by consulting `GetModuleSecurity`, case-insensitively because Mendix treats role names that way and an anchor is hand-written. The module-anchor gap is SEMANTIC and cannot be fixed by lookup: the anchor resolves correctly and is still useless, so it is refused at capture time with the alternative named (an author told only 'no' deletes the anchor, which loses the signal entirely rather than fixing it). Keep the control in BOTH directions: a module anchor stays legal on a decision and on a question, or the fix degrades to 'refuse every module anchor' and the negative test still passes. Verified end to end: `@MyFirstModule.User` \u2192 1 anchor 1 resolved; `@MyFirstModule.NoSuchRole` \u2192 NOT FOUND, exit 1, so the resolver did not simply become permissive. Reported by ako/ChipCoV1", "refs": ["ako/ChipCoV1 FINDINGS.md"]}
{"area": "cmd/mxcli", "date": "2026-09-11", "symptom": "`.claude/bootstrap-mxcli.sh` (the SessionStart hook) re-downloads ~85 MB of mxcli on EVERY fresh session in an environment where mxcli is already installed on PATH", "cause": "The script gated only on `[ ! -x ./mxcli ]` and never consulted PATH, while the bootstrap skill tells you to `rm -f <AppName>/mxcli` after moving the project to the repo root \u2014 so in a session image with mxcli pre-installed the guard could never be satisfied by the binary already present, forever", "file": "`cmd/mxcli/init_hook.go` (`bootstrapScriptTemplate`)", "insight": "**A guard that asks 'is the artifact HERE' rather than 'is it AVAILABLE' pays full cost for something already on the machine.** Hardlink a PATH copy in first (what `mxcli new` itself does), falling back to symlink across filesystems then to a copy, and only download when none of those work \u2014 every path leaves ./mxcli working, which the rest of the script and the generated project CLAUDE.md both assume. Keep BOTH controls when testing: nothing on PATH must still download (not silently no-op), and an existing ./mxcli must be left untouched. Reported by ako/ChipCoV1", "refs": ["ako/ChipCoV1 FINDINGS.md"]}
{"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"]}
Loading
Loading