Repository navigation
Starlark rule API: documented literals drift from what the linter emits — microflow_type has three spellings, two of which never occur #1178
Description
Summary
#1164 / #1165 fixed two rules that compared entity_type to "PERSISTENT", a value the linter never returns. The instances are fixed; the class is not. The same drift is live right now on microflow_type, where the repository documents three different spellings and two of them never occur.
Found while reviewing #1165, on main at cb7cfa86.
The failure mode is silence
A Starlark rule that compares a field to a value the API never emits does not error. It skips every item, reports nothing, and is still listed by --list-rules. Its output is byte-identical to a clean project, which is why ARCH002 and ARCH003 went unnoticed indefinitely — and why "I ran the rule and it found nothing" is not evidence that a rule works.
Live instance: microflow_type
LintContext.Microflows() selects mf.MicroflowType raw (mdl/linter/context.go:552) — no CASE normalization — so Starlark receives what the catalog stores: "MICROFLOW", "NANOFLOW", "RULE" (context.go:512).
What the repo tells a rule author:
| source | documented values | correct? |
|---|---|---|
.claude/skills/mendix/write-lint-rules/SKILL.md:176 |
"microflow", "nanoflow" |
no — neither occurs |
.claude/lint-rules/example_microflow.star:17 |
"Microflow", "Nanoflow" |
no — neither occurs |
.claude/lint-rules/mccabe_complexity.star:21 |
"MICROFLOW", "NANOFLOW" |
yes |
No shipped rule is currently dead from this — the only rule that actually compares the field (missing_documentation.star:186) uses "MICROFLOW". But the two wrong sources are the two a new rule gets written from, and example_microflow.star exists to be copied. It is synced into cmd/mxcli/lint-rules and embedded (Makefile:74), so it ships into every project mxcli init touches.
Both wrong sources also omit "RULE" entirely. All three flavours share one catalog table, so a rule filtering microflow_type without knowing that silently treats rules as microflows or drops them — the same root cause as the DocumentNoun() comment at context.go:520.
Second instance: the entity field table is incomplete
entityToStarlark exposes 17 keys; the skill's entity table documents 13. Missing: has_created_date, has_changed_date, has_owner, has_changed_by — added in d6c4059 precisely so a rule could ask "which persistent entities have no audit trail", and undocumented since. Not a dead comparison, but the same drift: the API moved and its only documentation did not.
Why it recurs
59db6e7b (Sep 18) corrected "six of its example rows named values the API has never returned" in that same skill file, and never touched the entity_type row — which stayed wrong until #1165 five days later. Two passes, same file, same class, and nothing in CI can tell that a documented literal is unreachable.
There is also an inconsistency worth deciding on directly: Entities() normalizes its enum (CASE e.EntityType WHEN 'PERSISTENT' THEN 'Persistent', context.go:185) and Microflows() does not. Two adjacent iterators in one file with opposite conventions is the trap that produced both bugs.
Suggested fix
Either direction closes it; the test is the part that matters.
- Pin the literals in a test. Assert that every value documented in
write-lint-rules/SKILL.mdand in theexample_*.starcomment headers is one the corresponding API can actually emit. That is the check neither fix(lint): ARCH002 and ARCH003 compare entity_type to a value the linter never returns #1165 nor59db6e7badded, and it is what makes a third recurrence impossible rather than unlikely. - Remove the asymmetry, by normalizing
MicroflowTypeinMicroflows()the wayEntityTypeis normalized inEntities()— then one convention holds across the API and the docs have one spelling to state. Note this would be a behaviour change for any user rule already comparing"MICROFLOW"correctly, so it needs a CHANGELOG entry and probably a deprecation note; option 1 does not.
Fixing the two wrong sources without (1) leaves the next drift to be found by a user whose rule reports nothing.
Activity
github-actions commentedon Sep 24, 2026
Issue Triage
Summary
The issue points out that the documentation for
microflow_typeand several entity fields lists literal values that the mxcli linter never actually emits, causing Starlark rules that compare against those values to silently fail.Checklist of required bug‑report information
mxcli --versionor commit/build)mxcli diag --bundleor at least the session logNext steps
Could you please add the missing details above? For example, let us know which version of mxcli you’re using, the Mendix version of the project you analyzed, the exact command you ran, what you expected to see, and what you actually observed (including any logs or the output of
mxcli diag --bundle).Thanks for bringing this to our attention—once we have the extra information we can investigate and fix the drift.
Automated triage via OpenRouter — workflow source
fix(lint): pin documented Starlark field values to what the API emits
fix(lint): name nanoflows and rules correctly in shipped Starlark rules
docs(lint): document every Starlark builtin and struct field; test th…
Merge pull request #1178 from ako/fix/1428-doc-comment-bullet