From a6b5f4614578ad71edd0c3ab7f7c699046303662 Mon Sep 17 00:00:00 2001 From: MendixMau Date: Thu, 15 Oct 2026 22:32:28 +0800 Subject: [PATCH 1/2] fix(install-manifest): name coverage-check-all.sh and ts-sync.sh as NOINSTALL; test fails on unnamed files (#381) Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 4 +++- bin/lib/install-manifest.sh | 2 +- tests/wave2/test-manifest-clean-checkout.sh | 14 ++++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100755 tests/wave2/test-manifest-clean-checkout.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e238acd..6629f014 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,9 @@ updating it became a separate chore). One line per change: Kinds: `new` · `fix` · `learn` (a skill/learning) · `process` (rules, templates, CI). Credit the person or project that surfaced the change — the credit line is the thank-you. -**Release cycle (from 2026-09-19).** New lines land under `## Unreleased`, at the top. Every few +**Release cycle (from 2026-09-19).** New lines land under `## Unreleased + +- fix(install-manifest): **a clean toolkit checkout passes its own `project-bin/` manifest self-check, so adopters no longer see the "named by NEITHER list" warning at the top of every sync.** `coverage-check-all.sh` (found by `review-module.sh` through its `_tool` lookup in the toolkit clone) and `ts-sync.sh` (UNPROVEN and SUPERSEDED per its header) join `MXTK_PROJECT_BIN_NOINSTALL` with reasons. New `tests/wave2/test-manifest-clean-checkout.sh` fails, rather than warns, when a `project-bin/` file is in neither list. — joshuamoesa (#381)`, at the top. Every few days the maintainer cuts a release with `bin/cut-release.sh`: the `## Unreleased` heading becomes `## vYYYY.MM.DD`, master is tagged `vYYYY.MM.DD`, and a fresh empty `## Unreleased` opens. So the top section is always "what changed since the last release", a project reports the release it is diff --git a/bin/lib/install-manifest.sh b/bin/lib/install-manifest.sh index e1c939d3..13a78191 100644 --- a/bin/lib/install-manifest.sh +++ b/bin/lib/install-manifest.sh @@ -126,7 +126,7 @@ MXTK_PROJECT_BIN="app-restart.sh test-scratch.sh assemble-prototype.js prototype # installed because a PROJECT runs it. report-disposition-check.sh is run by gate-check.sh out of # the toolkit clone, so a project copy would be a second copy nothing calls — which is how the # per-script lists drifted in the first place. -MXTK_PROJECT_BIN_NOINSTALL="report-disposition-check.sh" # gate-check.sh runs it from the TOOLKIT clone ($TOOLKIT_DIR/project-bin/, gate-check.sh:2149), never from a project copy — installing it would create a second copy nothing calls +MXTK_PROJECT_BIN_NOINSTALL="report-disposition-check.sh coverage-check-all.sh ts-sync.sh" # gate-check.sh runs it from the TOOLKIT clone ($TOOLKIT_DIR/project-bin/, gate-check.sh:2149), never from a project copy — installing it would create a second copy nothing calls; coverage-check-all.sh is run by review-module.sh through its _tool lookup (beside it, then the toolkit clone), so a project copy is optional and nothing calls it from bin/; ts-sync.sh is a toolkit-side transplant helper marked UNPROVEN and SUPERSEDED in its header (#381) # --- Starlark lint rules ----------------------------------------------------------------- # Copied from toolkit lint-rules/ into /.claude/lint-rules/. Two lists, because the diff --git a/tests/wave2/test-manifest-clean-checkout.sh b/tests/wave2/test-manifest-clean-checkout.sh new file mode 100755 index 00000000..48e8e8e3 --- /dev/null +++ b/tests/wave2/test-manifest-clean-checkout.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +# #381: a clean toolkit checkout must pass its own install-manifest self-check. Every file in +# project-bin/ is named by MXTK_PROJECT_BIN or MXTK_PROJECT_BIN_NOINSTALL, so the warning fires +# only when a contributor adds a file and forgets the manifest, never on every adopter's sync. +# This test FAILS (not warns) on an unnamed file. +# +# usage: test-manifest-clean-checkout.sh [toolkit-root] +set -uo pipefail +TK="${1:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}" +. "$TK/bin/lib/install-manifest.sh" 2>/dev/null || { echo "FAIL cannot source install-manifest.sh"; exit 1; } +OUT="$(_mxtk_manifest_check_bin_unnamed 2>&1)" +if [ -z "$OUT" ]; then echo " ok project-bin/ is fully named by the manifest"; echo "test-manifest-clean-checkout: 1 passed, 0 failed"; exit 0; fi +echo " FAIL project-bin/ holds files named by neither list:"; printf '%s\n' "$OUT" | sed 's/^/ /' +echo "test-manifest-clean-checkout: 0 passed, 1 failed"; exit 1 From 2ed20a3b02f2ea8975a6fd94d27f035e4901dfc5 Mon Sep 17 00:00:00 2001 From: MendixMau Date: Thu, 15 Oct 2026 23:00:05 +0800 Subject: [PATCH 2/2] docs(changelog): move the #381 line under ## Unreleased (review #399) Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6629f014..5f886f99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,9 +7,7 @@ updating it became a separate chore). One line per change: Kinds: `new` · `fix` · `learn` (a skill/learning) · `process` (rules, templates, CI). Credit the person or project that surfaced the change — the credit line is the thank-you. -**Release cycle (from 2026-09-19).** New lines land under `## Unreleased - -- fix(install-manifest): **a clean toolkit checkout passes its own `project-bin/` manifest self-check, so adopters no longer see the "named by NEITHER list" warning at the top of every sync.** `coverage-check-all.sh` (found by `review-module.sh` through its `_tool` lookup in the toolkit clone) and `ts-sync.sh` (UNPROVEN and SUPERSEDED per its header) join `MXTK_PROJECT_BIN_NOINSTALL` with reasons. New `tests/wave2/test-manifest-clean-checkout.sh` fails, rather than warns, when a `project-bin/` file is in neither list. — joshuamoesa (#381)`, at the top. Every few +**Release cycle (from 2026-09-19).** New lines land under `## Unreleased`, at the top. Every few days the maintainer cuts a release with `bin/cut-release.sh`: the `## Unreleased` heading becomes `## vYYYY.MM.DD`, master is tagged `vYYYY.MM.DD`, and a fresh empty `## Unreleased` opens. So the top section is always "what changed since the last release", a project reports the release it is @@ -21,6 +19,7 @@ Sections dated before 2026-09-19 predate the cycle and stay as they are. Named m ## Unreleased +- fix(install-manifest): **a clean toolkit checkout passes its own `project-bin/` manifest self-check, so adopters no longer see the "named by NEITHER list" warning at the top of every sync.** `coverage-check-all.sh` (found by `review-module.sh` through its `_tool` lookup in the toolkit clone) and `ts-sync.sh` (UNPROVEN and SUPERSEDED per its header) join `MXTK_PROJECT_BIN_NOINSTALL` with reasons. New `tests/wave2/test-manifest-clean-checkout.sh` fails, rather than warns, when a `project-bin/` file is in neither list. — joshuamoesa (#381) - new(mxpatch, exec): **`project-bin/mxpatch.py`, the shared patch core, and a `mxcli fix hashes` check around every `exec.sh --patch` run: the two shipped workflow patchers no longer leave a stale ContentsHash.** mxpatch finds a unit by type + name (+ module) with a byte pre-filter, finds an element by Name, gets/sets a value by key, and writes the unit and its `.mpr` ContentsHash (base64 SHA-256 of the file) in one step; dry run by default, `already applied` on a re-run, and a refusal (exit 3) when the current value is not the expected old one. `wf-set-call-captions.py` and `wf-add-path-terminators.py` now write through it, refuse drift (a caption is replaced only while it is still the stamped microflow name or the `--expect-caption` value; `--expect-paths N` for terminators), and also take the `exec.sh --patch` form (` Module.Workflow`). The index is committed before the file swap, so a kill mid-write leaves a MISMATCH that `fix hashes` reports and a re-run repairs. `mxunit_bson.py` reads BSON 0x09 (UTC datetime). `exec.sh --patch` runs `mxcli fix hashes` (v0.25.0+, probed via `fix --help`) before and after the script and restores the snapshot on any issue the baseline did not have, before mxbuild, which cannot see it. Field evidence: captured mxcli v0.25.0/v0.26.0 runs on a public model (`tests/wave2/fixtures/mxpatch/CAPTURE.txt`): master's patchers leave a MISMATCH, the ported ones verify clean; the hash routine agrees with mxcli on 67 of 67 mismatched and 302 matching units of a second model. Widget-shape copying and pluggable-widget properties wait on a captured page unit. Field run ([#390](https://github.com/MendixMau/mxcli-project-toolkit/issues/390), mxcli v0.26.0, macOS): PASS, and the patch repaired a ContentsHash MISMATCH an old-style `--patch` had left on the unit it rewrote. Fixes from it: the backup of a rewritten unit is kept outside `mprcontents/` (in `$MXPATCH_BACKUP_DIR`, which `exec.sh --patch` points into the snapshot it just took, else a 0700 `/mxpatch-bak-/`; refused when it resolves inside `mprcontents/`, through a symlink or another case spelling; named with pid and counter so two writes in one second keep both), no longer as an untracked `.mxunit.bak` that `git add mprcontents` would commit; the BUILD-LOG row carries the hash bracket (`hashes: baseline 1 mismatch (pre-existing), verify clean (1 pre-existing repaired by this patch's rewrite)`); and the baseline message says that a unit the patch rewrites gets a fresh hash, and to repair the others with `fix hashes --repair`. A baseline MISMATCH that is still reported on a unit the patch rewrote counts as new (restore, exit 1), not as pre-existing. — jopterhorst ([#294](https://github.com/MendixMau/mxcli-project-toolkit/issues/294), [#295](https://github.com/MendixMau/mxcli-project-toolkit/issues/295)) - learn(pipelines/mendix-mpr/samples): **three minimal mxcli repros from the native-module bug hunt, the files the upstream draft cites** (split from [#293](https://github.com/MendixMau/mxcli-project-toolkit/pull/293), 6/6). `fsm-template-9.24.2/native-bughunt/` holds CAPTURE.txt and D1–D3, which are written from scratch in a `Repro` module: `describe entity` printing `index ( desc);`, the native Repeater `content` slot, and no flow writable to a 9.24.2 project. They are the repros for U3, U2 and U14 in `bug-logs/pending-github-issues/2026-10-12-mxcli-0.26-round-trip-report.md`. The other 472 sample files of #293 had no citing reader, because the skills and Rehost splits state their field results inline, so none of them ships. — MendixMau, Decompose/Rehost lab runs 2026-10-12 - learn(inbox, pending-github-issues): **ten field-note drops from the Decompose/Rehost lab runs, and one not-filed draft of 53 mxcli 0.26 defects for mendixlabs/mxcli** (split from [#293](https://github.com/MendixMau/mxcli-project-toolkit/pull/293), 5/6). `contrib/inbox/2026-10-1{2,3}-*.md`: increments 1–8 of the split-a-monolith runs on a public Marketplace template (FSM 9.24.2), the native-module bug hunt, and the GenAI Showcase regeneration (0.26.0 and the 2026-10-13 nightly); each now has the template's front matter and is at most 600 words. `bug-logs/pending-github-issues/2026-10-12-mxcli-0.26-round-trip-report.md`: the U1–U53 table the inbox drops refer to, marked DRAFT — NOT FILED, to be split into one issue per defect and retested before anything is posted. No BUG numbers assigned; triage promotes. — MendixMau, Decompose/Rehost lab runs 2026-10-12/13