Esquema de salida

Esta es la estructura exacta del objeto que devuelven runDomRulesInPage(...) / runa11yCoreInPage(...) (consulta INTEGRATION.md para saber cuál llamar). Todos los ejemplos de esta página son salida real del motor actual (schemaVersion: "1.0.0"), no están escritos a mano. runa11yCoreAcrossFrames devuelve una estructura distinta y recursiva que envuelve esta. Ver Resultado entre frames más abajo.

Resultado de nivel superior

{
engine: {
tag: string,
schemaVersion: string,
locale: { requested: string, resolved: string, reason: string },
wcagVersion: "2.0" | "2.1" | "2.2"
},
url: string | null,
title: string | null,
timestamp: string | null,
perfStats: object | null,
contextSelector: string | string[] | null,
checksResults: CheckResult[],
rulesResults: CompositeResult[],
overriddenBuiltinIds: string[]
}
CampoSignificado
engine.tagLa etiqueta de identidad propia del motor, actualmente "a11ycore". Cada regla (integrada o personalizada) la lleva en meta.tags: los ruleId de las reglas en sí son simples (sin prefijo).
engine.schemaVersionLa versión del esquema de resultados ("1.0.0"). Sujeta a incrementarse si la estructura de este documento cambia alguna vez de manera incompatible: ánclate a ella si analizas la salida de forma programática. Consulta API_STABILITY.md para ver la lista completa de campos estables/inestables y la política de incremento de versión.
engine.localeQué diccionario usó realmente la ejecución. requested es tu engineOptions.locale después de recortar espacios ("en" si no pasaste nada o pasaste algo que no es una cadena); resolved es el idioma cuyo diccionario se usó; reason explica el porqué de ese emparejamiento. Como el mecanismo de reserva de idioma es gradual y se aplica cadena por cadena, pedir un idioma que la compilación no incluye produce texto en inglés en lugar de un error: este campo es cómo te enteras de eso sin leer las cadenas. Se informa una vez por resultado: una ejecución usa un solo diccionario en todo momento.
engine.locale.reason"ok": obtuviste el diccionario que pediste, y contiene todas las claves. "primary-subtag": tu código tenía un subtag sin diccionario propio, así que se usó su idioma base: "de-DE" se resuelve a "de". "dictionary-not-loaded": el proyecto incluye ese idioma, pero esta compilación no lo lleva y no se suministró ninguno (el paquete independiente para navegador, sin su archivo lateral de idioma). "unknown-locale": el proyecto no tiene ninguna traducción de ese tipo. "partial-dictionary": se usó el diccionario, pero le faltan claves que el inglés sí tiene, así que esas cadenas recurrieron al inglés. Trata este conjunto como abierto; versiones posteriores pueden añadir más.
engine.wcagVersionContra qué versión de WCAG se evaluó la conformidad en esta ejecución: tu engineOptions.wcagVersion, o lo que implicaban tus etiquetas de origen de versión, o el valor predeterminado "2.2". Hoy afecta a una sola cosa: una regla mapeada únicamente al SC 4.1.1 Parsing no puede dar fail bajo un objetivo 2.2 (ver checksResults[i].wcagVersionScope más abajo). Se informa una vez por resultado: una ejecución tiene un solo objetivo en todo momento.
urlEl argumento pageUrl que pasaste, o document.location.href si pasaste null/lo omitiste, o null si ninguno está disponible.
titledocument.title en el momento del análisis o null.
timestampNo se genera automáticamente. Solo se establece si pasas engineOptions.timestamp como una cadena no vacía: el motor no tiene reloj integrado (es determinista por diseño). Si quieres una marca de tiempo del análisis en el resultado, súplela tú mismo.
perfStatsnull a menos que engineOptions.perfStats: true. Temporizaciones/contadores internos: su estructura no está cubierta por este documento, trátalo como solo para depuración.
contextSelectorEl argumento (recortado) contextSelector que pasaste: una cadena, un array de cadenas (análisis multi-región, ver Opciones del motor), o null si no hay ninguno o está vacío.
checksResultsUna entrada por cada regla atómica que se ejecutó (toda regla no filtrada por runOnly, ver Opciones del motor). Cada regla cargada produce una entrada, incluso las que dan como outcome notApplicable: esto no es una lista de «solo violaciones».
rulesResultsUna entrada por cada regla compuesta (agregación por SC de WCAG) que se ejecutó. Ver Un resultado compuesto y Conformidad. Array vacío si ningún compuesto coincidió con el filtro runOnly/etiqueta actual.
overriddenBuiltinIdsIds de regla en los que una entrada de engineOptions.customRules compartió su id con una regla integrada, de modo que la implementación personalizada reemplazó a la integrada para este análisis (ver Opciones del motor). Siempre es un array; vacío cuando no ocurrió ninguna colisión. También se registra vía console.warn en el momento del análisis, ya que una regla personalizada con el mismo nombre es tan probable que sea una colisión accidental como una sustitución deliberada.

Resultado entre frames (runa11yCoreAcrossFrames)

runa11yCoreAcrossFrames (consulta INTEGRATION.md) devuelve una estructura distinta y recursiva en lugar de un resultado de nivel superior simple:

{
topFrame: <the normal top-level result shape above>,
frames: Array<
| { url: string | null, topFrame: <top-level result>, frames: [...same shape, recursively] }
| { url: string | null, error: string }
>
}
  • topFrame es exactamente la estructura del resultado de nivel superior, para el frame en el que se llamó a la función.
  • frames tiene una entrada por cada <iframe>/<frame> hijo directo dentro del ámbito analizado. Un hijo alcanzable (uno que llamó a a11yCoreEnableFrameResponder()) aporta su propio { url, topFrame, frames } completo: incluyendo sus propios frames anidados, de forma recursiva, ya que un nieto anidado más profundo solo es alcanzable a través de su padre inmediato. Un hijo inalcanzable (el caso común para la mayoría de los embebidos de terceros, sin responder cooperante o que agotó el tiempo de espera) aporta { url, error } en su lugar, y no aborta el resto del análisis.
  • Esto es un árbol, no una lista plana: una diferencia deliberada respecto a @surea11y/playwright's .frames(true), que puede aplanar porque page.frames() de Playwright ya entrega todos los frames sin importar la profundidad de anidamiento; un relé por postMessage no tiene esa visión global, así que el anidamiento se expresa de forma estructural en su lugar.

Un resultado de comprobación (checksResults[i])

{
ruleId: string,
outcome: "pass" | "fail" | "cantTell" | "notApplicable",
outcomeNormalized: "pass" | "fail" | "cantTell" | "inapplicable",
severity: "minor" | "moderate" | "serious" | "critical",
confidence: "high" | "medium" | "low",
type: "automatic" | "manual",
occurrences: Occurrence[],
title: string,
description: string,
i18n: { titleKey: string, descriptionKey: string } | null,
meta: {
ruleId: string,
ruleInterfaceVersion: string,
ruleVersion: string,
normative: boolean,
atomic: boolean,
deprecated: boolean,
deprecation: object | null,
category: "perceivable" | "operable" | "understandable" | "robust" | null,
normativeMappings: Array<{ standard: string, version: string, requirement: string, title: string, conformanceLevel: string }>,
standard: string | null,
applicability: string,
expectation: string,
references: string[],
requirements: object | null,
mappings: object | null
},
engineOptions: object, // the resolved engineOptions this rule actually ran under
schemaVersion: string,
wcagVersionScope?: { // present only when the target WCAG version changed this outcome
target: "2.0" | "2.1" | "2.2",
removedSc: string[],
coercedFrom: "fail"
},
error?: string // present only if the rule threw — see below
}

Notas:

  • outcome frente a outcomeNormalized: idénticos, salvo que notApplicable se convierte en "inapplicable" en outcomeNormalized. Se ofrecen ambos para que puedas ajustarte a tu propio vocabulario o al vocabulario interno del motor.
  • Las reglas type: "manual" nunca pueden devolver outcome: "fail". Si la lógica propia de una regla manual hubiera dicho fail, el motor la fuerza a cantTell y añade una nota explicativa a error: esto se aplica de forma centralizada (policy.coerceManualFailToCantTell, activado por defecto bajo el contrato de política a11y; consulta POLICY.md), no es algo que cada regla tenga que recordar por su cuenta. fail está reservado únicamente para hallazgos deterministas de type: "automatic".
  • meta.normativeMappings es cómo un resultado de comprobación se vincula de vuelta a un criterio de éxito de WCAG: [] para reglas sin mapeo formal a WCAG (este motor las llama reglas consultivas type: "manual"). Consulta Conformidad para ver cómo se agregan.
  • wcagVersionScope: presente solo cuando la versión de WCAG objetivo de la ejecución convirtió el fail de esta regla en un cantTell: hoy eso significa una regla mapeada al SC 4.1.1 Parsing (duplicate-id) bajo el objetivo 2.2 predeterminado, ya que 2.2 eliminó ese criterio. removedSc enumera los criterios que dejaron de existir, target es la versión que los eliminó, y coercedFrom es el outcome que la propia regla devolvió. Las occurrences son las propias de la regla, sin cambios: no se descartó nada, solo cambió el veredicto de conformidad. Ausente en cualquier otro resultado, y nunca se indica a través de error: no salió nada mal. Consulta Filtrado por versión de WCAG.
  • error: presente solo en tres casos: la implementación de la regla lanzó una excepción no capturada, se activó la coerción de fail manual descrita arriba o cada occurrence de un resultado fail tuvo su recorrido de ancestros topando con un límite de profundidad interno (así que el motor no pudo confirmar que el contenido señalado esté realmente expuesto) y todo el resultado se forzó a cantTell del mismo modo. Una regla que lanza una excepción siempre aparece como outcome: "cantTell" con occurrences: [] y error establecido al mensaje de la excepción: el motor nunca deja que una regla rota haga fallar todo el análisis.
  • engineOptions en cada resultado es el objeto de opciones resuelto (después de aplicar los valores predeterminados de locale/contrast), no literalmente lo que pasaste: útil para confirmar qué vio realmente una regla dada, especialmente el locale resuelto y contrast.mode/contrast.rootCanvasFallback.

Una ocurrencia (occurrences[i])

Normalmente presente solo cuando outcome es fail o cantTell: un resultado pass tiene occurrences: [], ya que este motor no enumera los elementos que pasó, solo los que señaló.

notApplicable es la única excepción. Una regla que no tuvo nada que juzgar puede adjuntar una única occurrence explicando por qué, y las reglas de contraste hacen exactamente eso cuando ningún texto tenía un fondo calculable: la diferencia entre «se comprobó, nada que señalar» y «no se pudo comprobar» es algo que este motor indica en lugar de ocultar. Una occurrence así describe el análisis, no un elemento, así que su selector está vacío. No interpretes occurrences.length como un recuento de violaciones sin comprobar antes outcome.

{
selector: string,
html: string,
structuralPath: number[] | null,
summary: string,
hint: string,
i18n: { summaryKey: string, hintKey: string, params: object } | null,
occurrenceOutcome?: "fail" | "cantTell", // present when the rule graded its findings into tiers
uncertainty?: { // present only on a cantTell-tier occurrence
code: "not-computable" | "runtime-dependent" | "spec-only"
| "equivalence-unknown" | "judgement-required" | "out-of-scope",
needed?: string, // what would settle the question
evidence?: object // what the rule did establish, rule-specific
},
data: {
visibilityFilter?: { eligible: boolean, targetSet: string, accEligible: boolean | null, reasons: string[] },
details?: object // rule-specific, non-normative — see below
}
}
CampoSignificado
selectorUn selector CSS construido con el mejor esfuerzo posible para resolver de vuelta al elemento señalado (ver helpers.buildSelector en RULE_AUTHORING.md). No se garantiza que sea único en estructuras de DOM adversas, pero el motor verifica activamente que resuelva al elemento identificado antes de usarlo. La excepción es una regla cuyo hallazgo es un elemento ausente: page-title-present devuelve head > title con un html de <title>(missing)</title>, ninguno de los cuales está en la página. Ambos son constantes, así que la huella que alimentan se mantiene estable, pero no trates selector como resoluble ni html como marcado real sin comprobar antes que la regla devolvió algo que existe.
htmlUn fragmento de outer-HTML del elemento señalado: úsalo como tu señal principal de «qué elemento es» cuando includeShadowDom: true (los selectores no atraviesan los límites de shadow DOM).
structuralPathLa ruta de índices de hermanos del elemento señalado, desde documentElement hasta él (por ejemplo, [1, 0, 2]): [] si el elemento es documentElement, null si no pudo determinarse. Un mecanismo de identidad de elemento más robusto que selector por sí solo: sobrevive a cambios en el DOM que una cadena de selector no soportaría (un cambio deid/clase, por ejemplo), a costa de no poder usarse como un selector CSS real.
summaryLegible para humanos, ya localizado ("This button has no accessible name.").
hintGuía de corrección legible para humanos, ya localizada.
i18nLas claves de traducción originales detrás de summary/hint, por si quieres volver a renderizarlas tú mismo en otro idioma sin volver a ejecutar el análisis. null si la ocurrencia no usó i18n basado en claves.
data.visibilityFilterPresente en la mayoría de las ocurrencias: por qué el motor consideró este elemento elegible (o no) según el modelo de elegibilidad que usó la regla. eligible es ese resultado; targetSet indica qué modelo lo produjo ('dom': visibilidad de DOM/CSS en bruto, la mayoría de las reglas; 'acc': elegibilidad del árbol de accesibilidad). accEligible refleja eligible solo cuando targetSet es 'acc'; en caso contrario es null. reasons es una lista de códigos de exclusión legibles por máquina cuando eligible: false.
data.detailsDatos estructurados específicos de la regla (métricas calculadas, referencias resueltas),no normativos: útiles para construir una interfaz más rica o para depurar, pero nunca cambian lo que significan outcome/severity. La estructura varía según la regla; trátalo como contexto adicional de mejor esfuerzo, no como un contrato estable. La única excepción es data.details.reasonCode, que es estable: identifica cuál de los hallazgos de una regla es este, y junto con ruleId y html forma la huella sobre la que se indexan los baselines y SARIF. Consulta API_STABILITY.md.
occurrenceOutcomeA qué nivel pertenece esta ocurrencia, en una regla que clasificó sus hallazgos en un nivel fail (con confianza) y un nivel cantTell (que necesita revisión). Una regla que solo informa un nivel lo omite, en cuyo caso el propio outcome del resultado es el nivel de la ocurrencia.
uncertaintyPor qué no se pudo decidir este hallazgo (ver Códigos de incertidumbre más abajo).

Códigos de incertidumbre

Un cantTell dice que el motor no decidió. uncertainty dice por qué, a partir de un vocabulario cerrado, para que un consumidor pueda ramificar según el motivo en lugar de analizar una cadena de resumen. Está presente solo en una occurrence de nivel cantTell: una de nivel fail estaría afirmando que la regla decidió y no decidió a la vez, así que el motor la omite.

codeSignificadoForma típica
not-computableLa evidencia que la regla necesitaba no se pudo leer en este entorno.Una hoja de estilos de origen cruzado, un color de fondo que no resuelve a ningún valor, un src que no se resuelve.
runtime-dependentEl marcado no puede resolverlo porque un script lo decide en tiempo de ejecución.Un aria-controls que nombra un elemento que el widget crea al abrirse.
spec-onlyUna violación real de la especificación, pero el nombre, rol y valor expuestos sobreviven a ella, así que no se establece que ningún criterio de éxito haya fallado.Un atributo ARIA cuya ausencia la especificación cubre con un valor predeterminado.
equivalence-unknownDos cosas pueden o no cumplir el mismo propósito, y ni el marcado ni el contenido lo resuelven.Dos frames que comparten un nombre accesible pero incrustan recursos distintos.
judgement-requiredLa pregunta es, por naturaleza, una decisión humana.Si un objetivo de tamaño insuficiente es esencial; toda regla type: "manual".
out-of-scopeEl hallazgo es real, pero queda fuera del estándar al que apunta esta ejecución.Una regla mapeada únicamente a un criterio que la versión de WCAG objetivo eliminó.

needed indica, en una frase, qué resolvería la cuestión: lo que un revisor tiene que ir a comprobar. evidence lleva lo que la regla llegó a establecer, para que el revisor parta del trabajo del motor en lugar de repetirlo; su estructura es específica de cada regla y, como data.details, no es un contrato estable. En cuanto a code: pueden añadirse códigos nuevos en una versión menor, pero uno existente no cambia de significado, así que ramifica según los códigos que conoces y trata uno no reconocido como «necesita revisión» en lugar de como un error.

Toda regla automática que puede devolver cantTell lleva esto, y una prueba mantiene esa línea para que no pueda llegar una nueva sin ello. El código out-of-scope lo adjunta el motor, no una regla, en las mismas occurrences que producen un wcagVersionScope a nivel de resultado. Las reglas manuales no lo llevan: judgement-required ya es lo que significa type: "manual", así que repetirlo por occurrence no diría nada que el resultado no diga ya.

Un resultado compuesto (rulesResults[i])

Los compuestos agregan varias reglas atómicas en un solo criterio de éxito de WCAG (por ejemplo, wcag-1.1.1-non-text-content agrega 21 reglas atómicas). La estructura es la misma que la de un resultado de comprobación, con un data.details específico de compuestos:

{
ruleId: string, // e.g. "wcag-1.1.1-non-text-content"
outcome: "pass" | "fail" | "cantTell" | "notApplicable",
severity, confidence, type, title, description, meta, engineOptions, schemaVersion, // same as a check result
occurrences: [], // always empty — composites are rollups, not element-level findings
data: {
details: {
reasonCode: string, // e.g. "composite.rollup.fail.anyFail"
checksIds: string[], // every atomic ruleId this composite rolls up
contributors: Array<{ testId: string, outcome: string, severity: string | null }>,
metrics: { failCount, cantTellCount, notApplicableCount, passCount, missingCount }
}
}
}

Precedencia de la agregación (determinista, en este orden): cualquier contribuyente fail → compuesto fail; si no, cualquier cantTell (o una regla contribuyente que no se ejecutó en absoluto, missingCount > 0) → compuesto cantTell; si no, todos los contribuyentes notApplicable → compuesto notApplicable; si no, pass. Consulta Conformidad para ver qué implica esto en una afirmación de conformidad global.

Valores de outcome

ResultadoSignificado¿Puede aparecer en type: "manual"?
failViolación determinista y normativa: el procedimiento de decisión no adivina nada.No (se fuerza a cantTell)
passEl/los objetivo(s) aplicable(s) de la regla existen y ninguno fue señalado.
cantTellRequiere juicio humano: ya sea genuinamente ambiguo o el hallazgo de carácter consultivo de una regla manual.
notApplicableLa regla no encontró elementos a los que aplicarse en esta página/ámbito.

fail es, de forma intencional, el outcome más estrecho y de mayor exigencia en este motor: reservado para violaciones deterministas y normativas; la persecución de cobertura de reglas nunca debe diluir esto.

Valores de severity y confidence

  • severity: minor < moderate < serious < critical: la evaluación del autor de la regla sobre el impacto en el usuario, independiente de confidence.
  • confidence: low < medium < high: cuán seguro está el motor de que un veredicto fail/cantTell es correcto. Ambos son metadatos informativos para priorizar; ninguno cambia el significado de outcome.

Un fail no siempre tiene confidence: "high", y eso no es una contradicción. El outcome describe el procedimiento de decisión (resolvió la cuestión sin adivinar), mientras que confidence describe el modelo contra el que se tomó esa decisión. Un puñado de reglas automáticas deciden de forma determinista contra algo que en sí mismo es una aproximación (las tablas curadas de roles WAI-ARIA, los mapeos de roles nativos, un árbol de accesibilidad inferido a partir de marcado estático) y devuelven medium: aria-required-children, aria-prohibited-children, aria-required-parent, aria-allowed-attr, form-control-programmatic-label-present, identical-iframes-same-purpose, svg-image-text-alternative-present, video-poster-text-alternative-present y target-size-minimum. confidence está presente en todo resultado, así que un consumidor que solo quiera los fallos más seguros puede filtrar directamente por él; policy.allowedConfidence no hará eso por ti, ya que un valor no permitido se sustituye por el defaultConfidence propio de la regla en lugar de cambiar el outcome (consulta POLICY.md).

Ejemplo resuelto

Analizando <img src="logo.png"> (sin alt) y <button></button> (sin nombre accesible), limitado a esas dos reglas mediante runOnly: { includeRuleIds: [...] } (ver Opciones del motor; esto no es un array simple):

const result = runDomRulesInPage(
'https://example.test/',
null,
{},
{ includeRuleIds: ['img-alt-present', 'button-name-present'] }
);
{
"engine": {
"tag": "a11ycore",
"schemaVersion": "1.0.0",
"locale": { "requested": "en", "resolved": "en", "reason": "ok" }
},
"url": "https://example.test/",
"title": "Example",
"timestamp": null,
"perfStats": null,
"contextSelector": null,
"checksResults": [
{
"ruleId": "button-name-present",
"outcome": "fail",
"severity": "serious",
"confidence": "high",
"type": "automatic",
"occurrences": [
{
"selector": "html > body > button",
"html": "<button></button>",
"structuralPath": [1, 1],
"summary": "This button has no accessible name.",
"hint": "Provide visible button text or a programmatic accessible-name mechanism (for example aria-label) so assistive technologies can identify the button.",
"data": {
"visibilityFilter": { "eligible": true, "reasons": [], "targetSet": "acc", "accEligible": true },
"details": { "reasonCode": "name_missing" }
}
}
]
},
{
"ruleId": "img-alt-present",
"outcome": "fail",
"severity": "serious",
"confidence": "high",
"type": "automatic",
"occurrences": [
{
"selector": "html > body > img",
"html": "<img src=\"logo.png\">",
"structuralPath": [1, 0],
"summary": "Missing alt attribute on <img>.",
"hint": "Add an alt attribute (use alt=\"\" only for decorative images)."
}
]
}
],
"rulesResults": [],
"overriddenBuiltinIds": []
}

(Recortado por legibilidad: el resultado real también incluye title/description/i18n/meta/engineOptions/schemaVersion en cada entrada, según la estructura completa mostrada arriba. rulesResults está vacío aquí porque runOnly.includeRuleIds limitó el análisis a dos reglas atómicas y no se incluyó el ID propio de ningún compuesto.)