fix(run-local): refuse stale ports, watch theme SCSS, log build generation - #8
Merged
Merged
Conversation
…eration Investigating "SCSS edits don't show up in the running app" surfaced three issues in the warm local loop — none an actual compiled-CSS cache: 1. Stale process silently adopted (the real time-sink). Nothing checked that the loop's ports were free before booting, and the readiness probes (StartServe.waitReady / runtime waitAdminReady) treat "the port answers" as "ready" — which a leftover mxbuild --serve/runtime satisfies. So a fresh `run --local` attached to the OLD process (its own child, unable to bind, was torn down by defer) and kept serving old output. Add checkTargetPortsFree: refuse to boot with an actionable message when :8080/:8090/:6543 already answer. Detect only, never kill — reaping someone's process is the user's call. 2. Theme source was watched by nothing. The --watch change signal was model-only (.mpr + mprcontents/), so editing theme/web/main.scss or themesource/<module>/web/*.scss triggered no rebuild even under --watch. Add themeSourceMTime and combine it with the model signal in sourceMTime; both are mtime-polling, so this is container-safe (unlike the rollup chokidar web-client watcher). A theme edit now rebuilds and hot-applies. 3. "Did my change take?" was unanswerable. watchAndApply already tracked a client-bundle generation but never surfaced it; log a monotonic build generation (boot is #1) on every apply. The incremental theme step itself is fine — verified that one /build after an SCSS content edit rewrites theme-cache/web/theme.compiled.css — so there is no cache to clear; the "rm -rf theme-cache" ritual was a red herring. Tests: TestCheckTargetPortsFree (free ports pass; an occupied port is named in the refusal) and TestThemeSourceMTime_WatchesThemeAndThemesource (theme/ and themesource/ edits advance the combined watch signal). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
…ss guidance Document the outcome of the "SCSS cache" investigation across the two canonical homes (docs-site page + synced skill) plus the dev symptom table: - The --watch change signal now covers theme source (theme/, themesource/) as well as the model, and logs a build-generation counter. - Editing SCSS needs a rebuild (--watch or a clean restart), never a cache clear — mxbuild --serve recompiles the theme on the next /build and picks up content changes, so `rm -rf theme-cache/ .mendix-cache/` is a red herring. - "My edit didn't show up" is usually a stale serve/runtime still serving on the ports, not a cache: run --local now refuses to boot when the ports are taken, and the docs give the pgrep/kill/curl recovery and the "launch as the sole command, poll separately" guidance. - fix-issue.md gets a symptom row mapping the whole class to runlocal.go. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
This was referenced Jul 25, 2026
ako
pushed a commit
that referenced
this pull request
Jul 26, 2026
`retrieve … where [Seq = $Game/MoveSeq + 1]` failed with a bare `mismatched input '+' expecting ']'`, with no hint that Mendix XPath constraints take a literal/token/variable/path on the value side — never an arithmetic expression. This is a Mendix limitation, not an mxcli bug, so adding grammar support would only let through XPath that mxbuild rejects. Add an error hint keyed on `mismatched input '<+|*|div|mod>' expecting ']'` (the `expecting ']'` shape only occurs inside a bracketed constraint) that names the limitation and the workaround: compute the value into a variable first, then compare against it. Documented in xpath-constraints.md; visitor test + negative bug-test example. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
ako
pushed a commit
that referenced
this pull request
Jul 26, 2026
`retrieve … where [Seq = $Game/MoveSeq + 1]` failed with a bare `mismatched input '+' expecting ']'`, with no hint that Mendix XPath constraints take a literal/token/variable/path on the value side — never an arithmetic expression. This is a Mendix limitation, not an mxcli bug, so adding grammar support would only let through XPath that mxbuild rejects. Add an error hint keyed on `mismatched input '<+|*|div|mod>' expecting ']'` (the `expecting ']'` shape only occurs inside a bracketed constraint) that names the limitation and the workaround: compute the value into a variable first, then compare against it. Documented in xpath-constraints.md; visitor test + negative bug-test example. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
ako
pushed a commit
that referenced
this pull request
Jul 27, 2026
Three checker hints steered authors the wrong way: - MDL001 (nested loop) recommended `retrieve $Match from $List where … limit 1`, which is a parse error — a plain retrieve cannot filter a list variable. Recommend `$Match = FIND($List, <cond>)` (in-memory, O(N)). Same broken advice fixed in CLAUDE.md idiom #2. - MDL044 flagged `count()` used in an expression with "Did you mean 'round()'?" — count is an aggregate activity, not a typo. For the known aggregates (count/sum/average/minimum/maximum) emit "assign it to a variable first: $n = count($List);" instead of a did-you-mean. - MDL044's generic hint cited `mxcli syntax expressions`, which does not exist; point it at `mxcli syntax microflow`. Also lock in finding #5's second trigger: a microflow-call output variable reused across a fallback chain (try A, else try B) is CE0111. It was already caught by the shared create-output-variable check (`check --references`); add TestValidateDuplicateMicroflowCallOutputVar (same-scope + nested-in-if) as a regression guard and document the correct pattern (one variable per call + a plain set) in write-microflows.md. Reported from the RSS-reader build (findings #7, #8, #14c, #5). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Investigating a "my SCSS edit keeps serving old styles / stale-CSS-cache" report on
mxcli run --localturned up three issues in the warm dev loop — none an actual compiled-CSS cache. Two are fixed here; the third (a suspected incremental-theme cache bug) was disproven by experiment.Findings
--watchthere is no file watcher at all —mxbuild --serveonly rebuilds on a/buildrequest (startup / watch tick), so a save changes nothing in the running app.StartServe.waitReady/ runtimewaitAdminReady) treat "the port answers" as ready — which a leftover process satisfies. The fresh child (unable to bind) is torn down bydefer, and the old process keeps serving old output. Reads exactly like a stale cache; it's a stale process.--watchsignal was model-only (.mpr+mprcontents/), sothemesource/**/*.scsswas watched by nothing → fixed.Problem-3 experiment (settles the "cache bug" question): one clean serve up → edit
theme/web/main.scss(content change, no cache clear) → one/build→ bothdeployment/web/theme.compiled.cssandtheme-cache/web/theme.compiled.csschanged and the new rule appeared. So there is no incremental-theme cache to clear —rm -rf theme-cache/ .mendix-cache/was a red herring.Changes
eb0ec29— code:checkTargetPortsFreerefuses to boot with an actionable message when:8080/:8090/:6543already answer. Detection only — reaping another process is the user's call.themeSourceMTime(walkstheme/+themesource/for.scss/.css/.js/.json) combined with the model signal insourceMTime. Both are mtime-polling, so this is container-safe (unlike the rollup chokidar web-client watcher).build #N(boot is#1) so "did my change take?" is answerable from the log.TestCheckTargetPortsFree,TestThemeSourceMTime_WatchesThemeAndThemesource.b815db8— docs:docs-site/src/tools/run-local.md, the synced skill.claude/skills/mendix/run-local.md, and afix-issue.mdsymptom row — "SCSS needs a rebuild (--watchor a clean restart), never a cache-clear; kill the old serve/runtime first."Testing
go build ./cmd/mxcli/...,go vet, andgofmtare clean.StartServe/Buildpath).TestServeIntegration(stale local/tmp/spikeappfixture, v11.6.3 vs cached mxbuild 11.12.1) — unrelated to and untouched by these changes.🤖 Generated with Claude Code
https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
Generated by Claude Code