Keep status, accessibility result, and release check separate
Three fields describe different layers of a scan. Mixing them is the most common integration error.
status: platform execution
status answers whether AccessPreflight completed trustworthy processing. Only completed has a final result. fetch_failed, timed_out, and engine_failed are operational failures—not accessibility passes or failures.
result: accessibility preflight outcome
For a completed scan, result follows this precedence:
incompletewhen required configured coverage was not achieved.detected_failureswhen an unsuppressed deterministic or partial failure exists.review_requiredwhen heuristic signals or manual work remain.no_detected_failureswhen none of the above apply.
no_detected_failures means no failure was detected within executed coverage. It never means “certified compliant.”
quality_gate.status: your release policy
The release check is calculated independently:
passed: the configured gate was evaluated and passed.failed: one or more configured blocking conditions occurred.indeterminate: the policy could not reach a trustworthy pass/fail decision, commonly because coverage is incomplete or a required baseline is missing.not_configured: no release rule was supplied or resolved.
A not_configured gate is not a pass. If your CI requires a gate, explicitly reject this value.
Safe CI decision table
| Condition | Deployment decision |
|---|---|
status != completed |
Do not interpret accessibility outcome; fail or hold according to availability policy |
result == incomplete |
Hold for investigation unless your documented policy explicitly allows reduced coverage |
quality_gate.status == failed |
Block |
quality_gate.status == indeterminate |
Hold or fail closed |
quality_gate.status == not_configured |
Configuration error if a gate was expected |
quality_gate.status == passed |
Gate passed; still complete required manual work |
Example evaluator
const decide = (scan) => {
if (scan.status !== 'completed')
return { decision: 'hold', reason: `scan_${scan.status}` }
if (scan.result === 'incomplete')
return { decision: 'hold', reason: 'incomplete_coverage' }
switch (scan.quality_gate?.status) {
case 'passed':
return { decision: 'continue', reason: 'gate_passed' }
case 'failed':
return { decision: 'block', reason: 'gate_failed' }
case 'indeterminate':
return { decision: 'hold', reason: 'gate_indeterminate' }
default:
return { decision: 'hold', reason: 'gate_not_configured' }
}
}
This evaluator intentionally does not use risk_score as a pass/fail threshold. Risk score prioritizes technical remediation; it is not a compliance percentage.