Skip to content

Invert feature gating: required_featuresmissing_features#134

Merged
ianks merged 3 commits intomainfrom
invert-feature-gating
Apr 28, 2026
Merged

Invert feature gating: required_featuresmissing_features#134
ianks merged 3 commits intomainfrom
invert-feature-gating

Conversation

@ianks
Copy link
Copy Markdown
Contributor

@ianks ianks commented Apr 27, 2026

Previously adapters declared what they support (allowlist / default-deny). This caused silent test-skipping: a new spec with required_features that no adapter declared would silently never run anywhere. The 27 broken ToSDrop specs from caf34da went undetected for 4 months because ruby_drops wasn't in the reference adapter's allowlist.

What changed

Polarity flip:

  • Specs declare features: — informational tags describing what the spec exercises (renamed from required_features)
  • Adapters declare config.missing_features = [...] — an explicit denylist of capabilities they can't provide
  • A spec runs unless its tags intersect the adapter's missing_features

Default is now run everything. Skipping requires a conscious opt-out.

Coverage check (new):

Added a coverage_check rake task, wired into CI, that verifies every feature tag used in the spec YAML is "covered" — i.e. not in every adapter's missing_features. This makes orphan tags a CI failure rather than a silent gap.

Coverage check passed: all 15 feature tags covered across 10 reference adapters.

Reference adapters updated — each now declares what it genuinely can't handle:

  • liquid_ruby.rb: missing Shopify-specific features + activesupport + lax_parsing
  • liquid_ruby_shopify.rb: empty (runs everything — full Shopify Ruby Liquid)
  • liquid_c.rb: missing runtime_drops, ruby_types, etc.

Also includes the ToSDrop counter restore fix and the [](key) method needed for map filter tests.

Migration for adapters outside this repo

# Before:
config.features = [:core, :strict_parsing, :ruby_types]

# After (conservative — preserves current skip behavior exactly):
config.missing_features = [:lax_parsing, :activesupport, :shopify_filters, ...]

# After (ideal — only list what you genuinely can't handle):
config.missing_features = [:shopify_filters, :shopify_tags]

ianks added 3 commits April 27, 2026 15:54
Previously adapters declared what they support (allowlist / default-deny).
This caused silent test-skipping: a new spec with required_features that no
adapter declared would never run anywhere.

This inverts the polarity:

- Specs declare `features:` — informational tags describing what they exercise
- Adapters declare `config.missing_features = [...]` — explicit denylist of
  capabilities they can't provide
- A spec runs unless its tags intersect the adapter's missing_features

Default: run everything. Skipping requires conscious opt-out.

Also adds a `coverage_check` rake task (wired into CI) that verifies every
feature tag in the spec YAML files is covered by at least one reference adapter
(i.e. not in every adapter's missing_features). This makes orphan tags a CI
failure rather than a silent gap.

Includes the ToSDrop counter restore fix (cherry-picked from restore-tosdrop-counter)
and the [] method for property-access tests.
@ianks ianks requested review from Maaarcocr and tobi April 27, 2026 20:21
@ianks ianks merged commit 7f5fb3e into main Apr 28, 2026
2 checks passed
@ianks ianks deleted the invert-feature-gating branch April 28, 2026 13:31
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.

2 participants