Skip to content

feat(sync-project): --only-bin installs just the named scripts (#390) - #396

Merged
MendixMau merged 4 commits into
masterfrom
feat/sync-only-bin
Oct 15, 2026
Merged

MendixMau merged 4 commits into
masterfrom
feat/sync-only-bin

Conversation

@MendixMau

@MendixMau MendixMau commented Oct 15, 2026 •

Copy link
Copy Markdown
Owner

Direct lane

What changed and why (one paragraph):
bin/sync-project.sh <project> --upgrade-bin X is not a scoped install, and nothing else was. --upgrade-bin only allows overwriting a locally modified copy of X; the full sync still runs. Field finding 1 in #390: an install step written as sync-project.sh <project> --upgrade-bin exec.sh --upgrade-bin _common.sh --upgrade-bin test-scratch.sh changed 244 tracked files, deleted one file, added about 30 and reinstalled 3 git hooks. This PR adds --only-bin <script.sh> (repeatable). It copies only the named project-bin/ scripts into <project-root>/bin/, the same bin/ on single-tree and two-tree (app/) layouts, then exits before any other sync section runs. That means no skills, CLAUDE.md, hooks, tests/e2e, routing or deletions. It decides everything before it writes anything. An unknown name, a path-like name, or a locally modified copy that --upgrade-bin <name>/all or the new --force did not accept exits 1 and leaves the project untouched. It refreshes an unedited older toolkit copy, as the full sync does, unless --no-refresh is given. It backs up an overwritten copy first and prints every file it writes, backups included. --dry-run works with it. Options that make no sense with it (--repair-intake, --adopt-routing, --pin-models, --diff-completed, --upgrade-lint-rules) are rejected. The header and --help now say plainly that --upgrade-bin runs a full sync. The "install just this file" remedy lines in app-restart.sh, test-scratch.sh, test-stack-up.sh, doctor.sh and harvest-learnings.sh now name --only-bin X --upgrade-bin X. No .md doc outside CHANGELOG described --upgrade-bin. copy_kind/TK_ROOT moved up next to past-stock.sh so the early-exit block can use them; the function is unchanged.

Impact

Row Answer
Process A new safe option: --only-bin for installing or trying just a few scripts, for example from a branch. Nothing new blocks; the default sync and --upgrade-bin behave as before.
Dependencies bin/sync-project.sh (shared by every project sync), plus message-only edits in project-bin/app-restart.sh, test-scratch.sh, test-stack-up.sh, bin/doctor.sh and bin/harvest-learnings.sh (each keeps the --upgrade-bin <name> substring its fixtures grep for). No new tools, no new artifact reads. bash 3.2 safe (no mapfile, no associative arrays).
Context cost none: no routed or always-loaded file touched (bin/render-routing.sh --check passes unchanged on head).
Behaviour n/a: scripts only.
Runtime n/a for the default sync. --only-bin is a handful of cp/cmp calls plus one git-history lookup per differing copy, which is far cheaper than the full sync it replaces for this use.

Field evidence: issue #390, finding 1. On a real Mendix 11.15 project (macOS, bash 3.2), the documented --upgrade-bin install of three scripts ran a full sync: 244 tracked files changed, 1 deleted, about 30 added, 3 git hooks reinstalled. The field tester had to revert and copy the three files by hand. --only-bin is that hand copy, with the local-modification guard and a list of what was written. It has not yet been run on a field project; the next field step that installs branch scripts should use it.

  • No client data anywhere in the diff (LEAKGUARD_ALLOW_NO_DENYLIST=1 bin/check-no-client-data.sh: clean)
  • Size cap: 6 files and 168 lines changed excluding the fixture and CHANGELOG (8 files / 334 lines including them)
  • Test tier: T1. tests/wave2/test-sync-only-bin.sh bin/sync-project.sh gives 40/40 across both layouts; against origin/master's script it gives 8/26 on the first-round cases, and against the first commit of this PR the review-round cases fail 12 of 14, so it discriminates. tests/wave2/test-bug12-sync.sh bin/sync-project.sh gives 61/61. Fixtures that grep the changed remedy lines (test-property-sets, test-harvest-learnings, test-app-restart, test-test-scratch) were checked by inspection (T0): their substrings are still present.
  • New/changed instrument: both layouts covered by the fixture (single-tree, and .mpr under app/). Platform: only cp/cmp/chmod/date, no mac-only tools, and bin/check-portability.sh is clean. There is no golden capture because no tool output is parsed.
  • CHANGELOG.md line added under Unreleased, credited "field run, issue Field runs 2026-10-15: #379 PASS, #384 PASS (sync --upgrade-bin not scoped; copy 87-134 s), #374 PASS (.bak in mprcontents) #390"
  • bin/check-scripts.sh, bin/check-pr-discipline.sh origin/master and bin/render-routing.sh --check all clean

Fixture coverage (tests/wave2/test-sync-only-bin.sh, per layout):

  • --only-bin restore-mpr.sh changes git status by exactly ?? bin/restore-mpr.sh. The scratch project is committed, with two bin scripts missing and the hooks removed, so a full sync would have work to do.
  • Hooks stay absent, the skills trees (.claude/skills, .ai-context/skills) are byte-identical, and so is every other file.
  • Control: a full --upgrade-bin restore-mpr.sh sync of the same project installs other scripts and the hooks.
  • An unknown script, even next to a valid one, exits non-zero and writes nothing. So does a path-like name.
  • A locally modified copy is refused with nothing written. --upgrade-bin <name> upgrades it and writes a backup, and only those two files change. --force overwrites too.
  • Refresh hold (review round): an older exec.sh the toolkit really shipped is refreshed on a clean _common.sh but refused, with the full sync's message, on a hand-edited one. --dry-run of the upgrade names the backup and writes nothing, and --upgrade-bin exec.sh lifts the hold.
  • A script outside the install manifest (report-disposition-check.sh, NOINSTALL) is refused.
  • --only-bin '*' run from a directory holding restore-mpr.sh/snapshot-mpr.sh installs nothing.
  • --only-bin '' is a usage error.

🤖 Generated with Claude Code

https://claude.ai/code/session_01VJgWP5vEoAsNsJYqCDMGNw


Generated by Claude Code

--upgrade-bin only lifts the overwrite refusal for a modified copy; the full
sync still runs. A field run used it as "install just these scripts" and got
244 changed tracked files, a deletion, ~30 additions and reinstalled hooks.

--only-bin X [--only-bin Y] copies only project-bin/X into <project>/bin/,
decides everything before writing (unknown/path-like name or an unaccepted
local modification exits 1, project untouched), backs up an overwritten copy
(--upgrade-bin X or --force), prints every file written, and exits before
any other sync section runs. Docs and remedy lines now say --upgrade-bin is
a full sync and point scoped installs at --only-bin.

Fixture tests/wave2/test-sync-only-bin.sh: 26/26 on single- and two-tree.
test-bug12-sync.sh: 61/61.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VJgWP5vEoAsNsJYqCDMGNw
Review fixes for #396:
- an unedited older copy is not refreshed on top of a hand-edited
  bin/_common.sh (the full sync's hold, same message) unless --upgrade-bin
  names it / all, or --force
- names are validated against MXTK_PROJECT_BIN; NOINSTALL files such as
  report-disposition-check.sh are refused
- set -f around the --only-bin name and plan loops: '*' is never globbed
- --only-bin '' (or a value with spaces) is a usage error
- the dry-run line for an upgrade says a backup would be written

Fixture test-sync-only-bin.sh: 40/40 (O6-O9 added, both layouts; the
previous commit fails 12 of them). test-bug12-sync.sh: 61/61.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VJgWP5vEoAsNsJYqCDMGNw
@MendixMau
MendixMau merged commit 1ea7fac into master Oct 15, 2026
2 checks passed
MendixMau pushed a commit that referenced this pull request Oct 15, 2026
Brings in #396 (sync-project.sh --only-bin). No conflicts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VJgWP5vEoAsNsJYqCDMGNw
MendixMau pushed a commit that referenced this pull request Oct 15, 2026
exec.sh and test-scratch.sh told users to run sync-project.sh with
--upgrade-bin _common.sh alone, which runs a full sync. They now give
--only-bin _common.sh --upgrade-bin _common.sh, matching test-scratch.sh's
mxtest guard on master. app-restart.sh is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VJgWP5vEoAsNsJYqCDMGNw
@MendixMau
MendixMau deleted the feat/sync-only-bin branch October 15, 2026 10:45
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.

2 participants