DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • 6 Techniques To Reduce LLM API Costs With the Python Library
  • Agentic System Design in Practice: The Technical Debt in Enterprise Agentic Systems
  • How I Built a Storage System for My Agent’s Memory
  • When TypeScript Types Meet Untrusted AI: Building Type-Safe LLM Pipelines With Runtime Validation

Trending

  • The Real Skill Stack Behind Production-Ready AI Engineers
  • From Platform Cowboys to Governance Marshals: Taming the AI Wild West
  • Stop Paying Your AI Agent to Do the Same Job Twice
  • Implementing Asynchronous Communication Between Microservices Using Kafka and Spring Boot
  1. DZone
  2. Data Engineering
  3. AI/ML
  4. Beyond Linting: Why We Switched To Semantic Contracts for A11y and Localization

Beyond Linting: Why We Switched To Semantic Contracts for A11y and Localization

We arrived at the concept of "Semantic Contracts" not as a top-down decree, but as a survival mechanism. Here's how we implemented the switch.

By 
Ridhdhi Desai user avatar
Ridhdhi Desai
·
Sep. 23, 26 · Analysis
Likes (0)
Comment
Save
Tweet
Share
114 Views

Join the DZone community and get the full member experience.

Join For Free

I remember sitting in the war room three days before a major release. We were confident; our static accessibility (a11y) linter was passing, and our localization (l10n) unit tests, which performed simple string comparisons, returned green. Then, a beta user reported that the primary_submit_action button was physically impossible to tap because our localization file had grown the button label, pushing the touch target off-screen.

Our tests hadn't failed because they weren't looking at the screen. They were looking at text files. That was the moment I realized our reliance on brittle string-comparison and basic static linting had hit a hard wall at scale. We needed a new approach, one that didn't just check for the presence of a label, but verified the semantic contract between the layout and the user. 

The Semantic Contract Insight

We arrived at the concept of "Semantic Contracts" not as a top-down decree, but as a survival mechanism. We were suffering from the "false positive" epidemic: tests that passed while the product was broken. We needed to treat our accessibility tree and layout engine as dynamic data structures rather than static files.

By moving the validation gate into the CI/CD pipeline and using an AI orchestrator to enforce multi-dimensional constraints, we shifted from checking if a button exists to ensuring it functions according to the contract of our design system.

From Linting to Semantic Contracts

Making the Switch from Linting to Semantic Contracts


Pillar 1: Accessibility as a Semantic Contract

Our first attempt at accessibility was rule-based. We hardcoded minimum coordinate thresholds (like 44x44 points) into our CI pipeline. It worked until our design system grew to include nested containers that varied by device class. Hardcoded thresholds became a maintenance nightmare, costing us five engineering hours per sprint in manual threshold adjustments. We realized accessibility couldn't be a list of static rules; it had to be a contract validated within the CI environment.

The Tradeoff: Complexity vs. Coverage

We tried standard automated scanners like native native a11y inspectors, but they failed to catch context-dependent issues. For example, an icon-only button is technically "accessible" if the label exists, but it’s contextually confusing if the label isn't descriptive. The cost of manual audit was too high, so we pivoted to an LLM-validator.

Implementation: Enforcing the Contract

We now use automated XCUITest assertions to ensure every primary interactive element meets our physical usability thresholds, followed by an LLM-based pass to ensure the semantic quality of those labels.

Swift
 
func testSubmitButtonMeetsAccessibilityMinimums() {

    let app = XCUIApplication()

    // Using a standard identifier from our design system

    let submitButton = app.buttons["primary_submit_action"]

    

    // Explicitly check for the presence to avoid false positives

    XCTAssertTrue(submitButton.exists, "Primary action button not found in hierarchy.")

    

    // Enforcing the 44x44 touch target contract

    let frame = submitButton.frame

    XCTAssertTrue(frame.size.width >= 44 && frame.size.height >= 44, 

                  "Submit button size \(frame.size) is below the 44x44 accessibility threshold.")

}

Pillar 2: Localization via Visual-Contextual Pipelines

Localization is often treated as a "search and replace" problem. When we were just comparing strings, we missed layout collisions constantly. The tradeoff here was significant: we moved from fast, flaky screenshot comparison testing to a slower, more accurate multi-modal LLM collision detection.

The Failure of Visual Regression

We initially tried pixel-perfect screenshot regression. It failed because our dynamic content—like usernames and feed timestamps—caused thousands of "false failures." Maintaining the baseline screenshots cost us more time than actually writing the localized strings.

Implementation: The Semantic Validator

We now feed our view hierarchy (as JSON) and snapshots into an LLM orchestrator. This allows the system to understand that a button label is not just a collection of pixels, but an interactive semantic component that must not overlap with its parent container.

Python
 
import openai

def validate_accessibility_labels(accessibility_tree_json):

    prompt = f"""

    You are an accessibility expert. Analyze the following UI accessibility tree. 

    Verify that every interactive element has an accessibility label that is descriptive 

    and not just a repeated image filename or a cryptic ID.

    

    Accessibility Tree: {accessibility_tree_json}

    

    Return a JSON response: {"passed": bool, "issue_description": str}

    """

    

    response = openai.ChatCompletion.create(

        model="gpt-4o",

        messages=[{"role": "user", "content": prompt}]

    )

    return response.choices[0].message.content



Architecture Summary

Validation Engine

Input Source

Analytical Method

A11y-Validator

Accessibility Tree

Rule-based logic + LLM semantic labeling

L10n-Visualizer

UI Snapshot + Resource Keys

LLM-based boundary collision detection

Contract-Gate

CI/CD Environment

Infrastructure-as-Policy enforcement


Moving Forward

The transition to semantic contracts was not cheap in terms of CI time—validating against an LLM is slower than a simple regex check. However, the cost of an emergency patch or a poor user experience for our accessible or international user base is significantly higher.

By treating our UI as data and our accessibility requirements as verifiable contracts, we’ve moved the conversation from "Does this lint?" to "Does this meet our contract?" That shift is what keeps our release process sane, even at scale.

large language model

Opinions expressed by DZone contributors are their own.

Related

  • 6 Techniques To Reduce LLM API Costs With the Python Library
  • Agentic System Design in Practice: The Technical Debt in Enterprise Agentic Systems
  • How I Built a Storage System for My Agent’s Memory
  • When TypeScript Types Meet Untrusted AI: Building Type-Safe LLM Pipelines With Runtime Validation

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook