fix(storyboards): format_id / signal_ids entity-id drift cluster (adcp#2763)#2788
Merged
Conversation
…dcp#2763) Second cluster follow-up to the schema lint from #2768. Two parts. Lint improvement. `placeholderFor` now recursively synthesizes shape-valid object placeholders for substitutions that land at object-typed schema locations — including oneOf/anyOf discriminated unions. Before this, a substitution like `$context.first_signal_id` landing at a `oneOf` of object variants produced `{}`, which ajv rejected against every branch's `required`. At runtime the substitution resolves to a concrete object captured from a prior step's response, so the lint should treat it as shape-valid. Five false positives across `format_ids`, `format_id`, and `signal_ids` now pass automatically. Fixture fix. `specialisms/creative-template/index.yaml#build/build_multi_format` was missing the required `format_id` on `creative_manifest`. Added `{ agent_url, id }` matching the canonical `core/format-id.json` shape. Allowlist shrinks 35 → 29. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code reviewer on PR #2788 flagged that the new `placeholderFor` / `synthesizeObject` / `firstObjectBranch` code path had only end-to-end coverage via the allowlist shrink. Adds a direct unit test asserting: - plain `type: object` with required fields produces a populated object - discriminated `oneOf` picks the first object branch and honors the const discriminator Keeps the next refactorer honest without having to reason about the whole allowlist. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 tasks
bokelley
added a commit
that referenced
this pull request
Apr 22, 2026
…63) (#2798) Third cluster-bundle follow-up to the schema lint landed in #2768, #2781, #2788. Allowlist shrinks 29 → 13. Lint change: isNegativeStep now treats `expect_error: true` as a canonical negative-step marker alongside the existing error_code / http_status_in heuristics. That's the widely-used convention in the suite (20+ sites) and lets reversed_dates and other deliberate error fixtures pass without per-fixture opt-ins. Fixture changes across 14 files. Main themes: - Shape completion (missing required fields): account on state-machine, reason on si_terminate_session, query/uses on get_rights_catalog, external_id on audience-sync add[] entries, event_time on log_event / log_events, event_source_id on sales-social event_logging, package_id on sales-non-guaranteed update_media_buy (with upstream capture), request_type/creative_manifest/assets on preview_display and preview_synced, creatives[] padding on reassign_creative. - Shape corrections: total_budget bare number → { amount, currency } object on two accept_proposal fixtures; flat brand/operator wrapped in accounts[{...}] on deterministic sync_accounts_for_state. - additionalProperty removal: accounts[].brand.name on sales-catalog- driven sync_accounts. - Explicit negative-test opt-in on error-compliance missing_fields (accepts either response or error — doesn't use expect_error). 13 entries remain, all blocked on WG decisions in upstream issues #2774-#2776 or the sales-social/sync_dpa_creative cluster (separate PR). Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced Apr 22, 2026
Merged
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
Second cluster follow-up to the schema lint from #2768. Two-part fix for the entity-id-as-object cluster.
Lint improvement
placeholderFornow recursively synthesizes shape-valid object placeholders for substitutions that land at object-typed schema locations — including `oneOf`/`anyOf` discriminated unions. Before this, a substitution like `$context.first_signal_id` landing at a oneOf of object variants produced `{}`, and ajv rejected it against every branch's `required`. At runtime the substitution resolves to a concrete object captured from a prior step's response, so the lint should treat it as shape-valid. This resolves 5 false positives across `format_ids`, `format_id`, and `signal_ids` automatically:Fixture fix
`specialisms/creative-template/index.yaml#build/build_multi_format` was missing the required `format_id` on `creative_manifest`. The schema at `core/creative-manifest.json` lists `format_id` and `assets` as required. Added `{ agent_url, id }` matching the canonical `core/format-id.json` shape.
Ratchet
Allowlist shrinks 35 → 29. Six cluster entries drop deterministically.
Test plan
npm run test:storyboard-sample-request-schema— passes (29 grandfathered, 0 new drift, 0 stale)node --test tests/lint-storyboard-sample-request-schema.test.cjs— 7/7 pass (reducer + fingerprint + substitution + negative-step unit tests)npm run test:unit— 631 passednpm run typecheck— clean🤖 Generated with Claude Code