Skip to content

fix(storyboards): format_id / signal_ids entity-id drift cluster (adcp#2763)#2788

Merged
bokelley merged 2 commits into
mainfrom
bokelley/fix-format-id-shape
Apr 22, 2026
Merged

fix(storyboards): format_id / signal_ids entity-id drift cluster (adcp#2763)#2788
bokelley merged 2 commits into
mainfrom
bokelley/fix-format-id-shape

Conversation

@bokelley

Copy link
Copy Markdown
Contributor

Summary

Second cluster follow-up to the schema lint from #2768. Two-part fix for the entity-id-as-object cluster.

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 `{}`, 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:

  • `protocols/media-buy/index.yaml#creative_sync/sync_creatives`
  • `protocols/media-buy/index.yaml#product_discovery/list_formats_integrity`
  • `protocols/media-buy/scenarios/pending_creatives_to_start.yaml#supply_creatives/sync_creative`
  • `specialisms/signal-marketplace/index.yaml#discovery/search_by_ids`
  • `specialisms/signal-marketplace/index.yaml#verification/verify_provenance_metadata`

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)
  • All 6 other storyboard lints pass
  • npm run test:unit — 631 passed
  • npm run typecheck — clean

🤖 Generated with Claude Code

bokelley and others added 2 commits April 21, 2026 21:52
…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>
@bokelley
bokelley merged commit ea57a80 into main Apr 22, 2026
12 checks passed
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>
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