320b200ac8
The existing name-level contract (packages/git-sync schema-editor-ext-contract) only compares node/mark TYPE NAMES, so a new attribute added to an existing node upstream slips through and is silently dropped on every git-sync round trip -- a repeatedly-hit data-loss class (image caption #221, paragraph align #10). This closes the attribute gap by comparing the RESOLVED ProseMirror Schema objects (getSchema has already merged all addGlobalAttributes spreads into concrete per-node attrs) of the server's canonical tiptapExtensions vs the git-sync mirror, asserting equal attribute-key sets per shared node/mark modulo a committed, self-checking allowlist of the 6 understood divergences. A forgotten attribute now fails CI loudly instead of losing data. Comparing resolved schemas (not raw extension configs) is what makes this stable rather than the fragile config-shape compare the name-level test deferred. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>