Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
107 commits
Select commit Hold shift + click to select a range
8f08e22
docs(proposal): implementation plan for first-class expressions (#750)
claude Sep 23, 2026
cb1bbdc
fix: resolve association-path join alias written with uppercase AS
claude Sep 24, 2026
3f57713
Merge remote-tracking branch 'origin/main' into claude/mxcli-issue-65…
claude Sep 24, 2026
0a821cf
Merge pull request #660 from ako/claude/mxcli-issue-652-paxl5t
ako Sep 24, 2026
cd5775c
feat: mxcli layout flows re-arranges microflows and nanoflows
claude Sep 24, 2026
d6dd95e
docs: document mxcli layout flows
claude Sep 24, 2026
c23af78
docs(proposal): OData client expression slots for first-class express…
claude Sep 24, 2026
6ff7404
docs(proposal): `constant Mod.C` for by-name constant references
claude Sep 24, 2026
9a03215
docs(proposal): measure OData proxy constants against a Studio Pro re…
claude Sep 25, 2026
513fdfe
docs(proposal): record Integer/Long proxy-port constants as measured
claude Sep 25, 2026
26880a0
fix(odata): describe odata client re-quotes stored expressions
claude Sep 25, 2026
dad9be6
fix(odata): store proxy constant references without the @ prefix
claude Sep 25, 2026
6a48ed7
fix(odata): design-time fetch sends a string-literal credential's con…
claude Sep 25, 2026
dcd6f71
docs(skill): odata-data-sharing walkthrough credentials as string lit…
claude Sep 25, 2026
fdbcceb
Merge remote-tracking branch 'origin/main' into claude/nice-einstein-…
claude Sep 25, 2026
9ac62cd
Merge pull request #661 from ako/claude/layout-handling-approach-eg2kcm
ako Sep 25, 2026
3baa709
fix: DESCRIBE WIDGET and widget list see installed widgets without wi…
ako Sep 25, 2026
618c600
fix: qualify inherited associations with their declaring module (#662)
ako Sep 25, 2026
ad3cc3c
fix(lsp): widget registry sees installed widgets without widget init
ako Sep 25, 2026
46cd408
Merge remote-tracking branch 'origin/main' into claude/mxcli-issue-66…
ako Sep 25, 2026
f38696f
fix(describe): keep comment entries in a widget property list parseable
ako Sep 25, 2026
95eb07e
feat(pages): author open_link with a dynamic address ($currentObject/…
ako Sep 25, 2026
31fb40f
Merge pull request #665 from ako/claude/nice-einstein-a74lz4
ako Sep 25, 2026
f040bf7
Merge pull request #666 from ako/claude/mxcli-issue-662-regression-67…
ako Sep 25, 2026
624c8e0
Merge remote-tracking branch 'origin/main' into claude/mxcli-issue-66…
ako Sep 25, 2026
e91b8ba
fix(pages): refuse an expression property written as a bracketed list
claude Sep 25, 2026
0b7143f
docs(changelog): OData client quoting, proxy and credential fixes
claude Sep 25, 2026
88630b9
test(odata): detach the file's explanatory comment from the helper
claude Sep 25, 2026
df339a0
Merge pull request #667 from ako/claude/mxcli-issue-663-35c8c8
ako Sep 25, 2026
3b67ef2
Merge pull request #668 from ako/claude/nice-einstein-a74lz4
ako Sep 25, 2026
c7ffc0f
feat(pages): author Studio Pro's Label widget; describe emits it named
ako Sep 25, 2026
6183624
Merge remote-tracking branch 'origin/main' into fix/describe-unauthor…
ako Sep 25, 2026
755f94a
Merge remote-tracking branch 'origin/main' into fix/describe-nameless…
ako Sep 25, 2026
51d8963
feat(odata): write client credentials and header values as expressions
claude Sep 25, 2026
9c764e5
fix(codec): write a compound design property's Properties list with m…
ako Sep 25, 2026
ee2de4f
fix(pages): write a nanoflow data source flat, as Studio Pro does (CE…
ako Sep 25, 2026
66f186e
feat(pages): round-trip "Visible: based on attribute value"
ako Sep 25, 2026
ff6a5e0
Merge pull request #669 from ako/fix/describe-unauthorable-action
ako Sep 25, 2026
8da7c43
Merge pull request #670 from ako/fix/describe-nameless-widget
ako Sep 25, 2026
daa8458
Merge remote-tracking branch 'origin/main' into fix/attribute-conditi…
ako Sep 25, 2026
c28ab0c
Merge pull request #671 from ako/fix/attribute-conditional-visibility
ako Sep 25, 2026
b896dd3
Merge pull request #672 from ako/fix/dataview-nanoflow-source-shape
ako Sep 25, 2026
ebaee1a
Merge pull request #673 from ako/fix/compound-design-property-marker
ako Sep 25, 2026
8f0f64b
Merge branch 'mendixlabs:main' into main
ako Sep 25, 2026
61c2b33
feat(odata): ServiceUrl names a constant, like ProxyHost
claude Sep 25, 2026
ccbfa26
fix(describe): keep a ComboBox's expression caption (#664)
ako Sep 25, 2026
778da0c
Merge remote-tracking branch 'origin/main' into claude/nice-einstein-…
claude Sep 25, 2026
864440d
fix: excluded page's dangling action references no longer block exec
ako Sep 25, 2026
872e42d
fix(check): name the current property for a design-property key the t…
ako Sep 25, 2026
1984c9c
fix(pages): round-trip a page over a flow the project lacks
ako Sep 25, 2026
d10b910
Merge pull request #674 from ako/fix/664-combobox-caption
ako Sep 25, 2026
e4b2ebc
Merge remote-tracking branch 'origin/main' into fix/excluded-page-ref…
ako Sep 25, 2026
16ae440
Merge remote-tracking branch 'origin/fix/excluded-page-reference-chec…
ako Sep 25, 2026
3c590b8
Merge pull request #675 from ako/fix/excluded-page-reference-check
ako Sep 25, 2026
2a723ec
Merge pull request #676 from ako/claude/nice-einstein-a74lz4
ako Sep 25, 2026
5ec78f1
Merge remote-tracking branch 'origin/main' into fix/describe-unresolv…
ako Sep 25, 2026
db949df
style: gofmt the unresolved-context describe test
ako Sep 25, 2026
6591e02
Merge remote-tracking branch 'origin/main' into fix/widget11-design-p…
ako Sep 25, 2026
b4170eb
Merge pull request #678 from ako/fix/describe-unresolved-context-attrs
ako Sep 25, 2026
c865b99
Merge pull request #679 from ako/fix/widget11-design-property-false-p…
ako Sep 25, 2026
713c5d7
feat(pages): write DynamicClasses and DynamicCellClass as expressions
claude Sep 25, 2026
66c84a2
feat(lint): scope a lint run to named documents with -d/--documents
claude Sep 25, 2026
61a90bb
feat(check): warn on a commit inside a loop before it is written (MDL…
claude Sep 25, 2026
2451d7e
fix(check): ALTER STYLING names the current property for a renamed key
ako Sep 25, 2026
60bd4fa
fix(check): resolve a `label`'s design properties against the theme's…
ako Sep 25, 2026
33fb2a9
fix(catalog): tell same-named excluded/live documents apart (#1185)
claude Sep 25, 2026
cb6810e
fix(pages): refuse a bare attribute reference on every write, ALTER i…
ako Sep 25, 2026
68535d0
Merge pull request #682 from ako/claude/nice-einstein-a74lz4
ako Sep 25, 2026
128e3c4
Merge pull request #683 from ako/claude/youthful-planck-x6x8xk
ako Sep 25, 2026
4de5801
Merge remote-tracking branch 'origin/main' into fix/alter-page-bare-a…
ako Sep 25, 2026
a23a479
Merge remote-tracking branch 'origin/main' into fix/label-design-prop…
ako Sep 25, 2026
3613f68
Merge remote-tracking branch 'origin/main' into fix/alter-styling-ren…
ako Sep 25, 2026
3796fcc
Merge remote-tracking branch 'origin/main' into claude/mxcli-issue-11…
claude Sep 25, 2026
67e31d2
fix(visitor): store text expressions with their whitespace
claude Sep 25, 2026
51b36dc
fix(describe): name the datasource key on a widget declaring several …
claude Sep 25, 2026
968dc4f
fix(check): refuse bare bindings ALTER PAGE inserts where no entity i…
ako Sep 25, 2026
4da3ffb
Merge mendixlabs/mxcli main into ako/mxcli main
claude Sep 25, 2026
1ec267f
fix(catalog): mark java action type-parameter types unambiguously
claude Sep 25, 2026
c1f8c89
fix(pages): refuse an attribute binding with no object to bind to (MD…
ako Sep 25, 2026
aaa5645
fix(lint): pin documented Starlark field values to what the API emits
claude Sep 25, 2026
1ae6737
fix: resolve every widget keyword's design properties through the $Ty…
ako Sep 25, 2026
8325731
Merge pull request #689 from ako/claude/laughing-brahmagupta-e3niwq
ako Sep 25, 2026
f22ed68
Merge pull request #685 from ako/fix/alter-page-bare-attributeref-guard
ako Sep 25, 2026
7c806d1
Merge pull request #686 from ako/fix/label-design-property-check
ako Sep 25, 2026
e628ebc
Merge remote-tracking branch 'origin/main' into fix/alter-styling-ren…
ako Sep 25, 2026
5ede892
Merge remote-tracking branch 'origin/main' into fix/alter-page-unscop…
ako Sep 25, 2026
1546b19
Merge pull request #687 from ako/fix/alter-styling-renamed-design-pro…
ako Sep 25, 2026
2b81fd8
Merge pull request #688 from ako/claude/mxcli-issue-1185-d39f0i
ako Sep 25, 2026
b13a324
Merge pull request #690 from ako/claude/bold-galileo-4r4uks
ako Sep 25, 2026
9823c8a
Merge remote-tracking branch 'origin/main' into fix/input-binding-wit…
ako Sep 25, 2026
06c0450
Merge remote-tracking branch 'origin/main' into claude/nice-einstein-…
claude Sep 25, 2026
f139436
Merge remote-tracking branch 'origin/main' into fix/design-property-k…
ako Sep 25, 2026
7c8619b
fix(lint): name nanoflows and rules correctly in shipped Starlark rules
claude Sep 25, 2026
6d74d01
Merge remote-tracking branch 'origin/main' into fix/alter-page-unscop…
ako Sep 25, 2026
f1fd11c
fix(java-actions): primitive-named type parameters and list of a type…
claude Sep 25, 2026
0079d8f
Merge remote-tracking branch 'origin/main' into fix/input-binding-wit…
ako Sep 25, 2026
5c74e4e
Merge remote-tracking branch 'origin/main' into fix/design-property-k…
ako Sep 25, 2026
2f58869
Merge pull request #691 from ako/claude/mxcli-issue-1178-otrecn
ako Sep 25, 2026
a2c0d00
Merge pull request #692 from ako/claude/nice-einstein-a74lz4
ako Sep 25, 2026
7df73ce
Merge pull request #693 from ako/fix/alter-page-unscoped-bindings-check
ako Sep 25, 2026
8f6f4f5
Merge remote-tracking branch 'origin/main' into fix/input-binding-wit…
ako Sep 25, 2026
5dc51ce
Merge pull request #694 from ako/fix/input-binding-without-context
ako Sep 25, 2026
d8b199a
Merge remote-tracking branch 'origin/main' into fix/design-property-k…
ako Sep 26, 2026
2ee3bd0
Merge pull request #695 from ako/fix/design-property-keyword-mappings
ako Sep 26, 2026
27cca2e
Merge remote-tracking branch 'origin/main' into fix/starlark-flow-doc…
claude Sep 26, 2026
4b93130
Merge pull request #697 from ako/fix/starlark-flow-document-noun
ako Sep 26, 2026
2e5ebdc
Merge pull request #698 from ako/claude/zealous-brown-89djqi
ako Sep 26, 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
8 changes: 4 additions & 4 deletions .claude/lint-rules/conv009_max_microflow_objects.star
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ def check():
for mf in microflows():
if mf.activity_count > MAX_ACTIVITIES:
violations.append(violation(
message="Microflow '{}' has {} activities (convention max: {}). Split into sub-microflows.".format(
mf.name, mf.activity_count, MAX_ACTIVITIES
message="{} '{}' has {} activities (convention max: {}). Split into sub-{}s.".format(
mf.document_noun_title, mf.name, mf.activity_count, MAX_ACTIVITIES, mf.document_noun
),
location=location(
module=mf.module_name,
document_type="Microflow",
document_type=mf.document_noun_title,
document_name=mf.qualified_name,
),
suggestion="Extract logical sections into SUB_ microflows to keep each under {} activities".format(MAX_ACTIVITIES),
suggestion="Extract logical sections into SUB_ {}s to keep each under {} activities".format(mf.document_noun, MAX_ACTIVITIES),
))

return violations
20 changes: 10 additions & 10 deletions .claude/lint-rules/conv010_act_microflow_content.star
Original file line number Diff line number Diff line change
Expand Up @@ -92,31 +92,31 @@ def check():
continue

violations.append(violation(
message="ACT_ microflow '{}' contains '{}' action. Delegate business logic to a SUB_ microflow.".format(
mf.name, act.action_type
message="ACT_ {} '{}' contains '{}' action. Delegate business logic to a SUB_ {}.".format(
mf.document_noun, mf.name, act.action_type, mf.document_noun
),
location=location(
module=mf.module_name,
document_type="Microflow",
document_type=mf.document_noun_title,
document_name=mf.qualified_name,
),
suggestion="Move the '{}' action to a SUB_ microflow and call it from '{}'".format(
act.action_type, mf.name
suggestion="Move the '{}' action to a SUB_ {} and call it from '{}'".format(
act.action_type, mf.document_noun, mf.name
),
))
elif act.activity_type not in ALLOWED_ACTIVITY_TYPES:
# Any other non-allowed activity type
violations.append(violation(
message="ACT_ microflow '{}' contains '{}' activity. Delegate to a SUB_ microflow.".format(
mf.name, act.activity_type
message="ACT_ {} '{}' contains '{}' activity. Delegate to a SUB_ {}.".format(
mf.document_noun, mf.name, act.activity_type, mf.document_noun
),
location=location(
module=mf.module_name,
document_type="Microflow",
document_type=mf.document_noun_title,
document_name=mf.qualified_name,
),
suggestion="Move the '{}' to a SUB_ microflow called from '{}'".format(
act.activity_type, mf.name
suggestion="Move the '{}' to a SUB_ {} called from '{}'".format(
act.activity_type, mf.document_noun, mf.name
),
))

Expand Down
9 changes: 6 additions & 3 deletions .claude/lint-rules/example_microflow.star
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@
# .name - Simple name (e.g., "ACT_ProcessOrder")
# .qualified_name - Full name (e.g., "MyModule.ACT_ProcessOrder")
# .module_name - Module name
# .microflow_type - "Microflow" or "Nanoflow"
# .microflow_type - "MICROFLOW", "NANOFLOW" or "RULE"
# .description - Documentation
# .return_type - Return type
# .parameter_count - Number of parameters
# .activity_count - Number of activities
# .document_noun - "microflow", "nanoflow" or "rule" (microflows() yields all three)
# .document_noun_title - the same, capitalised: use it for document_type=

RULE_ID = "CUSTOM002"
RULE_NAME = "Microflow Prefix Convention"
Expand Down Expand Up @@ -48,11 +50,12 @@ def check():
if not has_valid_prefix:
loc = location(
module=mf.module_name,
document_type="Microflow",
document_type=mf.document_noun_title,
document_name=mf.qualified_name
)
v = violation(
message="Microflow '{}' should start with a standard prefix ({})".format(
message="{} '{}' should start with a standard prefix ({})".format(
mf.document_noun_title,
name,
", ".join(VALID_PREFIXES)
),
Expand Down
8 changes: 5 additions & 3 deletions .claude/lint-rules/long_microflows.star
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,16 @@ def check():
if mf.activity_count > MAX_ACTIVITIES:
loc = location(
module=mf.module_name,
document_type="Microflow",
document_type=mf.document_noun_title,
document_name=mf.qualified_name
)
v = violation(
message="Microflow '{}' has {} activities (max: {}). Consider splitting into smaller microflows.".format(
message="{} '{}' has {} activities (max: {}). Consider splitting into smaller {}s.".format(
mf.document_noun_title,
mf.name,
mf.activity_count,
MAX_ACTIVITIES
MAX_ACTIVITIES,
mf.document_noun
),
location=loc,
suggestion="Extract logical sections into SUB_ microflows. This improves readability, testability, and reusability."
Expand Down
12 changes: 8 additions & 4 deletions .claude/lint-rules/mccabe_complexity.star
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@
# .name - Simple name (e.g., "ProcessOrder")
# .qualified_name - Full name (e.g., "MyModule.ProcessOrder")
# .module_name - Module name
# .microflow_type - "MICROFLOW" or "NANOFLOW"
# .microflow_type - "MICROFLOW", "NANOFLOW" or "RULE"
# .description - Documentation
# .return_type - Return type
# .parameter_count - Number of parameters
# .activity_count - Number of activities
# .complexity - McCabe cyclomatic complexity
# .document_noun - "microflow", "nanoflow" or "rule" (microflows() yields all three)
# .document_noun_title - the same, capitalised: use it for document_type=

RULE_ID = "QUAL001"
RULE_NAME = "McCabe Complexity"
Expand All @@ -45,14 +47,16 @@ def check():
if mf.complexity > MAX_COMPLEXITY:
loc = location(
module=mf.module_name,
document_type="Microflow",
document_type=mf.document_noun_title,
document_name=mf.qualified_name
)
v = violation(
message="Microflow '{}' has complexity {} (max: {}). Consider splitting into smaller microflows.".format(
message="{} '{}' has complexity {} (max: {}). Consider splitting into smaller {}s.".format(
mf.document_noun_title,
mf.name,
mf.complexity,
MAX_COMPLEXITY
MAX_COMPLEXITY,
mf.document_noun
),
location=loc,
suggestion="Break down complex logic into sub-microflows. Extract decision branches into separate SUB_ microflows."
Expand Down
4 changes: 2 additions & 2 deletions .claude/lint-rules/orphaned_elements.star
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,11 @@ def check():
if not has_callers:
loc = location(
module=mf.module_name,
document_type="Microflow",
document_type=mf.document_noun_title,
document_name=mf.qualified_name
)
v = violation(
message="Microflow '{}' is not called from anywhere.".format(mf.name),
message="{} '{}' is not called from anywhere.".format(mf.document_noun_title, mf.name),
location=loc,
suggestion="Remove if unused, or rename with ACT_/SCH_ prefix if it's an entry point."
)
Expand Down
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 @@ -126,3 +126,5 @@
{"area": "cmd/mxcli/diag", "date": "2026-09-23", "symptom": "`mxcli diag loop-report` showed all 5 `test` runs as 'did not close' although every test passed, and inflated the `-c` (111) and `exec` (180) counts in the same log. Reported as 'the command apparently skips the summary record on success too' \u2014 which is not what happens: `test` returns normally, PersistentPostRun fires, and the session_end IS written.", "cause": "mxcli runs mxcli. Measured from a real `mxcli test` with MXCLI_LOG_DIR pointed at a scratch dir: one parent session_start (pid 1071) followed by THREE child session_starts \u2014 `-c DESCRIBE SETTINGS`, `-c SHOW MODULES`, and an `exec` of the generated runner \u2014 before a single test executes. `new`, `eval`, `tui` and the LSP self-spawn the same way (six os.Executable() sites). buildInvocations segmented on 'next session_end OR next session_start, whichever comes first', so a child's start closed the parent's invocation and the parent's own end landed on whatever was open by then. session_end carried no pid, so pairing by process was impossible.", "file": "`mdl/diaglog/diaglog.go` (pid on session_end; parentPIDEnv marker set once in Init and inherited by every child), `cmd/mxcli/diag_loop_report.go` (buildInvocations pairs by pid with the positional rule as fallback; spawned runs excluded from the table and wall time, counted on their own line), tests `cmd/mxcli/diag_loop_report_test.go`", "insight": "The segmentation rule documented itself as exact 'for sequential invocations, which is what an agent loop produces' \u2014 and the thing that breaks that assumption is the tool itself, not concurrency by the user. When a tool can invoke itself, EVERY per-process measurement over it needs a parent link, not just a pid: a pid alone fixes the pairing but still counts three phantom agent calls per test run. The marker belongs on the ENVIRONMENT, not at each spawn site: exec.Command inherits the parent's environment (explicitly via os.Environ(), implicitly when Cmd.Env is nil), so one os.Setenv in Init covers all six self-spawn sites and any added later \u2014 six edits that would each have to be remembered become zero. Second-order trap: spawned runs must be excluded from WALL TIME too, not just the count, because a child's seconds are already inside its parent's; the test asserts 10s for a parent with three 1s children, and the reverted code says 3. Prove-by-revert done on the measured record shape: the positional rule gives Invocations=4 (want 1), Unclosed=1 for a parent whose tests all passed, Wall=3 (want 10).", "refs": ["ako/mxcli#617", "ako/mxcli#629"]}
{"area": "cmd/mxcli/syntax", "date": "2026-09-23", "symptom": "`mxcli syntax page datasource` documented `DataSource: MICROFLOW Module.MF($P)`. That form is a parse error: `dataview dv (datasource: microflow M.DS_X($State))` gives 'line 2:15 no viable alternative at input datasource'. Only the NAMED form `M.DS_X(State: $State)` parses. Hit in a real build, diagnosed from the error rather than the doc.", "cause": "The syntax entry was written from the intended shape rather than from something that had been run through the parser. Nothing checks it: the Syntax and Example fields are free text.", "file": "`cmd/mxcli/syntax/features_page.go` (page.datasource entry now shows `MICROFLOW Module.MF(Param: $P)` and states that the positional form is a parse error)", "insight": "CLAUDE.md deliberately points at `mxcli syntax` instead of restating syntax, so that it cannot go stale \u2014 which makes a wrong entry there worse than a wrong entry in prose, because it is the thing consulted INSTEAD of checking. The cost lands in the agent loop: read it, write it, fail to parse, diagnose, retry. Measured before reaching for the systemic guard: 42 of 164 syntax examples fail `mxcli check` today, but the large majority are fragments by design (a microflow body like `IF \u2026`, a widget snippet like `DATAGRID \u2026`, an OQL fragment) and are legitimately not standalone top-level MDL \u2014 so a blanket 'every example must parse' test would be mostly noise, and making it useful needs a way to mark which examples are standalone. Measuring that first is what stopped a plausible-sounding guard from being built wrong.", "refs": ["ako/mxcli#630"]}
{"area": "cmd/mxcli/test", "date": "2026-09-23", "symptom": "Windows: `mxcli test tests/ -p MyApp.mpr --local` fails with `local runtime: starting mxbuild serve: mxbuild --serve did not become ready` after caching a Linux ELF in %USERPROFILE%\\.mxcli\\mxbuild, and there is \"no flag, environment variable, or mechanism to redirect mxcli to the Windows mxbuild.exe already present in the Studio Pro installation\"", "cause": "Two layers. The platform part (downloading/exec'ing the Linux binary, serving from the cache instead of the resolved binary) was already fixed by #916 and #1122, both after the reporter's v0.21.0. What remained on main: `test` never registered `--mxbuild-path` — `run` gained it in #1125, but `test --local` boots through the same `ResolveMxBuildForLocal` and prints the same 'pass --mxbuild-path' guidance while answering `unknown flag`. `RunOptions` had no field and `localAppOptions` never set `LocalAppOptions.MxBuildPath`, though StartLocalApp honoured it. No env override existed anywhere", "file": "`cmd/mxcli/main.go` + `cmd_test_run.go` (flag), `testrunner/runner.go` + `localapp_options.go` (plumbing), `docker/mxbuild_platform.go` (`MxBuildPathEnv`, read in `resolveMxBuildForLocalOn` after the flag)", "insight": "**The guard for #1125 asserted its invariant against one command** — `TestErrorGuidanceNamesAFlagThatExists` checked only `runCmd`, while the guidance it polices is emitted by a resolver two commands share. When a test pins 'the advertised flag exists', enumerate the callers of the code that ADVERTISES it, not the command the report named; it now iterates `run` and `test`. **Before fixing a platform report, date it against the fixes**: the reporter's first two suggestions ('download platform-correct binary', 'auto-discover Studio Pro') were already on main, and re-implementing them would have been churn — only the override was missing. Put the env var in the resolver, not the CLI, so `run --local` and `test --local` both get it from one line; a flag-level env read would have been one more per-command copy to drift. Control: the env test runs as goos=windows with an unmatched version, so without the override it fails fast with the 'Linux binary cannot run natively on windows' refusal instead of hitting the CDN; removing only the `MxBuildPath:` line in localAppOptions fails the plumbing test for both runners. **Unverified**: no Windows host; code-level with OS-injected tests", "refs": ["mendixlabs/mxcli#1086", "mendixlabs/mxcli#1125", "mendixlabs/mxcli#916", "mendixlabs/mxcli#1122"]}
{"area": "cmd/mxcli", "date": "2026-09-25", "symptom": "Shipped Starlark rules CONV009, CONV010, QUAL001, QUAL003, QUAL004 and CUSTOM002 report nanoflows and rules as microflows: \"Microflow 'NF_Foo' has 30 activities\", and documentType \"Microflow\" in the JSON and report output.", "cause": "microflows() yields all three flow flavours (one catalog table, MicroflowType MICROFLOW/NANOFLOW/RULE), and each rule hardcoded document_type=\"Microflow\" and a \"Microflow '...'\" message. The Go rules had already been fixed with Microflow.DocumentNoun() after MPR002 called a rule a microflow, but that method was never exposed to Starlark, so every Starlark rule had to re-derive it and none did.", "file": "mdl/linter/starlark.go, .claude/lint-rules/{conv009_max_microflow_objects,conv010_act_microflow_content,example_microflow,long_microflows,mccabe_complexity,orphaned_elements}.star, mdl/linter/starlark_flow_noun_test.go", "insight": "When a Go-side fix lives in a method, check whether the Starlark projection can reach it; a fix Starlark cannot call is a fix for half the rules. Exposed as document_noun / document_noun_title on the microflow struct, and the test runs every shipped rule over a fixture with one flow per flavour, requiring a finding on each (else vacuous) plus a guard that any new `for x in microflows()` rule joins the list. Skip the wrong turn of excluding nanoflows/rules from QUAL004: rule calls from decisions ARE emitted as 'call' refs (builder_references.go collectRuleCalls), so only the label was wrong.", "refs": "mendixlabs/mxcli#1178"}
{"area": "cmd/mxcli", "date": "2026-09-25", "symptom": "Starlark rule API docs name microflow_type values the linter never returns: the write-lint-rules skill said \"microflow\"/\"nanoflow\", example_microflow.star (copied into every project by mxcli init) said \"Microflow\"/\"Nanoflow\", only mccabe_complexity.star had \"MICROFLOW\"/\"NANOFLOW\", and none listed \"RULE\". The skill's entity table also omitted has_created_date/has_changed_date/has_owner/has_changed_by.", "cause": "LintContext.Microflows() passes the catalog's MicroflowType through raw (MICROFLOW/NANOFLOW/RULE) while Entities() CASE-normalizes EntityType to TitleCase, so the two adjacent iterators have opposite conventions and each doc author guessed. Nothing tied the documented literals to what the API emits, so two passes over the same skill file (59db6e7b, #1165) fixed instances and left this one.", "file": ".claude/skills/mendix/write-lint-rules/SKILL.md, .claude/lint-rules/example_microflow.star, .claude/lint-rules/mccabe_complexity.star, mdl/linter/starlark_documented_values_test.go", "insight": "Fix the class, not the row: observe the emitted field names and enum values by running a Starlark rule (dir(e), e.entity_type) over a fixture holding every stored kind, then assert the skill tables, the shipped rules' `# .field - ...` headers, and every `.entity_type/.microflow_type ==` comparison in shipped rules against that observed set. Equality, not subset, for the docs -- an undocumented value (RULE) is a flavour a rule silently mistreats. Normalizing MicroflowType instead would have broken every user rule already comparing \"MICROFLOW\" correctly.", "refs": "mendixlabs/mxcli#1178, mendixlabs/mxcli#1164"}
Loading
Loading