Repository navigation
Sync ako/mxcli: annotations/folders/enum ids for lint rules, page round-trip fixes, MOVE access rules, docker builds as stored - #1793
Merged
Merged
Conversation
The generated opencode.json listed both skill trees as `instructions`, which OpenCode inlines whole: 150 files, 2.7 MB, ~73% of a 1M context window before the user typed anything. Its instructions are AGENTS.md alone; OpenCode discovers .opencode/skills/ and loads a skill when its description matches. Those copies were also given a second frontmatter, described by the skill's title, in front of the skill's own; OpenCode read the title instead of the "Use when…" description. A skill with frontmatter now keeps its description in a single block. Fixes #1822 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82qrr1WnXxq1eRn7qRJ
Inside a loop Mendix allows only Rollback (CE0644; check warns MDL006 on anything else), and a call to a Java action that exists to throw, such as CommunityCommons.ThrowException, is how a flow rolls itself back. CONV013 reported both, so an app needed a baseline entry for a deliberate pattern. Neither is reported now; other external calls are reported as before. Fixes #1838 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82qrr1WnXxq1eRn7qRJ
describe page X, then exec of that output, reported "Replaced page"
for 15 of TestApp's 68 pages with nothing changed. Three values MDL
cannot state were regenerated on rebuild:
- a tab container's DefaultPagePointer: stored null ("no default"),
written as the first tab; a stored second-tab default was reset on
every pass, a real loss;
- an Expression with a trailing newline, which MDL writes bare;
- an empty screen-reader label Studio Pro stores as a ClientTemplate
with no text, written null.
Reconcile now carries each from the stored element of the same $ID,
after TransplantIDs: the default tab while it is null or names a tab
the rebuild still has, an expression that differs only in surrounding
whitespace, an empty template where the rebuild writes null. All 15
pages report Unchanged; a real change still lands.
Refs #1897
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011oK82qrr1WnXxq1eRn7qRJ
…1436) A rule saw a folder only through the folder of a document in it, so an empty folder did not exist for it. folders_data holds one row per folder with its module, path (spelled as a document's Folder), parent path, depth and the documents and folders directly in it; folders() exposes it to Starlark rules. The rows are project-wide: a document moving between folders changes two folders' counts but rebuilds only the document. CATALOG.FOLDERS needed FOLDERS in catalogTableName, being a keyword; without it the select parsed to nothing and printed nothing. A new test parses every name Catalog.Tables() lists, and found CATALOG.AGENTS broken the same way on main, fixed here too. Schema 38. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
feat(catalog): folders() and CATALOG.FOLDERS, empty folders included (#1436)
The integration suite fails when a listed loss stops reproducing, and this one did: the page's whole-document round trip is now exact, the tab container's null default tab being carried (#1897). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82qrr1WnXxq1eRn7qRJ
…ists The round-trip suites fail when an allowlisted document stops breaking, and the carries for #1897 made 23 of them exact: Account_Overview on PedApp and TestApp, and on TestApp fifteen WorkflowCommons pages and seven of its snippets. No other document's outcome changed; make test-integration-roundtrip passes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82qrr1WnXxq1eRn7qRJ
enumerations().values gave each value's caption in the default language only, and a caption in another language is a strings() row naming the value only by element_id, which matched nothing a rule could see. Each value now carries id, the value's $ID, which is that element_id, so a rule can resolve getCaption(Module.Enum.Value) per language. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…24rqgv Unchanged pages no longer rewritten, opencode context size, CONV013 false positives
feat(lint): an enumeration value's id in Starlark rules (#1301)
Splitting a module with MOVE left an entity access rule's XPath naming the old module ([Src.Order_Customer/Src.Customer/...]; 11.12.6 mx check: CE1613 for both), its rules on the old module's roles, and a moved nanoflow's grants unmapped while a microflow's are mapped. The reference sweep now also rewrites path steps, in XPaths and in expressions such as $O/Src.Assoc/Name, when the moved element is an entity or an association; an enumeration rename still leaves a same-named association alone. An entity's access rules and a nanoflow's grants move to the target's same-named roles; a role the target lacks is kept, with a warning. Measured on a blank 11.12.6 app: the issue's split leaves 2 errors with main, 0 with this change. Fixes #1836 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82qrr1WnXxq1eRn7qRJ
They ran mx update-widgets on their temporary copy before the pre-build check and MxBuild, so a project whose stored widget definitions are stale built, while docker check, run --local and Studio Pro reported the CE0463s: the deployment was not built from what is committed. The pre-build check now checks the stored copy, as docker check does since #646, and on CE0463 labels each one as a stale definition `mxcli fix widgets` clears or one that persists; MxBuild builds the model as stored. --update-widgets (build, run, reload) keeps the old behaviour and says the project still has stale widgets; --no-update-widgets skips the labelling re-check. Fixes #1794 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82qrr1WnXxq1eRn7qRJ
…lised hop describe → exec of TestApp's WorkflowCommons.ManageTaskAssignments was refused: its snippet call omits $Account, which Studio Pro stores unmapped and mx check accepts (11.14) because a System.User data view two containers out supplies it, while the builder looked at the nearest container only. An omitted parameter is now satisfied by any enclosing data container whose entity is the parameter's, a specialisation or a generalisation of it. With that lifted the page built with CE1613: describe printed the single association hop TaskAssignmentHelper_User without its stored destination Administration.Account, so the rebuild arrived at System.User and labels bound to FullName lost their attribute. A hop whose stored destination is neither end of its association now prints Assoc/Destination. The page now reports Unchanged and mx check 0 errors; it and three WorkflowCommons snippets leave the TestApp round-trip allowlist. Fixes #2055 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82qrr1WnXxq1eRn7qRJ
…rioritization-24rqgv
…24rqgv MOVE rewrites XPaths and roles; docker build builds the stored project; snippet params from outer containers
mendixlabs#1785 reported `EntityToRefresh = "CustomModule"."NPActivity"` stored with its MDL quotes on mxcli 0.26.0, giving CE1613 at mxbuild. Main stores the bare qualified name (EntityTypeCodeActionParameterValue, checked in the BSON) and mx check 11.14 reports 0 errors on TestApp. The reporter's MDL is now a test, so a regression is caught by name. Refs #2057 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82qrr1WnXxq1eRn7qRJ
… notes (#1300) A microflow's annotations reached a rule as activities; a domain model's were in no table, so a "no TODO notes" rule passed every domain model. annotations_data holds one row per domain model annotation with its module, full caption (newlines kept) and canvas position, owned by the domain model unit like the entity rows; annotations() exposes it to Starlark rules. ANNOTATIONS joins catalogTableName, being a keyword. Schema 39. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`emptyplaceholder { ... }` on a Data grid 2 (or Gallery) was accepted by
check and exec, and the page then failed mx check with CE0463 on the
grid (11.14): the slot is hidden while showEmptyPlaceholder is "none",
its default. Studio Pro's own grid with a placeholder stores "custom".
MDL-WIDGET10 now counts a slot filled by a child block as set, and a
filled hidden slot is an error naming the property, as a hidden action
already is. `mxcli syntax page.widgets` documents the form that builds
(showEmptyPlaceholder: 'custom' plus an emptyplaceholder block) and its
ALTER PAGE equivalent; both check clean in mx check and round-trip
through describe unchanged.
Fixes #1862
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011oK82qrr1WnXxq1eRn7qRJ
feat(catalog): annotations() and CATALOG.ANNOTATIONS for domain model notes (#1300)
) jar_dependencies() lists the Maven dependencies module settings declare, not what is on disk, so a hand-added jar and the managed one in another version went unseen. jar_files() reads the top level of userlib/ and vendorlib/ at each call, through the backend's Path(), and gives each jar's folder, file name, library name and version (split at the last dash followed by a digit) and the modules whose .RequiredLib marker names it. No catalog change: the jars change without the .mpr changing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…24rqgv Empty placeholder documented and checked; pin quoted entity-type JS action arguments
feat(lint): jar_files() lists the jars in userlib/ and vendorlib/ (#1304)
Brings in upstream's two commits the fork lacked: the v0.31.0 release changelog/blog and a gofmt of splice_handler_test.go. CHANGELOG resolved by hand. Git's merge placed the fork's 11 Unreleased entries (work that is not in the v0.31.0 tag) under the new [0.31.0] heading; they stay under [Unreleased]. Everything from [0.31.0] down is upstream's text verbatim. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AeAyg3qx2my26Q8cvGyW5z
Upstream's 1365ba4 reformatted it with a gofmt other than go1.27.3's, the toolchain go.mod pins and make fmt-check runs, so the merged tree failed fmt-check (mendixlabs#1793). This restores the fork's toolchain-formatted version; make fmt-check passes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AeAyg3qx2my26Q8cvGyW5z
`brain capture --from-json <file|->` queues a JSON array of entries: every item is validated before any is queued (a bad one is named by its index), and a duplicate of a committed, queued or earlier item is skipped with the existing id, so the same list twice is a no-op. Ids are assigned against those given earlier in the batch as well as the stored ones, and the queue is appended once under its lock. `brain promote <id>...` resolves every id and checks each shard's cap with all of the batch's additions before writing anything. Shards are written first, each atomically, then the queue once; a re-run after an interruption between the two counts an id already in its shard with the same content as promoted and completes the batch. --to applies to every id, and a single id keeps its --json object shape. Shard files are now written through writeFileAtomic. Fixes #2054 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82qrr1WnXxq1eRn7qRJ
…it (#1303) With two buttons on a page a rule could not tell which caption belonged to the one without a confirmation: widgets() had no caption, and the strings() caption row named the button's inner Forms$ClientTemplate. widgets gains Caption and Tooltip in the default language (a button's CaptionTemplate, a label's Caption), and strings gains WidgetId, the nearest named Forms$ or CustomWidgets$ element around the text, so a widget's caption, tooltip and confirmation texts can be collected per language. Schema 40. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # CHANGELOG.md
Merge upstream v0.31.0 into main; re-gofmt splice_handler_test.go with the pinned toolchain
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nces (#2074) An agent-editor document produced no refs, and a microflow passed as a microflow-typed Java action parameter was no reference, so an agent's tool microflow, a chat context's ActionMicroflow and MCPServer.AddPrompt's Microflow showed "(no callers found)" and sat in GRAPH_DEAD_ASSETS. The agent pass now decodes each document (mprread.DecodeAgentEditorUnit, the decoder describe agent uses) and buildReferences writes its edges: an agent's tool microflow, nanoflow or agent is a call, a knowledge base or MCP service a tool, its model a model, its context entity a type, and a model's or knowledge base's key constant a key. A microflow or agent document passed as a Java action parameter is a call. show callers counts tool and model. Schema 41. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…24rqgv brain: capture and promote many entries as one act
feat(catalog): a widget's caption and tooltip, and its texts tied to it (#1303)
fix(catalog): agents and the microflows a Java action runs are references (#2074)
#2031) Agent Editor 2.2+ refused every agent mxcli created: AgentEditorCommons' AgentFromModel_Validate requires SelectedModelID ("Model with name is referenced but could not be found for the Agent"), and the refusal at startup stops the import of every agent document. mxbuild does not read agent documents, so check and the build stayed green. - create / create or modify / alter agent take SelectedModel: '<id>' and an optional SelectedModelName. IM_AgentFromModel reads only selectedModel/id (matched against DeployedModel.Model); name is the display text Studio Pro stores, so it defaults to the id and keeps the stored name while the id is unchanged. '' clears it; left out, create or modify keeps the stored value. - selectedModel is modelled in the Contents carry and written after model, before entity, as Studio Pro does. describe prints it. - check warns on a create agent without one (MDL-AGENT02). - Skill, syntax help, reference page, quick reference and examples show it (part of #2067). Measured: AgentEditorCommons 2.2.1 (ICXGraphPilot, mxcli-chat) and 2.6.0 (Agent Builder Starter App) require it; 1.1.0 (FactoryManagement) does not read it. describe -> exec of every agent-editor document in fresh ICXGraphPilot (6), FactoryManagement (33) and starter-app (9) copies changes no unit; a build without the encoder field changes GraphExplorer. alter set SelectedModel changes only selectedModel, and setting it back restores the stored bytes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82ttaGzay5CwiC2V7cf
…2075) CATALOG.AGENTS and its siblings held a document's name only; the settings live in the JSON Contents the agent pass did not read. AGENTS gains usage type, model, selected model, generation settings, streaming switches (NULL when not stored), context entity, variables and tool counts; AI_MODELS and KNOWLEDGE_BASES provider and key constant; CONSUMED_MCP_SERVICES protocol version, version and timeout. New AGENT_TOOLS (with the AGENT_MCP_SERVICES view), AGENT_KNOWLEDGE_BASES and PUBLISHED_MCP_SERVICES; a published MCP service's tool and authentication microflows are publish edges. Schema 42. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With a microflow M.Nightly and a scheduled event M.Nightly, `move scheduled event M.Nightly to folder 'Jobs'` was refused as "a microflow, not a scheduled event": the generic move looked the name up whatever its type and took the first match. A name is unique per document type, not per module. FindDocumentUnits returns every document of that name in the module, and the move (and its already-placed check) picks the one of the asked kind, falling back to the first so a true typo still names what the document is. Verified on TestApp: the unfixed binary refuses, the fixed one moves the scheduled event only, and mx check reports 0 errors. Fixes #2072 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82qrr1WnXxq1eRn7qRJ
feat(catalog): agent details, agent tools and published MCP services (#2075)
CATALOG.STRINGS indexed only an agent's documentation, so search could not find its system or user prompt or the descriptions the model reads for each tool and knowledge base. They live in the JSON Contents, which the translatable walk does not see. The strings pass now indexes them from the documents the agent pass already decoded, each row owned by its agent's unit. Schema 43. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ompts # Conflicts: # CHANGELOG.md # mdl/catalog/tables.go
…#2060) create consumed mcp service wrote only protocolVersion, version, connectionTimeoutSeconds and documentation. AgentEditorCommons' IM_ConsumedMCPService maps endpoint/qualifiedName to MCPEndpointConstant and authenticationMicroflow/qualifiedName to GetCredentialsMicroflow, and ConsumedMCPService_CreateUpdateFromModel imports the service only when the endpoint constant has a value. So an mxcli-written service was skipped at startup and an agent's mcp service block got no tools, while mx check and the build stayed green. - create / create or modify / alter consumed mcp service take Endpoint: @Module.UrlConstant (a String constant) and AuthenticationMicroflow: Module.GetHeaders; describe prints them; create or modify keeps stored ones; alter ... = '' clears them. - Both are modelled in the Contents carry; a new document writes endpoint first and the credentials microflow last, each documentId first, as Studio Pro 11.16 saves them. - check warns on a create without an Endpoint (MDL-AGENT03). check --references and exec refuse a missing or non-String constant; --references also refuses a credentials microflow MCP Client cannot call: ConsumedMCPService_CreateMCPClient runs it with no arguments and reads its result as a list of System.HttpHeader. - Agents skill, syntax help, reference page and examples (part of #2067). Measured: the same mapping in AgentEditorCommons 1.1.0, 2.2.1 and 2.6.0; documentId is the referenced unit's id. describe -> exec of every agent-editor document in fresh ICXGraphPilot (6), FactoryManagement (33) and starter-app (9) copies changes no unit; a build without the encoder field changes all six FactoryManagement consumed MCP services. alter set Endpoint changes only endpoint, and setting it back restores the stored bytes. mx check of a copy with a new service equals the untouched copy. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82ttaGzay5CwiC2V7cf
…24rqgv move: pick the document of the kind the statement names
A page hosting Conversational UI's chat needs a data view on ConversationalUI.ChatContext: the chat snippet takes that entity as its parameter, exactly as the module's own full-screen chat page does. No view entity or microflow can stand in, yet ARCH001 told every such page to use one. A cross-module entity is now exempt when the page calls a snippet, or links to a page, of that entity's module that takes the entity as a parameter, read from the refs table the catalog already builds. Every other cross-module data view is still reported. Verified on a real catalog: the old rule flags the chat host page, the new one does not, and a bare data view on the same entity stays flagged. Fixes #2069 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82qrr1WnXxq1eRn7qRJ
feat(catalog): agent prompts and tool descriptions in full-text search (#2075)
…ed-model # Conflicts: # CHANGELOG.md # mdl/types/agenteditor.go # modelsdk/mprread/reader_documents.go
…24rqgv lint: ARCH001 exempts an entity fed to its own module's snippet or page
`rename page M.Old_Page to New_Page;` followed by `show page
M.New_Page` was refused by check --references ("page not found"),
though exec ran it. The rename was recorded only in indirectDocs, which
only the alter-target check reads; the reference checks consult each
kind's own script-defined set. markIndirectDoc now writes both, for
renames and cross-module moves alike.
Verified on TestApp: check refused before and passes after; exec and
mx check report 0 errors.
Fixes #2070
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011oK82qrr1WnXxq1eRn7qRJ
…24rqgv check: resolve a document renamed or moved earlier in the script
fix(agents): create agent writes the selected model Agent Editor needs (#2031)
fix(agents): a consumed MCP service gets its endpoint and credentials (#2060)
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.
Syncs
ako/mxcli:maininto upstream: 14 commits — the code behind several v0.31.0 release-note entries, plus page round-trip, MOVE, lint and docker fixes. 7 upstream issues fixed.Lint API and catalog
annotations()andCATALOG.ANNOTATIONS— domain model annotations, one row each with module, full caption (newlines kept) and canvas position. A microflow's annotations reached a rule as activities; a domain model's were in no table, so a "no TODO notes" rule passed every domain model. Schema 39. Fixes Starlark lint API: domain model annotations are not readable (only microflow annotations are) #1309idin Starlark rules — the value's$ID, which is theelement_idof its caption rows instrings(), so a rule can resolvegetCaption(Module.Enum.Value)per language. Fixes Starlark lint API: enumeration values and their captions are not readable, so getCaption() cannot be resolved #1310folders()andCATALOG.FOLDERS, empty folders included — module, path, parent path, depth and direct contents.FOLDERS(and, found by a new test that parses every catalog table name,AGENTS) is a keyword, soselect … from CATALOG.FOLDERSparsed to nothing and printed nothing. Schema 38. Fixes lint: no folders() and empty folders are invisible #1538Pages
emptyplaceholder { … }was accepted whileshowEmptyPlaceholderwas its defaultnone, which hides the slot — CE0463 on the grid. MDL-WIDGET10 now counts a slot filled by a child block as set, and a filled hidden slot is an error naming the property.mxcli syntax page.widgetsdocuments the form that builds (showEmptyPlaceholder: 'custom'plus the block) and its ALTER PAGE equivalent. Fixes Data grid 2: no MDL form for the emptyPlaceholder slot #1704mx checkaccept — not only the nearest. And an association hop whose stored destination is neither end of its association printsAssoc/Destination, so the rebuild arrives at the stored entity instead of the association's end.MOVE between modules
Splitting a module left an entity access rule's XPath naming the old module (
[Src.Order_Customer/Src.Customer/…], CE1613), its rules on the old module's roles, and a moved nanoflow's grants unmapped. Path steps in XPaths and expressions are now rewritten when the moved element is an entity or association, and an entity's access rules and a nanoflow's grants move to the target's same-named roles (a role the target lacks is kept, with a warning). Measured on 11.12.6: the issue's split leaves 2 errors before, 0 after. Fixes #1687lint
CommunityCommons.ThrowException. Fixes CONV013 flags a deliberate ThrowException call and java action calls in a loop, where Rollback is the only valid handling #1689docker build / run / reload
They ran
mx update-widgetson their temporary copy before the check and build, so a project with stale stored widget definitions built whiledocker check,run --localand Studio Pro reported CE0463 — the deployment was not built from what is committed. The pre-build check now checks the stored copy and labels each CE0463 as onemxcli fix widgetsclears or one that persists, and MxBuild builds the model as stored.--update-widgetskeeps the old behaviour (and says the project still has stale widgets);--no-update-widgetsskips the labelling re-check.init --tool opencode
The generated
opencode.jsonlisted both skill trees asinstructions, which OpenCode inlines whole: 150 files, 2.7 MB, ~73% of a 1M context window before the user typed anything. Its instructions are nowAGENTS.mdalone; OpenCode discovers.opencode/skills/and loads a skill when its description matches. Those copies no longer get a second frontmatter whose title-based description OpenCode read instead of the skill's own. Fixes #1683Tests
EntityToRefresh = "CustomModule"."NPActivity"on a JavaScript action argument is pinned: main stores the bare qualified name andmx check11.14 reports 0 errors, so the regression reported against 0.26.0 is caught by name. Refs #1785