PROD-1492: only halt on duplicate model mappings when a source ID is still live#194
Merged
jules-exel merged 3 commits intoJul 23, 2026
Merged
Conversation
Two related fixes so a mapping-inconsistency guard actually stops the sync instead of being swallowed and silently continuing. 1. Template validation was swallowed. The guid-level orchestrator only re-threw errors containing "Model validation failed", but the template guard throws "Page template validation failed" — so it fell through to a yellow warning and the sync kept going. Broaden the re-throw match to any "validation failed" so template (and future) guards hard-stop. 2. Duplicate model reference-name was undetected. When a source model is deleted and recreated (new ID, same referenceName), the mapping keeps two records sharing that name — one pointing at the dead source model. The content-side lookup is first-match-wins, so it can latch onto the dead record and SILENTLY skip that model's content, after which pages referencing it fail with "No content mapping". The ID-based rename guard misses this (different source IDs = duplicate name, not duplicate ID). Add ModelMapper.getDuplicateSourceReferenceNames() and a pre-push integrity gate in pushModels that throws "Model validation failed: duplicate model mapping ..." before any writes. Tests: new orchestrate-pushers test (template failure aborts before content/pages) and new model-pusher test (duplicate-name mapping throws and writes nothing). Added per-test mapping-file cleanup so seeded mappings no longer leak between model-pusher tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…still live The duplicate-reference-name gate added in #191 halted the sync on ANY mapping that had two records sharing a source referenceName. That over-fires on a model deleted OUTRIGHT: both records point at source models that no longer exist (e.g. the case-only "ChangeLog"/"Changelog" pair, source IDs 110 & 117, both absent from the pull). There is no content of that type in the push and nothing references it, so halting is a false positive that blocks the whole sync over stale mapping residue. Scope the gate to duplicates where at least one conflicting source ID is still live in the current pull. That preserves the PROD-1492 fix (dead + live record, e.g. PromoBanner 46-dead / 48-live, still hard-stops the sync) while ignoring fully-dead residue silently. Tests: model-pusher.test.ts now covers both the live-vs-dead halt and the fully-dead no-halt path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5PK
approved these changes
Jul 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Follow-up to #191 (merged). That PR added a pre-push gate in
pushModelsthat halts the sync when the mapping file contains two records sharing a sourcereferenceName— the PROD-1492 "deleted-and-recreated model" corruption. But the gate fired on any such duplicate, including a model that was deleted outright (both records point at source models that no longer exist), which is a false positive that blocks the entire sync over stale mapping residue.Real example from a
63b1dc5d-us2 → 95bfb840-us2sync: a case-onlyChangeLog(source 110 → target 18) /Changelog(source 117 → target 24) pair where both source models are gone from the pull. Nothing references them, no content of that type is in the push — yet the sync hard-stopped.Change
Scope the gate to duplicates where at least one conflicting source ID is still live in the current pull:
PromoBanner46-dead / 48-live) → still throwsModel validation failedand halts. ✅ ticket behavior preserved.ChangeLog/Changelog, both absent) → silently ignored, sync continues. ✅ no false halt.getDuplicateSourceReferenceNames(case-insensitive) is unchanged; the LeftSidebar/template validation halt from #191 is untouched.Tests
model-pusher.test.ts:Model validation failed, writes nothing.success, no halt.All model / mapper / orchestrate suites pass;
tscclean.Sync before:

Sync after by-passed deleted models with same name