Skip to content

fix(scripts): --check reports real divergence instead of calling all 46 components "modified" - #3049

Merged
os-zhuang merged 1 commit into
mainfrom
claude/shadcn-check-divergence
Jul 30, 2026
Merged

fix(scripts): --check reports real divergence instead of calling all 46 components "modified"#3049
os-zhuang merged 1 commit into
mainfrom
claude/shadcn-check-divergence

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

--check was structurally incapable of telling you anything. The heuristic:

const isDifferent = lineDiff > 10 || localContent.includes('ObjectUI') || localContent.includes('data-slot');

Every synced file carries the ObjectUI header this script prepends, so the second clause was true for all 46 tracked components. --check reported the entire set as "modified", every run. That is the same as reporting nothing.

Using the primitive #3035 already built

localOnlyLines is directional — lines in the first argument the second lacks. Calling it both ways answers the two questions that actually decide whether to sync:

  • what would a sync destroy?localOnlyLines(local, upstream)
  • what would it gain?localOnlyLines(upstream, local)

That replaces the heuristic and splits the old "modified" bucket into the two states that need different actions:

meaning action
↑ outdated upstream moved, no local edits safe to sync
⚠ modified local edits present --update refuses

Because --check and the write guard now call the same function, the counts --check shows are exactly the counts that will stop a write.

What it says about this repo right now

✓ Identical: 29    ↑ Outdated: 0    ⚠ Modified: 17    ● Custom: 2

Zero outdated is the headline. Every component where upstream has moved also carries local edits — so there is currently no component --update-all could touch without deleting something. It has no safe work to do at all. That was completely invisible under the old output.

The summary also names the components per bucket with their counts, so triage doesn't need 46 --diff runs:

These carry local edits a sync would delete:
  badge(4), calendar(7), chart(11), command(35), context-menu(2), dropdown-menu(2),
  form(1), hover-card(1), menubar(2), popover(1), select(32), sheet(4), sidebar(24),
  slider(4), sonner(2), table(17), tooltip(1)

Verification

Against the live registry:

No changeset — tooling only.

🤖 Generated with Claude Code

…46 components "modified"

The heuristic was `lineDiff > 10 || localContent.includes('ObjectUI') ||
localContent.includes('data-slot')`. Every synced file carries the
ObjectUI header this script prepends, so the second clause was true for
all 46 of them: `--check` reported the entire tracked set as "modified",
every time, which is the same as reporting nothing.

#3035 added `localOnlyLines` for the pre-write guard. It is directional —
lines in the first argument the second lacks — so calling it both ways
answers the two questions that actually decide whether to sync: what
would a sync DESTROY, and what would it GAIN. That replaces the
heuristic, and splits the old "modified" bucket in two:

  ↑ outdated  upstream moved, no local edits      → safe to sync
  ⚠ modified  local edits present                 → --update refuses

Each line now carries counts, and the summary names the components in
each bucket so the next step is obvious without running --diff 46 times.

What it says about this repo right now:

  ✓ Identical: 29    ↑ Outdated: 0    ⚠ Modified: 17    ● Custom: 2

Zero outdated is the headline. Every component where upstream has moved
also carries local edits, so there is currently no component
`--update-all` could touch without deleting something — it has no safe
work to do at all. That was invisible before.

The per-component counts line up with the guard that enforces them
(`command` 35, `select` 32, `sidebar` 24, `table` 17 …), because both
sides call the same function.

`--check` stays exit 0: it is a status report, and 17 locally-modified
components is the steady state here, not a failure.

Verified against the live registry. The `outdated` bucket is the one real
traffic never exercises, so it was tested by deleting a line from an
identical component (`separator`): it flips to `↑ … 1 upstream line(s) to
pick up — safe to sync` and the summary offers the exact --update
command. Restored after. `--list`, `--diff`, `--update` and both #3033 /
#3035 guards regression-checked; no component file changes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 30, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectui Ignored Ignored Jul 30, 2026 1:54pm

Request Review

@os-zhuang
os-zhuang merged commit d2551ba into main Jul 30, 2026
15 checks passed
@os-zhuang
os-zhuang deleted the claude/shadcn-check-divergence branch July 30, 2026 14:00
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.

1 participant