Skip to content

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

Merged
angeloashmore merged 17 commits into
mainfrom
aa/deep-sort-canonicalize
Aug 14, 2026
Merged

fix: pull writes canonical model files and detects changes reliably#243
angeloashmore merged 17 commits into
mainfrom
aa/deep-sort-canonicalize

Conversation

@angeloashmore

@angeloashmoreangeloashmore commented Jul 29, 2026

Copy link
Copy Markdown
Member

Resolves:

Description

Model comparison now sorts JSON keys at every depth before it compares. Field and tab order stays the same. This corrects three faults:

1. pull rewrote files that had no changes

  • Setup: Your model files came from an earlier prismic pull. The API returns nested keys (inside a field's config, for example) in a different order.
  • Before: The comparison sorted only the top-level keys. Pull saw a change and rewrote the files. git diff showed only key-order movement.
  • After: Pull prints "Already up to date." and does not touch the files.

2. pull did not rewrite files with a non-canonical key order

  • Setup: Slice Machine wrote your model files. Its key order is different from the format that the CLI writes.
  • Before: The comparison sorted the keys on both sides. Pull saw no difference and kept the old order. A later content change then mixed key-order noise into its diff.
  • After: Pull rewrites these files one time, in the canonical format. The next pull prints "Already up to date."

3. sync --watch reported changes that did not exist

  • Setup: A poll returns the same models with a different key order.
  • Before: The loop generated types and printed "Changes detected in " with an empty list.
  • After: Sync hashes the canonical models. It generates types and reports changes only on the initial sync or when a model changed.

push and status continue to ignore key order. 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.
  4. Run prismic sync --watch. The command does not report changes when the remote models do not change.

🤖 Generated with Claude Code


Note

Medium Risk
Touches core model diffing for pull, push, status, and sync; incorrect canonicalization could hide real model changes or skip needed type generation, but behavior is heavily covered by new integration tests.

Overview
Model comparison and on-disk format now treat nested JSON key order as insignificant while preserving field/tab order and slice-zone choice order. canonicalizeCustomType / canonicalizeSlice recurse through configs (Groups, Slices zones, legacy Slice choices) and sortKeys walks arrays and nested objects.

pull compares remote models to already-canonical local files (canonicalize(remote) vs local), so a first pull normalizes Slice Machine–style key order and repeat pulls report “Already up to date.” without noisy rewrites.

sync --watch hashes canonicalized remote payloads, uses the same equality for diffs, runs generateTypes only on initial sync or when models actually change, and logs which resource types changed (e.g. slices only) instead of empty “Changes detected” spam.

Tests cover canonical pull idempotency, status/push staying quiet on key reorder, and sync reporting slice-only updates.

Reviewed by Cursor Bugbot for commit 6f8185e. 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.

angeloashmoreand 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>
@angeloashmoreangeloashmore changed the title fix: canonicalize nested model config objectsfix: pull writes canonical model files and detects changes reliablyJul 30, 2026
angeloashmoreand 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
Comment threadsrc/commands/sync.ts
The watch loop hashed the raw remote JSON. A change in key order
flipped the hash without a real model change. The loop then ran
generateTypes() and logged "Changes detected in" with no suffix.
Hash the canonicalized models instead. Run generateTypes() and log
changes only on the initial sync or when there are operations.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@cursorcursorBot 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 d72140d. Configure here.

Comment threadsrc/commands/sync.ts

@lihbrlihbr left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM but I think there's an issue to check with select fields, see bellow :)

Comment threadsrc/lib/prismic/models.ts
Replace a Text field in the slice with a Select field. The options are
not in alphabetical order. The test makes sure that pull sorts the
config keys but keeps the option order.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@angeloashmore
angeloashmore merged commit d5ab9bd into mainAug 14, 2026
15 of 16 checks passed
@angeloashmore
angeloashmore deleted the aa/deep-sort-canonicalize branch August 14, 2026 21:44
@github-actionsgithub-actionsBot mentioned this pull request Aug 14, 2026
Sign up for freeto 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

@angeloashmore@lihbr