Skip to content

fix(sync): sync-project.sh no longer exits 1 silently before its bin/ refresh - #231

Closed
MendixMau wants to merge 2 commits into
masterfrom
fix/sync-project-dup-heading-exit
Closed

MendixMau wants to merge 2 commits into
masterfrom
fix/sync-project-dup-heading-exit

Conversation

@MendixMau

Copy link
Copy Markdown
Owner

Fixes #227.

Direct lane

What changed and why (one paragraph):
sync-project.sh runs under set -euo pipefail. Its CLAUDE.md duplicate-routing check (section 3) found the "mxcli-project-toolkit Integration" heading with an unguarded grep -n … | head -1 | cut -d: -f1 inside a command substitution. A CLAUDE.md that cites skills/query-the-model.md or skills/learned-mdl-preflight.md without that heading is every CLAUDE.md that mxcli init v0.25 writes. On such a file, grep exits 1, pipefail makes that the pipeline's status, and errexit ends the whole sync with no message. Nothing after it ran: the crash-net bin/ refresh (#224), the tests/e2e/ install, the lint-rule restore, the script smoke test or the summary. The bug came in with 9a0350b (2026-09-18).

The change:

  • Append || true inside that substitution. The existing -n test already handles the empty result, and the warning still fires.
  • Give ledger_row_prefix the same guard. Its two callers only reach it after a matching grep, so it cannot fail today, but it was the only other unguarded grep pipeline whose status could reach errexit.

I checked the other greps in the script. They are in conditions, grep -q, or already || true.

Field evidence:
Three consuming projects (TramiusECI, TramiusSCR, TramiusSVC) on toolkit 69b223c, 2026-10-07:

  • Before the fix, the dry run's last line was Would rewrite: CLAUDE.md Communication Style …, then exit 1. bash -x ended at + _dup_from_line=.
  • With the guard, the dry run exits 0. It lists 7 (SVC) and 8 (ECI) Would refresh: bin/... lines that had been skipped silently, and the real run applied exactly those.

Reproduced on a fresh init-project.sh scaffold for this PR. The output is quoted in the test tier below.

  • No client data anywhere in the diff (bin/check-no-client-data.sh with the local denylist: clean, 743 files)
  • Size cap: 3 files, about 80 lines including the fixture and the CHANGELOG
  • Test tier: T1 + T2.
    • New fixture tests/wave2/test-sync-dup-heading-exit.sh, which builds its projects with the real init-project.sh.
      • On this branch: 6 passed, 0 failed.
      • On the pre-fix script (git show HEAD~1:bin/sync-project.sh): 2 passed, 4 failed (T1 exit 1, T2 no bin/ step, T3 no summary, T4 no warning).
      • The two cases with the heading present pass both ways.
    • Existing sync fixtures re-run on this branch:
      • test-sync-past-stock.sh: 22 passed, 0 failed.
      • test-bug12-sync.sh: 54 passed, 6 failed on this branch, against 47 passed, 13 failed on unmodified master (69b223c, same machine). The 7 it fixes are the existing bin/ crash-net assertions: missing script installed, exec bit repaired, drift reported, --upgrade-bin, backup, --dry-run reporting, and --strict exit 3. So this fixture already caught the bug on master.
      • The 6 that remain fail on master too, and are not touched here: pristine project written to, false alarm on a pristine project, intake rewritten unasked, second sync rewrote, and duplicated/pointer-only CLAUDE.md "sync WROTE". They come from the Rewrote: CLAUDE.md Communication Style rewrite on a fresh v0.25 scaffold, and from install-manifest.sh warning about coverage-check-all.sh and ts-sync.sh being in neither list.
    • bash -n clean, and bin/check-pr-discipline.sh clean.
  • Instrument: no parser change; layout-independent (the fixture uses the project root's CLAUDE.md); bash 3.2-safe
  • CHANGELOG.md line appended, credited

Not changed here, but worth noting: the warning text still says "its 'mxcli-project-toolkit Integration' section (~N words, heading to EOF)" when there is no such heading. In that case N is the whole file's word count.

Also seen on master, not in this PR: CHANGELOG.md lines 20 and 27 are leftover merge-conflict residue ( perf/faster-ui-loop, master).

🤖 Generated with Claude Code

https://claude.ai/code/session_01MpdPDrT1dsCR54JrgWmNso

… refresh

The CLAUDE.md duplicate-routing check looked up the "mxcli-project-toolkit
Integration" heading with an unguarded grep | head | cut under
set -euo pipefail. A CLAUDE.md that cites query-the-model.md or
learned-mdl-preflight.md without that heading (every mxcli init v0.25
CLAUDE.md) made grep exit 1, and errexit ended the whole sync there:
no bin/ crash-net refresh, no tests/e2e install, no lint-rule restore,
no message. Introduced by 9a0350b (2026-09-18).

Guard it with || true, and ledger_row_prefix too. New fixture
tests/wave2/test-sync-dup-heading-exit.sh: 6/6 on this script, 4 of 6
fail on the pre-fix one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MpdPDrT1dsCR54JrgWmNso
… fixture

The fixture header named consuming projects by client name; the public
toolkit cites field runs without naming clients.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VJgWP5vEoAsNsJYqCDMGNw
MendixMau added a commit that referenced this pull request Oct 8, 2026
Squash of integration/2026-10-08, which merges:

- #225 perf(ui-loop): test-stack-up.sh recognises a live mxcli run --local
- #231 fix(sync): sync-project.sh no longer exits 1 silently before its bin/ refresh
- #242 fix(init): local by default, no Dev Container
- #243 docs(lint): process/lint-backlog.md, the lint rollout plan
- #247 new(lint): the lint gate keeps a ledger
- #249 learn(test): skills/e2e-locators-that-lie.md
- #250 learn(skills): unhappy-path-testing.md
- #251 fix(testing-shape): mxcli test --local shares the deploy directory (#230)
- #252 fix(obligations): LOOK staleness reads the newest VALID AT stamp (#155)
- #253 docs(lint): quality-source review, Batch 4 backlog rows and skill additions
- #254 fix(lint): CONV020 works out of the box, page navigation counts as feedback (#229, #245)
- #255 fix(e2e): journey-runner rung 2 runs for a negative-only span claim (#150)
- #256 fix(gates): Stage 6 Surface, source-sufficiency title, ${JOURNEY_DIR} manifest token (#233, #234, #235)

Verified on the branch: tests/run-tests.sh 33/0, tests/test-lint-delivery.sh ALL GREEN, tests/wave2 73/75 (two environmental), render-routing --check, check-scripts, check-portability, leak guard, check-no-private-citations, check-pr-discipline all clean; scaffold smoke run without crashes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VJgWP5vEoAsNsJYqCDMGNw
@MendixMau

Copy link
Copy Markdown
Owner Author

Merged into master via integration PR #258 (squash 9dd9be4), on the maintainer's approval. Closing this PR; its branch is part of that squash.


Generated by Claude Code

@MendixMau MendixMau closed this Oct 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug] sync-project.sh exits 1 silently before the bin/ and tests/e2e refresh when CLAUDE.md cites a Baseline skill without the Integration heading

2 participants