diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ada9afb..baf8a4e2 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(sync-project): **the "Baseline-only skills cited" warning no longer fires on the toolkit's own wiring block, and no longer sizes a section that does not exist.** The check grepped all of `CLAUDE.md` for `skills/learned-mdl-preflight.md` / `skills/query-the-model.md`, and `wire-agents.sh`'s `mxtk:wiring` block cites the first, so every sync flagged the toolkit's own text; with no "mxcli-project-toolkit Integration" heading it then printed a whole-file word count as "heading to EOF". The wiring block is now stripped before the grep, and the warning is raised only when the heading exists. `tests/wave2/test-sync-dup-heading-exit.sh` T4 flips (no heading: no warning) and gains T7-T9. — joshuamoesa (#382) - learn(workflow, rest): **the v0.20-era workflow notes are marked superseded for mxcli v0.26.0:** `WAIT FOR NOTIFICATION` takes a name, `NOTIFY WORKFLOW` needs `TARGET Module.Workflow.Element` (CE0166 / MDL-WF16 without), mxcli writes the end-of-boundary-path marker itself so a boundary terminator is no longer a hand-add (the parallel-split terminator is a separate node and unchanged), and published REST `Authentication: (basic)` works (BUG-152 item 1: 401 / 401 / 200 proven, URL includes the resource segment). Sources: a five-app lab field run (Mendix 11.15, mxcli v0.26.0) and mxcli's public `write-workflows` skill and docs. `wf-add-path-terminators.py` already takes an `.mpr` since #294 (the reported crash was the older script). — TK-019 of a five-app lab report - learn(workflow): **a "compute, then branch" pattern in `workflow-structure-rules.md`: a workflow decision reads a Boolean or enumeration on the context and cannot call a microflow, so the rule is computed by an earlier call microflow into a context attribute (TK-023).** The same paragraph names the three limits a field run hit (called microflow returns Boolean, enumeration or nothing; decision expressions on the context only; single-outcome user task holds no activities, MDL-WF02 / CE1876). The call-microflow return rule and the lone-outcome rule were already in the skill (§5, `learned-workflow-patterns.md` §6); the report's claim that an `exposed as workflow action` microflow cannot return a value was not adopted, because mxcli's own docs show one with `returns String`. — five-app lab report, TK-023 - learn(bug-ledger): **published REST answers 404, not 403, for a user without the allowed role** (TK-046, Mendix runtime behaviour; write 404 into the contract) — a five-app lab project diff --git a/bin/sync-project.sh b/bin/sync-project.sh index 1770bc32..5a8fa567 100755 --- a/bin/sync-project.sh +++ b/bin/sync-project.sh @@ -1058,17 +1058,25 @@ if [ -f "$PROJECT_DIR/CLAUDE.local.md" ]; then # can also trip it; the message below is phrased as "check whether" for that reason, not as # a flat assertion. Same rule as the ledger-row warn above: CLAUDE.md is bootstrap-project.md's # (an LLM merge), not this script's, so sync never edits it — only names the fix. - if [ -f "$PROJECT_DIR/CLAUDE.md" ] && grep -qE 'skills/(learned-mdl-preflight|query-the-model)\.md' "$PROJECT_DIR/CLAUDE.md"; then + # The toolkit's own wiring block (mxtk:wiring:start..end, written by wire-agents.sh) cites + # skills/learned-mdl-preflight.md in its item-3 sentence, so it is stripped before the grep: + # otherwise the toolkit flags its own text as the adopter's duplicate (#382). And the check + # only speaks when the "mxcli-project-toolkit Integration" heading exists: with no heading + # there is no section to name or size, and a whole-file word count described as "heading to + # EOF" pointed the adopter at text that is not theirs to edit. + _dup_from_line="" + if [ -f "$PROJECT_DIR/CLAUDE.md" ]; then + _dup_body="$(awk '/mxtk:wiring:start/{skip=1} !skip{print} /mxtk:wiring:end/{skip=0}' "$PROJECT_DIR/CLAUDE.md")" # `|| true`: no heading is the COMMON case (every CLAUDE.md mxcli init v0.25 writes cites # the skills without it). Unguarded, grep's exit 1 fails the pipeline under pipefail and # errexit ended the whole sync here, silently, before the bin/ and tests/e2e refresh — # every sync from 9a0350b (2026-09-18) to this fix. Regression: tests/wave2/test-sync-dup-heading-exit.sh. - _dup_from_line="$(grep -n 'mxcli-project-toolkit Integration' "$PROJECT_DIR/CLAUDE.md" | head -1 | cut -d: -f1 || true)" - if [ -n "$_dup_from_line" ]; then - _dup_words="$(tail -n "+$_dup_from_line" "$PROJECT_DIR/CLAUDE.md" | wc -w | tr -d ' ')" - else - _dup_words="$(wc -w < "$PROJECT_DIR/CLAUDE.md" | tr -d ' ')" + if grep -qE -- 'skills/(learned-mdl-preflight|query-the-model)\.md' <<<"$_dup_body"; then + _dup_from_line="$(printf '%s\n' "$_dup_body" | grep -n 'mxcli-project-toolkit Integration' | head -1 | cut -d: -f1 || true)" fi + fi + if [ -n "$_dup_from_line" ]; then + _dup_words="$(printf '%s\n' "$_dup_body" | tail -n "+$_dup_from_line" | wc -w | tr -d ' ')" warn "CLAUDE.md cites Baseline-only skills also covered by CLAUDE.local.md — check whether" \ "its \"mxcli-project-toolkit Integration\" section (~$_dup_words word(s), heading to" \ "EOF, not all of it necessarily routing) is a duplicated Baseline routing block." \ diff --git a/tests/wave2/test-sync-dup-heading-exit.sh b/tests/wave2/test-sync-dup-heading-exit.sh index 504c0424..e2afd663 100755 --- a/tests/wave2/test-sync-dup-heading-exit.sh +++ b/tests/wave2/test-sync-dup-heading-exit.sh @@ -47,9 +47,11 @@ printf '%s\n' "$OUT" | grep -q 'Would install: bin/exec.sh' \ printf '%s\n' "$OUT" | grep -qE 'artifact\(s\) would be updated|All copied artifacts up to date' \ && ok "T3 no heading: sync reaches its summary line" \ || bad "T3 no heading: sync reaches its summary line" -printf '%s\n' "$OUT" | grep -q 'cites Baseline-only skills' \ - && ok "T4 no heading: the duplicate-routing warning is still raised" \ - || bad "T4 no heading: the duplicate-routing warning is still raised" +if printf '%s\n' "$OUT" | grep -q 'cites Baseline-only skills'; then + bad "T4 no heading: no duplicate-routing warning (nothing to name or size, #382)" +else + ok "T4 no heading: no duplicate-routing warning (nothing to name or size, #382)" +fi # --- heading present: the case the check was written for keeps working ------------------ P2="$(mkproj withheading)" @@ -60,6 +62,24 @@ printf '%s\n' "$OUT2" | grep -qE 'section \(~[0-9]+ word' \ && ok "T6 heading: warning sizes the section" \ || bad "T6 heading: warning sizes the section" +# --- #382: a citation inside the toolkit's own wiring block is not the adopter's duplicate --- +P3="$(mkproj wiringonly)" +printf '\n\nsee skills/learned-mdl-preflight.md STOP table\n\n' >> "$P3/CLAUDE.md" +OUT3="$("$SYNC" "$P3" --dry-run 2>&1)"; RC3=$? +[ "$RC3" -eq 0 ] && ok "T7 wiring block only: sync exits 0" || bad "T7 wiring block only: sync exits 0 (got $RC3)" +if printf '%s\n' "$OUT3" | grep -q 'cites Baseline-only skills'; then + bad "T8 wiring block only: no duplicate-routing warning" +else + ok "T8 wiring block only: no duplicate-routing warning" +fi +# the same text OUTSIDE the block, under the heading, still warns +P4="$(mkproj wiringplusheading)" +printf '\n\nsee skills/learned-mdl-preflight.md\n\n\n## mxcli-project-toolkit Integration\n\nRead skills/query-the-model.md.\n' >> "$P4/CLAUDE.md" +OUT4="$("$SYNC" "$P4" --dry-run 2>&1)" +printf '%s\n' "$OUT4" | grep -qE 'section \(~[0-9]+ word' \ + && ok "T9 block + heading: warning still raised, sized from the heading" \ + || bad "T9 block + heading: warning still raised, sized from the heading" + echo "" echo "test-sync-dup-heading-exit: $PASS passed, $FAIL failed" [ "$FAIL" -eq 0 ]