Skip to content
Merged
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(script-owners): **the restatement guard now parses under macOS's default bash 3.2, so `exec.sh` no longer skips it silently** (guard added in #498). `exec.sh` runs `bash script-owners.sh check … 2>/dev/null || true`; under /bin/bash 3.2.57 the file failed to parse (an apostrophe in a comment inside `$(...)`, then `case` patterns without a leading `(`), so the call (and the ledger `record` call) printed nothing and warned nothing. Fixture `test-restatement-guard.sh` under /bin/bash 3.2.57: 16 of 58 pass before, 58 of 58 after; `bin/check-scripts.sh` now also parses every script with /bin/bash when the bash on PATH is a different one. — saingge
- fix(facts-lock): **`check` no longer reports "N BRD(s) agree with all 0 frozen fact(s)" when nothing was compared** (#519). A corpus whose BRDs carry identifiers only under keys the harvest does not read (`domainEntities[].name`, `pages[].name`) froze an empty lock, and `check` printed what reads as a pass. With 0 frozen facts, `check` now prints `PENDING facts-lock: 0 identifiers found under any known key in N BRD(s): the lock is empty and check proves nothing (keys read: ...)`, or, when identifiers exist but no lock was built, `PENDING ... run build first; check compared nothing`; `build` prints the same empty-lock line when it froze 0 facts and found no conflicts. Exit codes are unchanged (an exit-3 "nothing measured" and harvesting `name` keys are left for a separate change). Fixture: `test-facts-lock.sh` (the issue's repro: 3 fail on master; 19/19). — AlvinnYeo (#519)
- fix(journey-runner): **the RUNG 1 landing guard now waits up to its 12 s for `ui.ready`** (#536). It called `locator.isVisible({ timeout: 12000 })`, and Playwright ignores that timeout and answers at once, so a page that rendered more than 300 ms after the per-action settle (a progress bar, a microflow before the page opens, a step ending in a fixed `settleMs`) read `reached: FAIL` and every later rung of the step INVALID. It now uses `waitFor({ state: 'visible', timeout: 12000 })`, and the NOT-REACHED screenshot is taken after that wait. Only the landing guard changes; the same no-wait call in `act()` (`click`, lines 184/210/222), the named-control probe and `helpers.js`/`monkey.js`/`full-app-walkthrough.js` are left for a separate change. **Behaviour change to check in your project:** a journey whose ready selector never appears now spends 12 s per such step before it reports NOT-REACHED. Verified by inspection and a Playwright probe (hidden element shown after 2 s: `isVisible` false in 74 ms, `waitFor` true in 2.3 s); no fixture drives the runner's step loop. — AlvinnYeo (#536)
- fix(build loop, exec): **the commit guidance stages `javasource/` and `javascriptsource/`, and `exec.sh` prints a staging hint when they changed** (#540). `create java action ... as $$` writes `javasource/<module>/actions/*.java` beside the model; the skill's example (`git add App.mpr mprcontents/ mdlsource/<script>.mdl`) committed the model without the body, which builds on the machine that ran exec and not in a clone. `iterative-build-loop.md` (both `git add` examples and the sentence after the exec one, +44 words, on-demand file: baseline 73828 before and after) now names both folders and says to drop one the app lacks (git refuses the whole add on a missing pathspec). After a clean exec, `exec.sh` runs one `git status --porcelain` over the model folder's `javasource/` and `javascriptsource/` and, when either has changes, prints `Action sources changed outside the model ...: stage them with the .mpr.` with up to 5 paths; never a failure, no mxcli call, exit codes unchanged. **Behaviour change to check in your project:** `exec.sh` success output can carry that hint. Fixture: `test-bug07-08.sh` A2/A3 (A2 fails on master; 48/48). — AlvinnYeo (#540)
Expand Down
13 changes: 11 additions & 2 deletions bin/check-scripts.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,15 @@ set -uo pipefail
TOOLKIT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
PROJECT_DIR="${1:-}"

# macOS ships bash 3.2 as /bin/bash and its $(...) scanner rejects things bash 5 accepts. When
# the bash on PATH is a different one, parse with /bin/bash too — script-owners.sh shipped
# unparseable on a Mac this way. `bash -n` there catches an apostrophe in a comment inside
# $(...); it does not catch a case pattern without a leading "(" (that fails only when run).
SYS_BASH=""
if [ -x /bin/bash ] && [ "$(/bin/bash -c 'printf %s "$BASH_VERSION"' 2>/dev/null)" != "$BASH_VERSION" ]; then
SYS_BASH=/bin/bash
fi

FAIL=0
SH_OK=0; SH_N=0
JS_OK=0; JS_N=0
Expand All @@ -42,11 +51,11 @@ check_sh() { # check_sh LABEL GLOB...
for f in "$@"; do
[ -f "$f" ] || continue
n=$((n + 1)); SH_N=$((SH_N + 1))
if OUT="$(bash -n "$f" 2>&1)"; then
if OUT="$(bash -n "$f" 2>&1)" && { [ -z "$SYS_BASH" ] || OUT="$("$SYS_BASH" -n "$f" 2>&1)"; }; then
SH_OK=$((SH_OK + 1))
else
FAIL=$((FAIL + 1))
printf ' FAIL %s does not parse under this bash:\n' "$f"
printf ' FAIL %s does not parse under this bash (or /bin/bash):\n' "$f"
printf '%s\n' "$OUT" | head -3 | sed 's/^/ /'
if ! tr -d '\r' < "$f" | cmp -s - "$f"; then
printf ' (file carries CRLF line endings — see doctor.sh "Line endings" for the fix)\n'
Expand Down
10 changes: 5 additions & 5 deletions project-bin/script-owners.sh
Original file line number Diff line number Diff line change
Expand Up @@ -243,11 +243,11 @@ case "$cmd" in
[ -n "$PAIRS" ] || exit 0
MY_SUP="$(so_header "$S" supersedes)"; MY_SUPBY="$(so_header "$S" superseded-by)"
OUT="$(NL_SEEN=""; NL_DESC=0
# rc 0: O's work on doc $1 is not in the model; 1: it is (or unknown); 2: DESCRIBE cap reached.
# rc 0: the work of O on doc $1 is not in the model; 1: it is (or unknown); 2: DESCRIBE cap reached.
not_live() { # $1 = "KIND Module.Name", $2 = O
local w live rc=1
if [ "$S_RAN" = 0 ] && ! so_has_run "$ROOT" "$2"; then return 0; fi # S is new
case "$NL_SEEN" in *"|$1="*) rc="${NL_SEEN#*"|$1="}"; return "${rc%%|*}" ;; esac
case "$NL_SEEN" in (*"|$1="*) rc="${NL_SEEN#*"|$1="}"; return "${rc%%|*}" ;; esac
w="$(so_last_writer "$ROOT" "$1")"
if [ -n "$w" ] && [ -n "$S_REL" ] && { [ "$w" = "$(so_sortkey "$S_REL")" ] || so_before "$w" "$S_REL"; }; then
rc=0
Expand All @@ -263,9 +263,9 @@ case "$cmd" in
revert() { # $1 doc $2 O $3 message
local r=0; not_live "$1" "$2" || r=$?
case "$r" in
0) ;;
2) printf 'UNCHECKED\t%s\t%s\tCONFLICT (not checked: 5 DESCRIBE calls per exec) — %s\n' "$1" "$2" "$3" ;;
*) printf 'REVERT\t%s\t%s\t%s\n' "$1" "$2" "$3" ;;
(0) ;;
(2) printf 'UNCHECKED\t%s\t%s\tCONFLICT (not checked: 5 DESCRIBE calls per exec) — %s\n' "$1" "$2" "$3" ;;
(*) printf 'REVERT\t%s\t%s\t%s\n' "$1" "$2" "$3" ;;
esac
}
while IFS=' ' read -r d o; do
Expand Down
Loading