Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Sections dated before 2026-09-19 predate the cycle and stay as they are. Named m

## Unreleased

- fix(test-agent): **the test-agent brief now names `journeys/` as a write location** ([#359](https://github.com/MendixMau/mxcli-project-toolkit/issues/359)). The brief confined writes to `{{TEST_DIR}}` (filled as `tests/e2e/`), while `verify-module.sh`, `fixture-manifest.sh`, `journey-proof.md` and the Stage-6 artifact gate read journeys from `${JOURNEY_DIR}` (default `journeys/`). A test-agent that obeyed its brief wrote `tests/e2e/journeys/*.journey.json`, which the gate never found, so the journey row stayed owed until the project added a root symlink. The brief and its workflow step now send journeys to `journeys/<Module>.journey.json` at the project root and say not to relocate them (`fixture-manifest.sh` reads only `journeys/`, whatever `JOURNEY_DIR` says); `agent-roles.md` says nothing fills `{{TEST_DIR}}` and how to fill it. A project's already-completed `test-agent.md` keeps its old text: `bin/sync-project.sh <project> --diff-completed` shows the change to copy in. No auto-fill: `init-agents.sh` and `sync-project.sh`'s pristine-stub comparison would both have to apply it, and the test directory is a project fact. Field evidence: an existing-app project (Ollama connector app, macOS) whose journey row cleared only after `ln -s tests/e2e/journeys journeys`. — joshuamoesa
- process(build): **Stage 5 drafts the ready set in parallel and applies serially.** The runbook dispatch row said "sequential within a module", which serialised drafting even for independent scripts; it now points to `iterative-build-loop.md` → Gate cost, the single statement of the rule. The unit is the build-plan row: every `BUILD` row whose "Depends on" rows are all applied, minus overlapping writers (two rows that replace, alter or drop+create the same document never share a ready set, and no row is drafted while it overlaps a queued unapplied one; `brd-to-build-plan.md` has Produces name every document a row writes), runs at once, its scripts in order, one `mdl-agent` per script. Applies stay one at a time through `bin/exec.sh`, and the ready set is recomputed after each. A queued draft made before a sibling apply landed is re-checked with `mxcli diff --format struct` (preflight STOP rule 23); any removal line (checked against `describe` per BUG-146) or STOP rule 21 target means re-draft, never patch, because a stale restatement of a shared document is exactly rule 21's silent seed-call loss and passes `check --references`. Report `ready set N, drafted N, applied k`; the `mdl-agent` template says a drafter never applies and never depends on an unapplied draft. Field evidence: none yet. — MendixMau
- fix(platform-link): **CLI commits now show their changed documents in Studio Pro History.** Studio Pro's History → Model changes pane reads a `ModelChanges` array from the commit's `refs/notes/mx_metadata` note. Trap 6c's hand-written template set it to `[]`, so every mxcli/agent commit showed "Model changes 0" (field project: 270 of 270 notes empty). New `project-bin/mx-metadata-note.py` (stdlib only) computes the array from the commit's changed `.mxunit` files, in Studio Pro's entry shape: Status, UnitID, UnitType, UnitName and Module (walked up the `.mpr` Unit tree). It has `changes` / `write` / `backfill` / `sync <remote>` subcommands. `install-project-hooks.sh` now also installs post-commit and post-rewrite hooks that write the note and never block, and `--check` covers them, so `sync-project.sh` rolls them out to wired projects. Notes are published with `mx-metadata-note.py sync <remote>` after the branch push. Push config is never touched. With mxcli v0.26+ in the project root the hooks call `mxcli git note --write` instead (mendixlabs/mxcli#1337); the Python script is the fallback for older pins, and on 160 field commits both wrote the same 3,594 entries. Trap 6c rewritten. Measured against Studio Pro's own notes, 51 commits in 5 apps: 3387/3389 entries exact on all five fields. Field run on a 357-commit Mendix 11.15.0 app: 158 notes backfilled and pushed, and Studio Pro History lists the documents per revision. Review fixes: an earlier revision added `HEAD` + the notes ref to `remote.<r>.push`. It was dropped because any push refspec replaces `push.default`. A branch tracking a differently named upstream got a new same-named branch on Team Server where `simple` refuses, a missing local notes ref failed the whole push, and nobody knows whether Studio Pro's own push reads that config. The installer now only fetches the remote's notes (non-forced). It removes that exact `HEAD` + notes pair if present, and leaves and reports any other entry. `sync` handles a remote with no notes ref (it used to exit 1) and retries a rejected push once after re-merging. A note that already lists changes (Studio Pro's) is never overwritten by `write`/`backfill` without `--force`, and `sync` keeps a colleague's non-empty note over ours. The mxcli probe greps `git note --help` for `--write`. Hooks and docs call the script through `resolve_py`. Fixture `tests/wave2/test-mx-metadata-note.sh` (40 cases, over real captured template units; single- and two-tree layouts, amend, backfill and `--force`, push exit codes identical to a no-hooks clone, leftover-refspec cleanup, sync to an empty remote and its retry, notes fetch at install, a diverged notes merge; green under `init.defaultBranch` master and main). — field project (Mendix 11.15 app), MendixMau
- learn(fixture-seeding): **explore the data structure first, choose rows by use case, scan actions for resets before any run.** Two seeding runs on public template apps: seeding raised journey passes 33 -> 58 and 20 -> 51 of the same sets (FAIL 93 -> 68, 163 -> 132; INVALID unchanged), and a "Reset all demodata" journey wiped accounts so 104 of 127 journeys reported `The username or password you entered is incorrect`, identical on empty and seeded databases. Skill gains three questions a seed must answer, a use-case checklist, a destructive-action scan, a generic traps table with symptoms, measured expectations and a denominator checklist; routing trigger now fires on seed/test/demo data and empty pages. Independent review fixes: object ids follow the Mendix bigint pattern with a business-key guard (no uuids), associations are seeded where the page's path stores them, four new traps (enum names, inheritance chain, calculated attributes, view/external entities), and the port-offset and container-label traps moved to `harness-architecture.md`. — MendixMau
Expand Down
16 changes: 10 additions & 6 deletions agents/test-agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@ tools: Read, Grep, Glob, Bash, Write, Edit

You author and run e2e test specs for {{PROJECT}}'s running UI.

**The boundary that matters:** you may create and edit files under {{TEST_DIR}}. You may NEVER
edit MDL, never touch the `.mpr`, never run `mxcli exec` or any `--mcp` write — those are model
changes and are out of scope regardless of what a test failure seems to call for. If a test
proves the model is wrong, that is a finding you report, not a fix you make. `mxcli -c "SHOW ..."`
and `"DESCRIBE ..."` reads are always fine, and are how you ground every name you use.
**The boundary that matters:** you may create and edit files under {{TEST_DIR}}, and journey
files (`<Module>.journey.json`) under `journeys/` at the project root. Do not relocate journeys:
`verify-module.sh`, `fixture-manifest.sh` and the Stage-6 artifact gate read them there, and a
journey under {{TEST_DIR}} stays owed. You may NEVER edit MDL, never touch the `.mpr`, never run
`mxcli exec` or any `--mcp` write — those are model changes and are out of scope regardless of
what a test failure seems to call for. If a test proves the model is wrong, that is a finding
you report, not a fix you make. `mxcli -c "SHOW ..."` and `"DESCRIBE ..."` reads are always
fine, and are how you ground every name you use.

## Skills — open each one when its trigger fires
<!-- Generated from mxcli-project-toolkit/bin/lib/skill-routing.tsv by bin/render-routing.sh.
Expand Down Expand Up @@ -174,7 +177,8 @@ assert *which* user you are logged in as, not merely that login succeeded.
## Workflow
1. Take the module/scenario you were given (or the BRD/brief, if none was specified).
2. Ground every selector, microflow and entity name per "Grounding a new spec" above.
3. Write or extend the spec under {{TEST_DIR}}, following the established rung shape.
3. Write or extend the spec under {{TEST_DIR}}, following the established rung shape; a journey
goes to `journeys/<Module>.journey.json`.
4. Syntax-check the file before the first real run.
5. Run it, and cross-check state-changing results against the database.
6. If a page isn't reachable via nav, check grants before rewriting the nav path.
Expand Down
10 changes: 8 additions & 2 deletions skills/agent-roles.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,14 @@ This mirrors `iterative-build-loop.md`'s gate discipline (0 CE errors + happy pa

**One deliberate exception:** `test-agent` also carries `Write, Edit`, because it authors test
specs rather than only walking a scenario list someone else wrote. Its boundary is therefore
stated by *directory*, not by tool: it may write under the project's test directory and
nowhere else, and the never-`exec`/never-`.mpr` rule binds it exactly as it binds the others.
stated by *directory*, not by tool: it may write under the project's test directory and the
journey directory and nowhere else, and the never-`exec`/never-`.mpr` rule binds it exactly
as it binds the others. Nothing fills `{{TEST_DIR}}` for you: set it to the directory the
project's specs actually live in (`tests/e2e/` where `install-tests.sh` installed the engine;
check, don't assume). Journeys go to `journeys/` at the project root, never under
`{{TEST_DIR}}` and never relocated (`fixture-manifest.sh` reads only `journeys/`): a
test-agent that wrote them to `tests/e2e/journeys/` left the Stage-6 journey row owed until
the project symlinked `journeys/` (#359).
Do not widen any other agent's tools by analogy — this one is scoped by what it produces.
4. **Report back** which files you wrote, and flag any assumption you had to make because the project didn't document something (e.g. "assumed the demo user is X — couldn't find one specified, confirm").

Expand Down
Loading