Skip to content

compliance(storyboards): fixture-hash normalization + requires_scenarios spec#2688

Merged
bokelley merged 1 commit into
mainfrom
bokelley/requires-scenarios-spec-fixtures-sort
Apr 21, 2026
Merged

compliance(storyboards): fixture-hash normalization + requires_scenarios spec#2688
bokelley merged 1 commit into
mainfrom
bokelley/requires-scenarios-spec-fixtures-sort

Conversation

@bokelley

Copy link
Copy Markdown
Contributor

Summary

Two hygiene follow-ups from #2679's expert review:

Fixture hash normalization (#2682)

`fingerprintEnv` now sorts arrays within each documented fixture category by its primary id before `stableStringify`. Two storyboards with semantically equivalent fixtures — `products: [A, B]` vs `products: [B, A]` — land in the same env bucket. Closes the false-negative envelope before `#2670 part 2` removes `sb=<doc.id>` and makes env-fingerprint precision load-bearing.

Sort keys (mirrors the schema's `fixtures:` block):

  • `products → product_id`
  • `pricing_options → pricing_option_id`
  • `creatives → creative_id`
  • `plans → plan_id`
  • `media_buys → media_buy_id`

Unknown fixture categories throw — a new seed category added to the schema without updating `FIXTURE_CATEGORY_PRIMARY_ID` is a hard error. Forces schema-doc and lint updates to land together so a silent false-negative bucket can't emerge.

requires_scenarios spec (#2683)

`storyboard-schema.yaml` now normatively describes the flow of `branch_set` contribution flags between a parent storyboard and its linked scenarios:

  • A flag contributed in parent X is considered asserted if either X's own phases assert it OR a scenario Y in `X.requires_scenarios` asserts it via `assert_contribution any_of`.
  • Reverse flow is prohibited — scenarios MUST be internally self-grading to preserve standalone lintability and prevent cycles in the composition graph.
  • Scenario IDs must match the referenced file's top-level `id:` exactly, and the file MUST exist at build time.

Matches the `orphan_contribution` lint behavior shipped in #2679. The lint was the de facto spec; this PR closes the gap.

Test plan

  • `npm run test:storyboard-contradictions` — 25 tests (3 new: array-order stability, content-difference still discriminated, unknown-category throws + documented categories round-trip)
  • `npm run test:storyboard-branch-sets` — unchanged, 19 tests pass
  • `npm run build:compliance` — all four storyboard lints green
  • Precommit (`npm run test:unit` + `typecheck`) — 631 tests pass
  • Expert review (code + protocol) applied: throw on unknown fixture category, strengthened reverse-flow restriction, scenario file existence in spec

Follow-up filed

  • #2687 — `unresolved_scenario_reference` grading reason + lint hard error on missing scenario files. Symmetrizes with the duplicate-`doc.id` throw already in `buildScenarioFlagIndex`.

🤖 Generated with Claude Code

…ios spec

Two hygiene follow-ups from #2679 expert review.

Fixture hash normalization (#2682):
- normalizeFixturesForHashing sorts arrays within each documented
  fixture category by its primary id before stableStringify.
- Categories + primary ids: products/product_id, pricing_options/
  pricing_option_id, creatives/creative_id, plans/plan_id,
  media_buys/media_buy_id.
- Unknown fixture category throws: schema-doc and lint updates must
  land together so a new seed category can't silently create a
  false-negative env-fingerprint bucket.
- Closes false-negative envelope before #2670 part 2 removes
  sb=<doc.id> and makes env-fingerprint precision load-bearing.

Spec: flag flow across requires_scenarios (#2683):
- storyboard-schema.yaml now normatively describes how branch_set
  contribution flags flow between parent and linked scenarios.
- Parent-flag flow: contributed in X, asserted in X or in any
  scenario Y listed in X.requires_scenarios.
- Reverse flow prohibited — scenarios MUST be internally self-
  grading to preserve standalone lintability and prevent cycles
  in the composition graph.
- Scenario IDs must match the referenced file's top-level id: and
  the file MUST exist at build time.

Tests: contradiction suite 25 (3 new — array-order stability,
content-difference still discriminated, unknown category throws +
documented categories round-trip).

Follow-up #2687 filed for unresolved_scenario_reference grading
(symmetric with the duplicate-id throw already in place).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@bokelley bokelley merged commit 573665c into main Apr 21, 2026
14 checks passed
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