Skip to content
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ Sections dated before 2026-09-19 predate the cycle and stay as they are.

## Unreleased

- learn(testing-shape, test-result-audit): **three test-strength rules, each with a denominator: refusals probed on the server, every undeclared 4xx a failure, one clean-database final run** ([#172](https://github.com/MendixMau/mxcli-project-toolkit/issues/172)). A field comparison of two builds against one frozen spec found the toolkit build checked permission refusals only in the client (a hidden menu item), logged unexpected 400/422 responses as information, and reached 20/20 by stitching three runs. `testing-shape.md` §7 gains three report lines (`N of N restricted pairs probed server-side`, `undeclared 4xx/5xx: 0 of M requests — each fails its step`, `one clean-DB run <id>: N of N scenarios incl. timers, not stitched`); `test-result-audit.md` gains check 2e, which carries the reasons and the field evidence and asks for those numbers. Both baseline skills stay inside the 80,000-word baseline budget (79,997): the reasons live in the on-demand audit skill, and two redundant sentences in `testing-shape.md` §4's verdict paragraphs were folded (the empty-set corollary is stated in the Trace row, `harness-architecture.md` and `report-schema.md`). The backing inbox note is trimmed to its unpromoted "Keep" items. — MendixMau
- learn(learned-detection-gaps, module-review): **two UI defects every model gate passes: a lazy-loaded combo box filter hides its preset, and a theme that pins row heights by position lets the next row cover an inserted widget** ([#299](https://github.com/MendixMau/mxcli-project-toolkit/issues/299)). Both passed check, mxbuild, lint and the scripted checks on a 127-module production app and were found only in the running app. Two register rows with the first oracle and the pre-build check (pluggable properties that change *when* data loads; grep the theme for fixed `height` on positional row classes before an insert), and two LOOK lines in `module-review.md` §4c with denominators (`N of N filters show their preset on first load`, `N of N widgets inserted into an existing container fully visible`). — jopterhorst
- fix(app-restart, test-stack-up): **a port held by another process before `run --local` is named and reported as "instrument blocked" (exit 4), never killed** ([#262](https://github.com/MendixMau/mxcli-project-toolkit/issues/262)). Studio Pro had started its own runtime on the app/admin ports a restart needed; `mxcli run --local` then failed with "Authentication failed" (the admin API answering was Studio Pro's), the next journey ran against Studio Pro's runtime, and four more runs were NOT RUN. `app-restart.sh` now checks the app port and the admin port (record's `adminPort`, else app + 10) before stopping anything — a holder outside the recorded process tree exits 4 with its name, pid and parent — and again after the stop, where anything still holding a port is by definition not ours. `test-stack-up.sh` runs the same check wherever it would tell you to start `run --local` (`--no-docker`, no Docker daemon, `--check` with a leftover record), on the record's ports, `RUN_LOCAL_APP_PORT`/`RUN_LOCAL_ADMIN_PORT`, or mxcli's defaults 8080/8090. Holder lookup: lsof, then ss, then netstat + tasklist on Windows; unnamed holders still block when nothing of ours is running. Fixtures: `test-app-restart.sh` +2 cases (14 assertions, all fail on the old script), `test-stack-up-local.sh` T7 (4 of 6 fail on the old script). — AlvinnYeo
- learn(record-demo-video): **four defects from a three-film demo set, ported as rules** ([#237](https://github.com/MendixMau/mxcli-project-toolkit/issues/237)). (1) From Node, read ffmpeg's freezedetect report with `spawnSync(...).stderr`: `execFileSync` returns stdout only, and one script threw on `null` after a six-minute take. Keep the raw `.webm` so post can be re-run on its own. (2) The step counter shows the step number only: a guessed total read "25/34" at the end of a complete 25-step film. (3) Find a grid row by the key the grid displays, not by the key the script created. (4) Skipped beats set a non-zero exit code: a fault film skipped its retry beats and still exited 0. Also: take the config module's named export and check the base URL before the browser opens (`goto("undefined/")`). Four new failure-mode rows; patch 0005 rebased over #303's rule 13 and rows. — MendixMau (requirements-driven back-office build, FINDINGS T-227)
- fix(project-bin): **`build-plan-status.sh` takes flags and the path in any order, and `restore-mpr.sh` takes the bare timestamp its usage line promised.** `build-plan-status.sh --json <root>` dropped `--json` and refused the path as "unknown arg" (exit 2); `--json` alone inside a project wrote no JSON and said nothing. `restore-mpr.sh 20261013-120000` resolved the name after its own `cd` into the model dir and failed with "snapshot ... is missing App.mpr"; a caller-relative path failed the same way on a two-tree checkout. Now one argument loop, a timestamp resolves under `.mpr-snapshots/`, and an unknown name exits 1 listing the newest snapshots. Fixtures `test-build-plan-status-args.sh` (4 of 6 fail on the old code) and `test-restore-mpr-arg.sh` (5 of 10 fail, both layouts) ([#309](https://github.com/MendixMau/mxcli-project-toolkit/pull/309)) — AlvinnYeo
- feat(lint): **Lint Batch 3 — TXT001 build-process words in user-visible text, TXT002 non-ISO dates in user-visible text, UI001 Data grid 2 / Atlas input layout traps.** From the 2026-10-12 UX-fix retros ([#280](https://github.com/MendixMau/mxcli-project-toolkit/issues/280), [#282](https://github.com/MendixMau/mxcli-project-toolkit/issues/282), [#276](https://github.com/MendixMau/mxcli-project-toolkit/issues/276)): leaked words reached 3 of 3 apps and non-ISO dates 2 of 3, each past a one-off glossary grep; a list view in a grid column and a width on an Atlas input each cost fix rounds. Warning severity, `_rule` finding on a missing field, an empty `strings()` under a FULL-catalog rule, or vocabulary that matches nothing; 23 cases in `tests/lint-rules/test-batch3-rules.sh` (harness gained a `strings()` mock). Field run (mxcli 0.26.0, 21-module Mendix 11.12 model): 0/0/0 over 478 user-visible strings and 271 widgets, with loosened positive controls returning 27/50/17 through the same accessors. TXT002 cannot see format strings inside expressions — that half is a blocked row. `process/lint-backlog.md` Batch 5 lists all 17 candidates from the three issues (rows 32–48) — MendixMau
- new(process): **feedback typed mid-build gets a change log in `PROJECT.md`, written before any edit, and the BRD/decision/architecture/wireframe is edited before the MDL.** Across 12 mid-build changes on real projects, 12 went straight into MDL and 0 updated a BRD, build plan or wireframe; the drift-sync `UNSYNCED` marker was never written once, and its absence is invisible, so every gate passed on silence. At the other extreme, one already-settled entity change cost ~270k tokens through two helper agents, and one screenshot-driven fix took 4 rounds because it regressed twice. New `skills/change-intake.md` (baseline, lead+ba, Stages 2–7; routing trigger "the user gives feedback or asks for a change mid-project"): one `## Change log` row per ask (`CR | Date | Source | Verbatim ask | Class | Size | Entry artifact | Status | Closed-by`), six classes, each mapped to its entry artifact (a decision is superseded by a new row, never edited; a built page's visual change is recorded as a before/after screenshot pair instead of wireframe upkeep; impl/bug need only a regression journey). Ceremony is proportional: a small change the user typed gets a one-line receipt and no question, a medium one gets one batched question at the next module gate, a large one or one that contradicts a CONFIRMED decision is asked and stopped on, and stakeholder asks wait for the user. Statuses run open → refined → agreed → applied → proven, or rejected. `bin/lib/change-log.sh` holds the one template and the parser: `init-project.sh` writes the section, `sync-project.sh` appends it once to older projects, and `gate-check.sh` prints a **warn-only** `Change log:` line plus a dashboard row (rows not yet applied, N of M; applied/proven rows with no Closed-by; unrecognised statuses). It becomes blocking only after two projects' counts match a hand count. `project-bin/exec.sh --cr CR-NN` tags the BUILD-LOG detail cell (metrics-ledger columns unchanged). Ownership contradiction fixed: the lead marks; ba-agent flushes BRDs and briefs; architect-agent flushes wireframes and `architecture/` (runbook §3b, `iterative-build-loop.md`, `agent-roles.md`, both stubs, `close-the-loop.md`). Inbox TD-04's change-loop half is promoted here, and its row is narrowed to the two unpromoted items. Fixture `tests/wave2/test-change-log.sh` (39 cases, PROJECT.md built by the real init) — MendixMau
- feat(exec): **per-project exec lock with stale takeover, opt-in `--commit-first`, a post-exec "restart needed / watch can apply this" verdict, a scoped `bin/app-restart.sh`, and `bin/test-scratch.sh` for `mxcli test` on a locked copy** ([#287](https://github.com/MendixMau/mxcli-project-toolkit/issues/287) items 3-4, [#284](https://github.com/MendixMau/mxcli-project-toolkit/issues/284), [#275](https://github.com/MendixMau/mxcli-project-toolkit/issues/275), [#289](https://github.com/MendixMau/mxcli-project-toolkit/issues/289) items 1-2, [#285](https://github.com/MendixMau/mxcli-project-toolkit/issues/285), [#278](https://github.com/MendixMau/mxcli-project-toolkit/issues/278) recipe half). In a 20-task UX-fix field run over three apps (2026-10-12), 57 of 148 `exec.sh` runs applied nothing (26 refused on uncommitted model changes, 15 gate failures, 16 mxbuild exit 1), a machine-wide `pgrep "mxcli exec"` guard blocked an exec because another project was writing, watch mode silently missed recreated microflows, grants, attributes, pages, page URLs and theme SCSS/JS (~26 restarts), and 24 implementer restart-resumes cost 41.6M tokens because only the lead could restart apps. `exec.sh` now locks per project (atomic, `<pid> <epoch> <script>`, a dead or reused pid is taken over with a note; another project never blocks), `--commit-first` commits only the `.mpr` + `mprcontents/` (refused while Studio Pro holds the model; the refusal names the flag), and every applied script ends with the watch verdict (`--watch-compat` alone). `app-restart.sh` stops only the pid `run --local` recorded for THIS project, restarts it with the same command and returns when the port serves a Mendix page and its JS bundle; no record, or a record from another project, refuses. `ui-loop.md` gains the covers / does-not-cover table and the stale-runtime symptom list (incl. the `IO_PathNotFound deployment/web/pages` rebuild crash); `agent-roles.md` lets implementers run that one helper. Fixtures: `test-exec-lock-watch.sh` (45), `test-app-restart.sh` (30), `test-test-scratch.sh` (20) — MendixMau
Expand Down
11 changes: 4 additions & 7 deletions contrib/inbox/2026-09-29-acceptance-test-strength.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Acceptance testing: what made the toolkit build's tests stronger, and its three gaps
# Acceptance testing: what made the toolkit build's tests stronger

**From:** a field comparison (mxcli + toolkit build vs a Studio Pro MCP build, same frozen spec)
**Date:** 2026-09-29
Expand All @@ -14,9 +14,6 @@ Keep (measured to matter):
escalation bug (uncommitted change) the other build never exercised.
- Fresh data per variant, not reuse of rehearsal data.

Gaps found (the other build did these better):
- Menu/permission refusal checked client-side only — add a server-side probe (expect HTTP 560
/ access denied), not "the menu item is hidden".
- Unexpected 400/422 API responses treated as informational — make them failures.
- 20/20 was stitched from three runs — require one clean-database final run that includes the
timer scenarios.
The three gaps this comparison found (server-side permission probe, unexpected 4xx as a failure,
one clean-database final run) were promoted on 2026-10-13 into `skills/testing-shape.md` §4/§7 and
`skills/test-result-audit.md` 2e (#172). The "Keep" items above are not yet promoted.
Loading
Loading