Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
0b21951
feat(grammar): add MDL grammar + AST for workflow activities and calc…
engalar Mar 21, 2026
29a3fa1
feat(sdk): add workflow BSON serialization + UnknownElement fallback …
engalar Mar 21, 2026
3cdac49
feat(executor): MDL executor for workflows, calculated attributes, de…
engalar Mar 21, 2026
f7b3edf
test(workflow): add BSON parse/write unit tests and MDL round-trip test
engalar Mar 21, 2026
a052d10
docs: update docs and skills for workflow, calculated attributes, sec…
engalar Mar 21, 2026
bec6d53
docs: add BSON discover tool design
engalar Mar 21, 2026
8e1ba99
feat(bson): add debug-only TypeRegistry and field classification package
engalar Mar 21, 2026
a3b1d59
feat(bson): add recursive BSON compare with smart array matching
engalar Mar 21, 2026
f245236
feat(bson): add discover command for BSON field coverage analysis
engalar Mar 21, 2026
35844b5
feat(bson): migrate dump-bson under bson parent command with build ta…
engalar Mar 22, 2026
1e53c37
docs: add workflow metadata gaps design (DISPLAY NAME, DESCRIPTION, E…
engalar Mar 22, 2026
af3c1bb
feat(workflow): add DISPLAY, DESCRIPTION, EXPORT LEVEL to CREATE/DESC…
engalar Mar 22, 2026
93fc926
fix(grammar): use qualifiedName for workflow parameter mapping identi…
engalar Mar 22, 2026
6d469ff
feat(executor): add per-statement output line limit and timeout guard
engalar Mar 22, 2026
67b7608
feat(bson): add NDSL normalized DSL renderer for LLM debugging
engalar Mar 22, 2026
0a1fc2c
feat(bson): add --format ndsl to bson compare for LLM-friendly side-b…
engalar Mar 22, 2026
5df43e8
feat(bson): add --format ndsl flag to bson dump command
engalar Mar 22, 2026
7ed7989
fix(bson): remove duplicate $Type header in nested object NDSL rendering
engalar Mar 22, 2026
7d69073
fix(workflow): correct P0 BSON writer bugs found via NDSL analysis
engalar Mar 22, 2026
72ae6cd
fix(workflow): emit missing MultiUserTaskActivity fields in BSON
engalar Mar 22, 2026
a4314bb
fix(workflow): P2 — remove extra ParameterExpression, add DESCRIPTION…
engalar Mar 22, 2026
8b2fbb7
fix(workflow): P0 — strip Module.Microflow prefix from parameter name…
engalar Mar 22, 2026
a50e243
fix(workflow): P1a — boundary event supports sub-flow body in grammar…
engalar Mar 22, 2026
305de27
fix(workflow): P2a — DESCRIBE outputs Caption comment for JumpTo/Wait…
engalar Mar 22, 2026
ca50d52
fix(workflow): P1b — verify annotation round-trip works correctly
engalar Mar 22, 2026
3c97158
fix(workflow): P2b — emit ParameterMappings in CALL WORKFLOW DESCRIBE…
engalar Mar 22, 2026
3fc58b2
feat(bson): promote bson commands from debug-only to release build
engalar Mar 22, 2026
a438c94
feat(cli): auto-discover .mpr file when -p is omitted
engalar Mar 22, 2026
4592d1b
fix(workflow): emit activity annotations as ANNOTATION statements for…
engalar Mar 22, 2026
c088bcc
chore: add bubbletea/lipgloss/bubbles dependencies for TUI
engalar Mar 22, 2026
45b1a20
feat(tui): add package skeleton, styles, runner helpers
engalar Mar 22, 2026
fb4242d
feat(tui): add mxcli tui cobra command
engalar Mar 22, 2026
6677b6f
feat(tui): modules panel — left column with project tree
engalar Mar 22, 2026
56e8664
feat(tui): elements panel — middle column with drill-down navigation
engalar Mar 22, 2026
2e80add
feat(tui): preview panel — DESCRIBE output viewport
engalar Mar 22, 2026
d628525
feat(tui): responsive three-column layout with status bar
engalar Mar 22, 2026
1f33de7
feat(tui): command bar, commands, shortcuts, help overlay
engalar Mar 22, 2026
1e24b28
docs(skills): add pre-execution validation step to OQL write workflow
engalar Mar 22, 2026
96604a8
docs: add tui implementation plan
engalar Mar 22, 2026
d474879
fix(tui): improve selection visual hierarchy with custom delegate
engalar Mar 22, 2026
5ffe467
feat(tui): command completion and fuzzy matching in cmdbar
engalar Mar 22, 2026
cb0e72b
feat(tui): project picker dialog with history when -p is omitted
engalar Mar 22, 2026
7938d45
feat(tui): lazygit-style UI with compare view, search, and BSON/MDL i…
engalar Mar 22, 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
53 changes: 53 additions & 0 deletions .claude/skills/mendix/docker-workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,21 @@ mxcli docker run -p app.mpr --fresh --wait

`docker run` handles everything: downloads MxBuild and runtime (if not cached), initializes the Docker stack (if needed), builds the PAD package, starts the containers, and optionally waits for the runtime to report successful startup.

## Creating an Empty Mendix App

To create a new blank Mendix project for testing (requires mxbuild to be downloaded first):

```bash
# Download mxbuild if not already cached
mxcli setup mxbuild --version 11.6.4

# Create a blank project
mkdir -p /path/to/my-app
~/.mxcli/mxbuild/{version}/modeler/mx create-project --app-name MyApp --output-dir /path/to/my-app
```

The `mx create-project` command creates an MPR v2 project with the standard Mendix module structure. You can then use the Docker workflow to build and run it.

## Step-by-Step Workflow

If you prefer more control, use the individual commands:
Expand All @@ -65,13 +80,38 @@ mxcli setup mxbuild -p app.mpr
# Download Mendix runtime matching the project version
mxcli setup mxruntime -p app.mpr

# Or specify version explicitly (without a project)
mxcli setup mxbuild --version 11.6.4
mxcli setup mxruntime --version 11.6.4

# Or preview what would be downloaded
mxcli setup mxbuild -p app.mpr --dry-run
mxcli setup mxruntime -p app.mpr --dry-run
```

MxBuild is cached at `~/.mxcli/mxbuild/{version}/` and the runtime at `~/.mxcli/runtime/{version}/`. Both are reused across builds.

#### Runtime-to-MxBuild Copying (PAD Build Prerequisite)

MxBuild 11.6.3+ expects runtime files (`pad/`, `lib/`, `launcher/`, `agents/`) inside its own `runtime/` directory, but `mxcli setup mxbuild` only downloads the build tools (not the full runtime). If the PAD build fails with `StudioPro.conf.hbs does not exist` or `ClassNotFoundException`, copy the runtime directories into mxbuild:

```bash
VERSION=11.6.4 # replace with your version

# After downloading both mxbuild and mxruntime:
cp -r ~/.mxcli/runtime/$VERSION/runtime/pad ~/.mxcli/mxbuild/$VERSION/runtime/pad
cp -r ~/.mxcli/runtime/$VERSION/runtime/lib ~/.mxcli/mxbuild/$VERSION/runtime/lib
cp -r ~/.mxcli/runtime/$VERSION/runtime/launcher ~/.mxcli/mxbuild/$VERSION/runtime/launcher
cp -r ~/.mxcli/runtime/$VERSION/runtime/agents ~/.mxcli/mxbuild/$VERSION/runtime/agents
```

**Important:** The PAD build output may only include partial runtime bundles (5 jars instead of 354). If the runtime fails to start with `ClassNotFoundException: com.mendix.container.support.EventProcessor`, copy the full runtime into the PAD build output:

```bash
rm -rf /path/to/project/.docker/build/lib/runtime
cp -r ~/.mxcli/runtime/$VERSION/runtime /path/to/project/.docker/build/lib/runtime
```

### 2. Initialize Docker stack (first time only)

```bash
Expand All @@ -81,6 +121,16 @@ mxcli docker init -p app.mpr

This creates a `.docker/` directory with Docker Compose configuration for the Mendix app + PostgreSQL.

**Port conflicts:** If default ports (8080/8090/5432) are already in use, check with `ss -tlnp | grep -E '808|809|543'` and use `--port-offset N` to shift all ports:

```bash
# Check which ports are occupied
ss -tlnp | grep -E '808[0-9]|809[0-9]|543[0-9]'

# Use offset to avoid conflicts (e.g., offset 5 → 8085/8095/5437)
mxcli docker init -p app.mpr --port-offset 5
```

### 3. Check project for errors

```bash
Expand Down Expand Up @@ -346,6 +396,9 @@ All defaults can be overridden in `.docker/.env`.
| Build fails with version error | Requires Mendix >= 11.6.1 for PAD support |
| No Dockerfile in PAD output | Normal for MxBuild 11.6.3+ — `mxcli docker build` auto-generates one |
| Runtime not found / runtimelauncher.jar missing | Run `mxcli setup mxruntime -p app.mpr` or let `docker build` auto-download |
| `StudioPro.conf.hbs does not exist` | Runtime not linked into mxbuild — see "Runtime-to-MxBuild Copying" above |
| `ClassNotFoundException: EventProcessor` | PAD has partial runtime bundles — copy full runtime into `.docker/build/lib/runtime/` (see above) |
| Port already allocated | Check ports with `ss -tlnp \| grep 808` and use `docker init --port-offset N --force` |
| `' etc/Default' is not a file` | Dockerfile CMD passes config arg — `docker build` patches this automatically |
| `DatabasePassword has no value` | Ensure `RUNTIME_PARAMS_DATABASE*` env vars are in docker-compose.yml — re-run `mxcli docker init --force` |
| `Password should not be empty (debugger)` | Add `RUNTIME_DEBUGGER_PASSWORD` — re-run `mxcli docker init --force` |
Expand Down
23 changes: 23 additions & 0 deletions .claude/skills/mendix/generate-domain-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,29 @@ COMMENT 'Additional documentation';

**Naming Convention**: `{FromEntity}_{ToEntity}` (e.g., `Order_Customer`, `Transaction_Account`)

#### Calculated Attributes

Calculated attributes derive their value from a microflow at runtime. Use `CALCULATED BY Module.Microflow` to specify the calculation microflow.

**IMPORTANT: CALCULATED attributes are only supported on PERSISTENT entities.** Using CALCULATED on non-persistent entities will produce a validation error.

```sql
@Position(100, 100)
CREATE PERSISTENT ENTITY Module.OrderLine (
/** Unit price */
UnitPrice: Decimal NOT NULL,
/** Quantity ordered */
Quantity: Integer NOT NULL,
/** Total price, calculated by microflow */
TotalPrice: Decimal CALCULATED BY Module.CalcTotalPrice
);
```

**Syntax variants:**
- `CALCULATED BY Module.Microflow` — recommended, binds the calculation microflow directly
- `CALCULATED Module.Microflow` — also valid (`BY` keyword is optional)
- `CALCULATED` — bare form, marks as calculated but requires manual microflow binding in Studio Pro

### Data Types

| Type | Example | Description |
Expand Down
7 changes: 6 additions & 1 deletion .claude/skills/mendix/manage-security.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,13 +171,18 @@ ALTER PROJECT SECURITY DEMO USERS OFF;
### Demo Users

```sql
-- Create demo user with roles
-- Create demo user (auto-detects entity that generalizes System.User)
CREATE DEMO USER 'demo_admin' PASSWORD 'Admin123!' (Administrator, SuperAdmin);

-- Create demo user with explicit entity
CREATE DEMO USER 'demo_admin' PASSWORD 'Admin123!' ENTITY Administration.Account (Administrator, SuperAdmin);

-- Remove demo user
DROP DEMO USER 'demo_admin';
```

The ENTITY clause specifies which entity (generalizing `System.User`) to use. If omitted, it auto-detects the unique System.User subtype in the project. If multiple subtypes exist, you must specify ENTITY explicitly.

## Starlark Lint Rule APIs

Security data is available in Starlark lint rules (`.star` files):
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,6 @@ grammardoc
*.pptx
# Excluded skills
.claude/skills/mendix/migrate-outsystems.md

# Snap tool binary (used for BSON fixture generation)
snap-bson
4 changes: 3 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -325,9 +325,11 @@ Full syntax tables for all MDL statements (microflows, pages, security, navigati
- Data import from external databases into Mendix app DB (`IMPORT FROM ... INTO ... MAP ...`)
- Database Connector generation from external schema (`SQL <alias> GENERATE CONNECTOR INTO <module>`)
- EXECUTE DATABASE QUERY microflow action (static, dynamic SQL, parameterized, runtime connection override)
- CREATE/DROP WORKFLOW with user tasks, decisions, parallel splits, and other activity types
- CALCULATED BY microflow syntax for calculated attributes

**Not Yet Implemented:**
- 48 of 52 metamodel domains (workflows, REST, etc.)
- 47 of 52 metamodel domains (REST, etc.)
- Delta/change tracking system
- Runtime type reflection

Expand Down
8 changes: 7 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev
BUILD_TIME = $(shell date -u +"%Y-%m-%dT%H:%M:%SZ")
LDFLAGS = -ldflags "-X main.Version=$(VERSION) -X main.BuildTime=$(BUILD_TIME)"

.PHONY: build release clean test test-mdl grammar completions sync-skills sync-commands sync-lint-rules sync-changelog sync-all docs documentation vscode-ext vscode-install source-tree sbom sbom-report lint lint-go lint-ts fmt vet
.PHONY: build build-debug release clean test test-mdl grammar completions sync-skills sync-commands sync-lint-rules sync-changelog sync-all docs documentation vscode-ext vscode-install source-tree sbom sbom-report lint lint-go lint-ts fmt vet

# Helper: copy file only if content differs (avoids mtime updates that invalidate go build cache)
# Usage: $(call copy-if-changed,src,dst)
Expand Down Expand Up @@ -101,6 +101,12 @@ build: sync-all completions
CGO_ENABLED=0 go build -o $(BUILD_DIR)/source_tree ./cmd/source_tree
@echo "Built $(BUILD_DIR)/$(BINARY_NAME) $(BUILD_DIR)/source_tree"

# Build with debug tools (includes bson discover/compare/dump)
build-debug: sync-all completions
@mkdir -p $(BUILD_DIR)
CGO_ENABLED=0 go build -tags debug $(LDFLAGS) -o $(BUILD_DIR)/$(BINARY_NAME)-debug $(CMD_PATH)
@echo "Built $(BUILD_DIR)/$(BINARY_NAME)-debug (debug build with bson tools)"

# Build for all platforms (CGO_ENABLED=0 for cross-compilation)
release: clean sync-all
@mkdir -p $(BUILD_DIR)
Expand Down
48 changes: 48 additions & 0 deletions bson/classify.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package bson

// FieldCategory classifies BSON fields by their role in serialization.
type FieldCategory int

const (
// Semantic fields carry business meaning (e.g., Name, Caption, Expression).
Semantic FieldCategory = iota
// Structural fields are BSON framing (e.g., $ID, $Type, PersistentId).
Structural
// Layout fields control visual positioning (e.g., RelativeMiddlePoint, Size).
Layout
)

func (c FieldCategory) String() string {
switch c {
case Semantic:
return "Semantic"
case Structural:
return "Structural"
case Layout:
return "Layout"
default:
return "Unknown"
}
}

var structuralFields = map[string]bool{
"$ID": true,
"$Type": true,
"PersistentId": true,
}

var layoutFields = map[string]bool{
"RelativeMiddlePoint": true,
"Size": true,
}

// classifyField returns the FieldCategory for a given BSON storage name.
func classifyField(storageName string) FieldCategory {
if structuralFields[storageName] {
return Structural
}
if layoutFields[storageName] {
return Layout
}
return Semantic
}
Loading
Loading