Skip to content

fix: pull writes canonical model files and detects changes reliably - #243

Open
angeloashmore wants to merge 15 commits into
mainfrom
aa/deep-sort-canonicalize
Open

fix: pull writes canonical model files and detects changes reliably#243
angeloashmore wants to merge 15 commits into
mainfrom
aa/deep-sort-canonicalize

Conversation

@angeloashmore

@angeloashmore angeloashmore commented Jul 29, 2026

Copy link
Copy Markdown
Member

Resolves:

Description

prismic pull rewrote model files that had no changes. It also did not rewrite files whose key order was different from the format that it writes.

This PR corrects both faults. Model comparison now sorts keys at every depth before it compares. Field order stays the same. Pull rewrites local files that have a non-canonical key order. prismic sync uses the same comparison as pull. push and status continue to ignore key order. As a result, they push nothing and report nothing when only the key order is different.

Checklist

  • A comprehensive Linear ticket, providing sufficient context and details to facilitate the review of the PR, is linked to the PR.
  • If my changes require tests, I added them.
  • If my changes affect backward compatibility, it has been discussed.
  • If my changes require an update to the CONTRIBUTING.md guide, I updated it.

Preview

How to QA 1

  1. Open a project with committed model files that Slice Machine wrote.
  2. Run prismic pull. The command rewrites the files.
  3. Run prismic pull again. The command prints "Already up to date." and leaves no dirty files.

🤖 Generated with Claude Code


Note

Medium Risk
Changes core model diffing and canonicalization used by pull, sync, and disk writes—incorrect equality could cause missed updates or unnecessary rewrites, but scope is CLI sync logic with new integration tests.

Overview
Fixes pull rewriting model files on every run and missing non-canonical key order on disk. Comparison now canonicalizes the remote model and compares it to the local JSON (as read from files), so pull only updates when content differs and rewrites locals into the canonical on-disk shape. prismic sync uses the same equality rules for slices and custom types.

canonicalizeCustomType / canonicalizeSlice are tightened: sortKeys recurses through nested objects and arrays; nested Group fields and Slices zone choices (including legacy Slice non-repeat / repeat) are canonicalized explicitly without treating slice choice order as sortable metadata.

Tests cover a forced pull that asserts sorted key layout (groups, thumbnails, legacy slice choices), a second pull reporting up to date, status/push staying quiet when only key order differs, and sync reporting slice-only changes.

Reviewed by Cursor Bugbot for commit d592dae. Bugbot is set up for automated code reviews on this repo. Configure here.

Footnotes

  1. Please use these labels when submitting a review:
    ❓ #ask: Ask a question.
    💡 #idea: Suggest an idea.
    ⚠️ #issue: Strongly suggest a change.
    🎉 #nice: Share a compliment.

angeloashmore and others added 6 commits July 29, 2026 23:07
Model canonicalization sorted keys only one level deep, so structurally
identical models with reordered keys inside nested config objects (e.g.
an Image field's constraint) compared as different, causing pull to
rewrite unchanged files.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@angeloashmore angeloashmore changed the title fix: canonicalize nested model config objects fix: pull writes canonical model files and detects changes reliably Jul 30, 2026
angeloashmore and others added 9 commits July 30, 2026 02:53
Sync compared raw remote JSON against canonical local files, so any
remote change re-synced every model whose key order differed. Sync now
uses pull's comparison: the remote model's canonical form against the
local file as parsed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Pull now has a test that pulled files keep field order, a second pull
changes nothing, and non-canonical files (types and slices) are
rewritten in canonical form. The status reorder test also covers a
slice and checks that push writes nothing. The scramble helper moves to
test/it.ts and handles slice field maps.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Deep key sorting also sorted a Slices field's choices, which is the slice
order shown in the editor, and the field maps inside legacy slices.
Rebuild both from the unsorted input, like group fields.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Fixtures already hold their keys in a non-canonical order, so writing
them to disk gives the same coverage as the scramble helper without
restating which maps are position-significant. Cover a slice zone and a
legacy slice too.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The pulled file only proved that field order survives. Assert the sorted
key order of the model, a field, a thumbnail, a slice, and a variation,
and add a second tab and thumbnail so tab and array order are covered.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Write the unsorted fixture locally before the pull so one run covers
both the rewrite and the canonical output. Compare the pulled models to
the fixture for content, then assert key order at each kind of object,
including the slice zone and a legacy slice.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Write the unsorted fixture locally instead of pulling first, so status
and push run against a non-canonical file in two CLI runs. Move the
Choices type next to the function that uses it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@angeloashmore
angeloashmore marked this pull request as ready for review August 7, 2026 00:06

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit d592dae. Configure here.

Comment thread src/commands/sync.ts
const customTypeOps = diffArrays(remoteCustomTypes, localCustomTypeModels, {
getKey: (m) => m.id,
equals: (remote, local) =>
JSON.stringify(canonicalizeCustomType(remote)) === JSON.stringify(local),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sync spurious change notifications

Medium Severity

prismic sync now treats models as unchanged when only remote JSON key order differs, but the watch loop still keys off a raw JSON.stringify hash. When that hash flips with no insert/update/delete work, it still runs generateTypes() and logs Changes detected in with an empty suffix.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit d592dae. Configure here.

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