UCDL Accessibility Use Case Definition Language
Contents

Accessibility Use Case Definition Language (UCDL) and Runner

This section is normative.

The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL in this document are to be interpreted as described in [RFC 2119] and [RFC 8174] when, and only when, they appear in all capitals.

The following classes of conforming products are defined:

2.2.1 Conforming use case document

A YAML document that:

  1. Validates against the schema in Appendix B; and
  2. Whose steps (or whose steps_override.steps, after resolution against its extends chain) all parse against the grammar in Appendix A; and
  3. Whose template variables (see §7.4) are all resolvable against the document's effective data map.

A document MAY be a conforming use case document even if its extends ancestor is not present in the same parse batch, but a resolved use case document — one with all extension chains followed and all steps materialized — REQUIRES that every ancestor referenced via extends is itself a conforming use case document, and that the chain is acyclic.

2.2.2 Conforming UCDL processor

A processor MUST declare which of the classes below it implements, and which optional capabilities it supports. Declaring the class is what makes a claim checkable: without the classes a parser-only implementation could not conform at all, because §2.3's scoring requirement would apply to every processor.

Class Implements
Document Produces documents conforming to §2.2.1.
Parser §7 stages 1–4: schema, step syntax, semantic constraints, inheritance and data resolution. Emits the AST of §7.6.
Executor Runs a resolved case against a page and produces step results. Declares its capabilities (below) and MUST refuse a document requiring one it lacks, rather than skipping the step.
Reporter Emits §10.1's shape from step results.

Executor capabilities are declared individually, because a processor without an OCR engine is not thereby non-conforming — it simply cannot run a document that uses read_image: audit, contrast, lang_check, read_image, sr_says (virtual), sr_says (real driver), viewport, and interaction profiles.

§2.3's scoring requirement belongs to the executor class.

A program that, given any conforming use case document and the configured external data files (see §12.2), produces:

  • a parse tree equivalent to the one defined by §7; or
  • a Playwright .spec.ts source whose runtime behavior, when executed by Playwright ≥ 1.40, is consistent with §5 and §8; or
  • a live execution result whose runtime behavior is consistent with the same sections; or
  • a report consistent with §10.

A processor MAY support a subset of these output forms. A processor MUST clearly identify which forms it supports.

2.2.3 Conforming use case report

A document — JSON, HTML, or any other format — that contains, for a single resolved use case execution, at minimum:

  • the id, title, and type of the use case;
  • the score, drawn from the enumeration defined in §11;
  • a list of step results, each with step number, step text, status, and duration;
  • a timestamp and a tester identifier; and SHOULD contain an environment record (§10.1).

The JSON form defined in §10.1 is the canonical form and is REQUIRED to be supported by any processor that emits reports.

2.3 Compatibility with the manual rubric

A conforming UCDL processor MUST emit scores drawn from the enumeration in §11, and MUST map them to the manual labels Pass, Pass w/ Conditions, and Fail of the informative document Use-case-description.md as §11 defines. The labels are comparable, not interchangeable. A manual tester assigns Pass w/ Conditions on a judgement about friction, workarounds, or assistance rendered; the automated score has no such dimension and is computed from step outcomes and accessibility_notes alone. A report that merges automated and manual results MUST keep the two sources distinguishable, so a reader can tell which kind of evidence a label rests on.


2.4 Language versioning and change classes

This section is normative.

The language carries its own version, independent of any implementation's. Tying the two together would make every package patch release a language release and leave a second implementer with no stable target: there would be no way to say "implements UCDL 1.0" separately from "matches a given @afixt/usecase-runner version".

A document MAY declare the version it is written to:

ucdl: '1.0'
id: login-success

The field is OPTIONAL in 1.0 — a document without it is read as 1.0. A processor MUST refuse a document declaring a version it does not implement, rather than parsing it hopefully.

Changes to this document fall into four classes:

Class Meaning Version effect
Editorial Wording, examples, cross-references. No normative content changes. none
Clarification States what was already required, where the text was silent or unclear. none
Additive New syntax or fields a conforming document may ignore. Nothing that parsed stops parsing. minor
Breaking A spelling that parsed no longer does, or a reported value changes meaning. major

Only a breaking change bumps the language major. Whether the reference implementation ships a change as a major of its own package is a separate decision, taken on its own release policy.

2.5 Portable core and Playwright binding

This section is informative.

Sections divide into two kinds, and a second implementation needs to know which is which:

Sections
Portable core — the language, independent of any automation engine §4, §5 (semantics), §6 (the resolution algorithm), §7, §10 (report shape), §11
Binding — how the reference implementation realises the core on Playwright §6's method names, §8.1's generated-file shape, §9.3's snapshot mechanism, §12–§14

Portable semantics are currently expressed in places using Playwright method names (toBeVisible(), check(), selectOption()), which conflates the two. Restating the core without them is intended work; the labelling above is the first step, and the document is deliberately not split into five until a second implementation exists to split it for.