diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d8199e7..895699ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ Sections dated before 2026-09-19 predate the cycle and stay as they are. Named m ## Unreleased +- fix(verify-module): the graph, coverage and journeys rung budgets are variables (`VM_TMO_GRAPH`, `VM_TMO_COVERAGE`, `VM_TMO_JOURNEYS`; defaults unchanged at 300/300/900, like the existing `VM_TMO_CONFORMANCE`), so a large build plan or a loaded machine can raise the 300 s that reported a clean coverage run as a timeout (TK-008) — five-app lab project (Mendix 11.15, mxcli v0.26.0) - fix(app-restart): mask the value of any `Name=value` whose name holds password/secret/token/key (e.g. `--constant Module.XPassword=v`), not only values after secret-named flags; the printed `start:` line leaked them (TK-003) — five-app lab project (Mendix 11.15, mxcli v0.26.0) - learn(bug-logs): **six BUG-DRAFT entries from a five-app lab project (mxcli v0.26.0, Mendix 11.15)**: `check` expression gaps (formatDecimal, Decimal toString, raw backslash in replaceAll), declare/retrieve partial checks, microflow splice and alter variable scope, create without commit, Data grid 2 write defects, describe round-trip and DateTime localization. Each gives the workaround; none is filed upstream yet, upstream issue numbers named where they exist (#580, #1489, #1111, #891). Read on demand through `bin/bug-lookup.sh`. — MendixMau, five-app lab report TK-027 to TK-036 - 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)) diff --git a/project-bin/verify-module.sh b/project-bin/verify-module.sh index fc4681aa..42a9126b 100755 --- a/project-bin/verify-module.sh +++ b/project-bin/verify-module.sh @@ -434,6 +434,8 @@ fi # These three share no state and touch no app, so they always run in parallel — unlike the # runtime instruments in §2 there is nothing here to race on and no login session to spend, so # this needs no opt-in flag. +# Rung budgets in seconds, overridable for big plans or loaded machines (TK-008): +# VM_TMO_CONFORMANCE (1200) VM_TMO_GRAPH (300) VM_TMO_COVERAGE (300) VM_TMO_JOURNEYS (900) if [ -x "$(_tool conformance-check.sh)" ]; then run_launch "conformance (ledger claims vs live model)" "$OUTDIR/10-conformance.log" gate "${VM_TMO_CONFORMANCE:-1200}" -- \ "$(_tool conformance-check.sh)" --module "$MODULE" @@ -442,7 +444,7 @@ else fi if [ -x "$(_tool graph-sweep.sh)" ]; then - run_launch "graph sweep (orphans + wiring shape)" "$OUTDIR/11-graph.log" gate 300 -- \ + run_launch "graph sweep (orphans + wiring shape)" "$OUTDIR/11-graph.log" gate "${VM_TMO_GRAPH:-300}" -- \ "$(_tool graph-sweep.sh)" --module "$MODULE" else fault "graph sweep (orphans + wiring shape)" "bin/graph-sweep.sh not installed" @@ -496,12 +498,12 @@ else # 3 and 4 are not passes and not faults; they are graded absences, and the rung says which. PREFLIGHT="$(_tool coverage-preflight.sh)" if [ -n "$PREFLIGHT" ] && [ -x "$PREFLIGHT" ]; then - run_launch "coverage (BRD leaves: UNCLAIMED/PHANTOM/DOUBLE)" "$OUTDIR/12-coverage.log" gate 300 -- \ + run_launch "coverage (BRD leaves: UNCLAIMED/PHANTOM/DOUBLE)" "$OUTDIR/12-coverage.log" gate "${VM_TMO_COVERAGE:-300}" -- \ "$PREFLIGHT" --summary ${MODULE:+--module "$MODULE"} elif [ -f "$LEDGER" ] && [ -n "$BRD" ]; then # Preflight absent (an older wired project that has not synced). Fall back to the engine # directly — level 1 only, which is what this rung did before the grading layer existed. - run_launch "coverage (BRD leaves: UNCLAIMED/PHANTOM/DOUBLE)" "$OUTDIR/12-coverage.log" gate 300 -- \ + run_launch "coverage (BRD leaves: UNCLAIMED/PHANTOM/DOUBLE)" "$OUTDIR/12-coverage.log" gate "${VM_TMO_COVERAGE:-300}" -- \ "$COVERAGE_CHECK" --summary "$BRD" "$LEDGER" else fault "coverage (BRD leaves)" \ @@ -576,12 +578,12 @@ else fault "journeys" "no journey runner at ${JOURNEY_RUNNER#$ROOT/}" \ "Set JOURNEY_RUNNER, or see the journey-proof.md skill for the harness this expects." elif [ -f "$JOURNEY" ]; then - _exec "journeys (UI + ordered spans + data effects)" "$OUTDIR/20-journeys.log" gate 900 -- \ + _exec "journeys (UI + ordered spans + data effects)" "$OUTDIR/20-journeys.log" gate "${VM_TMO_JOURNEYS:-900}" -- \ node "$JOURNEY_RUNNER" "$JOURNEY" # Non-vacuity: a journey that cannot fail is not evidence. Skipped under --quick because it # re-walks every step. [ "$QUICK" -eq 1 ] || _exec "journeys (positive control — MUST detect a broken precondition)" \ - "$OUTDIR/21-journeys-control.log" gate 900 -- \ + "$OUTDIR/21-journeys-control.log" gate "${VM_TMO_JOURNEYS:-900}" -- \ node "$JOURNEY_RUNNER" "$JOURNEY" --positive-control else fault "journeys" "no ${JOURNEY#$ROOT/}" \