Typed design properties: registry-driven value types + check validation - #36
Merged
Conversation
ako
force-pushed
the
feature/typed-design-properties
branch
2 times, most recently
from
July 26, 2026 05:00
c664d48 to
2adb077
Compare
Design properties were written fully free-form: a flat value always serialized as an option, so a ColorPicker/ToggleButtonGroup property got the wrong BSON $Type for Studio Pro's Appearance tab, and a typo'd key or value (both case-sensitive) sailed through mxcli check. Root cause of why the existing theme registry was unused: resolveDesignPropsKey upper-cased the MDL keyword but the lookup map is lowercase-keyed, so `container` never resolved to `DivContainer`. That left resolveDesignPropertyValueType as dead code and also made `show design properties <widget>` report "not found" for valid widgets. Fixed to lower-case the lookup. - Write path: astDesignPropToValue now takes the widget's theme properties and resolves each flat value's type from metadata (ColorPicker / ToggleButtonGroup -> custom), falling back to option when no project / themesource (backward compatible). - Check (-p only, when themesource defines properties): new ValidateDesignProperties walks page/snippet/alter-page widget trees and warns on MDL-WIDGET11 (unknown key, with a case-sensitivity hint / the list of valid keys) and MDL-WIDGET12 (invalid value, listing the allowed values). Warnings, not errors, for forward-compat with newer themes. Compound entries and widgets without type-specific metadata are skipped. - LSP: caches the theme registry once per session (no per-keystroke I/O) and surfaces the same diagnostics. Adds executor unit tests, an example, and theme-styling / symptom-table docs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
ako
force-pushed
the
feature/typed-design-properties
branch
from
July 26, 2026 05:18
2adb077 to
8744867
Compare
ako
pushed a commit
that referenced
this pull request
Jul 29, 2026
A pass-through view column (a bare source-attribute ref like `select c.Name as X`) inherits the source attribute's length verbatim, and Mendix requires the declared length to match EXACTLY — declaring an unbounded `string` (or a different `string(N)`) against a `string(100)` source fails the build with CE6770 "View Entity out of sync". MDL031's length check previously covered only DERIVED columns (cast/case → 200); the references-mode validator compared pass-through strings with `typesCompatible`, whose `>=` rule only guards truncation, so the mismatch slipped through. `validateViewEntityTypes` now checks pass-through string columns with `passthroughStringLengthMismatch` (exact match), reporting the source entity/attr and inherited length. `col.SourceAttr` is set only for a bare attribute ref, so aggregates/derived expressions are unaffected. References-mode only (needs the domain model to resolve the source length). Test `TestPassthroughStringLengthMismatch`; example mdl-examples/bug-tests/ledger-36-view-passthrough-length.mdl. Verified on a real Mendix 11.12.1 project: `string`→CE6770 flagged, `string(100)`→clean. 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 29, 2026
…ll gaps (FINDINGS #42/#36/#23/#48/#47) - #42 DESCRIBE WORKFLOW dropped the `with (...)` param mappings: the modelsdk read path built a CallMicroflowTask with only Microflow+Outcomes and never populated ParameterMappings, so describe→drop→exec silently lost the mapping (which nothing then reports). Added microflowParamMappingsFromGen and wired it into both the CallMicroflowTask and CallMicroflowActivity read cases; the legacy sdk/mpr parser already read them. Round-trip test added; verified `describe workflow` now emits `call microflow M.ACT_Do with (Item = '$workflowContext')`. - #36 SEC005 lint suggested `ALTER PROJECT SECURITY STRICT MODE ON`, a statement the parser doesn't implement. Strict mode is Studio Pro-only — the suggestion now says so instead of naming an unrunnable command. - #23 documented `create or modify association` (the idempotent form) in the domain-model skill: plain `create association` is not idempotent and its failure aborts the rest of the script. - #48 documented `set task outcome $Task '<Outcome>'` (there is no `complete task`) and the other workflow task statements in write-workflows. - #47 documented that System-module enumerations are read from the runtime, not the .mpr, so mxcli can't resolve them — constrain on an attribute instead. 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 31, 2026
…t (TraceOps #36) `mxcli oql` is the documented way to verify data, but it could not query a `mxcli run --local` app: the local runtime booted the JVM with no system properties, so /dev/preview_execute_oql was never mounted (docker mode passes -Dmendix.live-preview=enabled + -Dmendix.running.locally.by.studiopro=true via docker-compose; the local boot did not), and `mxcli oql` failed with "Action not found" — silently 0 rows. Before that, the admin password was undiscoverable: run --local never printed it and oql errored with "admin password required". - LocalRuntimeOptions.jvmArgs() now always passes the two live-preview -D flags (run --local is always DTAPMode=D, matching docker mode). - resolveM2EEDefaults falls back to defaultLocalAdminPass when nothing else supplies a token (the admin API is loopback-only), so oql works against a local run with zero configuration. - The "Action not found" hint now branches to cover the --local case. - The run --local banner prints a ready-to-copy `mxcli oql` line. Tests: TestJVMArgs, updated TestResolveM2EEDefaults_Defaults. 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.
Implements the "typed design properties" requirement (previously deferred P2 in
PROPOSAL_atlas_design_system.md:433/ open question inpage-styling-support.md:402).The problem
Design properties were written fully free-form. A flat value always serialized as an option, so a
ColorPicker/ToggleButtonGroupproperty got the wrong BSON$Typefor Studio Pro's Appearance tab, and a typo'd key or value — both case-sensitive — passedmxcli checkand only failed later.Root cause found along the way
The theme registry (
themesource/*/web/design-properties.json→theme_reader.go) already carried per-widget allowed keys/types/values, but nothing used it on the write/validate paths. Reason:resolveDesignPropsKeyupper-cased the MDL keyword while the lookup map is lowercase-keyed, socontainernever resolved toDivContainer. That leftresolveDesignPropertyValueTypeas dead code and madeshow design properties <widget>report "not found" for valid widgets. Fixed to lower-case the lookup.What's implemented
Write path —
astDesignPropToValuenow resolves each flat value's type from the registry (ColorPicker/ToggleButtonGroup→custom), falling back tooptionwhen there's no project/themesource (backward compatible;on/off/compound unchanged).Check (
-ponly, when themesource defines properties) — newValidateDesignPropertieswalks page/snippet/alter-page widget trees and warns:Both are warnings, not errors — a newer theme may legitimately add keys/values (forward-compat). Compound entries and widgets with no type-specific metadata (e.g. pluggable) are skipped to avoid false positives.
LSP — caches the theme registry once per session (no per-keystroke file I/O) and surfaces the same diagnostics.
Answering "does the error list the allowed values?"
Yes — MDL-WIDGET12 prints
Allowed values (case-sensitive): …from the registry, mirroringshow design properties.Tests & docs
typed-design-properties.mdl;theme-styling.mdvalidation section;fix-issue.mdsymptom row.Scoped deliberately to entity/widget design-property typing; the Atlas-first migration-skill update is a separate docs PR.
🤖 Generated with Claude Code
Generated by Claude Code