testaro 78.0.8 → 78.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (356) hide show
  1. package/.gitattributes +94 -0
  2. package/.github/workflows/ci.yml +58 -0
  3. package/.github/workflows/publish.yml +49 -0
  4. package/.github/workflows/typescript.yml +35 -0
  5. package/AGENTS.md +2 -2
  6. package/CLAUDE.md +24 -18
  7. package/CONTAINERS.md +9 -6
  8. package/CONTRIBUTING.md +29 -3
  9. package/Dockerfile +1 -1
  10. package/README.md +73 -19
  11. package/UPGRADES.md +4 -0
  12. package/actSpecs-doc.md +13 -1
  13. package/actSpecs.js +29 -5
  14. package/call.js +6 -5
  15. package/docker-compose.yml +8 -2
  16. package/docs/checkpoint-scanning.md +199 -0
  17. package/docs/standard-result-outcome.md +165 -0
  18. package/env.example +44 -10
  19. package/eslint.config.mjs +101 -0
  20. package/netWatch.js +372 -222
  21. package/package.json +46 -31
  22. package/pour/README.md +47 -0
  23. package/pour/pour.min.js +8 -0
  24. package/procs/actDo.js +808 -0
  25. package/procs/catalog.d.ts +17 -0
  26. package/procs/catalog.js +312 -221
  27. package/procs/catalog.ts +398 -0
  28. package/procs/checkpoint.js +110 -0
  29. package/procs/config.d.ts +35 -0
  30. package/procs/config.js +62 -0
  31. package/procs/dateTime.js +2 -1
  32. package/procs/doActs.js +442 -849
  33. package/procs/doTestAct.js +27 -121
  34. package/procs/flow.js +221 -0
  35. package/procs/generateRuleRegistry.js +94 -0
  36. package/procs/getSource.d.ts +26 -0
  37. package/procs/job.js +115 -1
  38. package/procs/launch.d.ts +40 -0
  39. package/procs/launch.js +239 -108
  40. package/procs/nu.d.ts +48 -0
  41. package/procs/scope.js +196 -0
  42. package/procs/shoot.d.ts +33 -0
  43. package/procs/standard.d.ts +18 -0
  44. package/procs/standard.js +83 -0
  45. package/procs/standard.ts +126 -0
  46. package/procs/testAct.js +145 -0
  47. package/procs/testaro.d.ts +20 -0
  48. package/procs/testaro.js +236 -189
  49. package/procs/testaro.ts +321 -0
  50. package/procs/userPath.js +126 -0
  51. package/procs/xPath.d.ts +4 -0
  52. package/procs/xPath.js +81 -69
  53. package/procs/xPath.ts +106 -0
  54. package/procs/xPathScript.d.ts +6 -0
  55. package/procs/xPathScript.js +70 -0
  56. package/run.js +3 -2
  57. package/surea11y/README.md +44 -0
  58. package/surea11y/surea11y.browser.js +14 -0
  59. package/testaro/adbID.d.ts +3 -0
  60. package/testaro/adbID.js +38 -41
  61. package/testaro/adbID.ts +66 -0
  62. package/testaro/allCapStyle.d.ts +3 -0
  63. package/testaro/allCapStyle.js +31 -34
  64. package/testaro/allCapStyle.ts +55 -0
  65. package/testaro/allCaps.d.ts +16 -0
  66. package/testaro/allCaps.js +179 -151
  67. package/testaro/allCaps.ts +228 -0
  68. package/testaro/allHidden.d.ts +13 -0
  69. package/testaro/allHidden.js +29 -30
  70. package/testaro/allHidden.ts +50 -0
  71. package/testaro/allSlanted.d.ts +3 -0
  72. package/testaro/allSlanted.js +30 -33
  73. package/testaro/allSlanted.ts +54 -0
  74. package/testaro/altScheme.d.ts +3 -0
  75. package/testaro/altScheme.js +27 -30
  76. package/testaro/altScheme.ts +50 -0
  77. package/testaro/attVal.d.ts +3 -0
  78. package/testaro/attVal.js +20 -21
  79. package/testaro/attVal.ts +52 -0
  80. package/testaro/autocomplete.d.ts +3 -0
  81. package/testaro/autocomplete.js +59 -75
  82. package/testaro/autocomplete.ts +101 -0
  83. package/testaro/bulk.d.ts +13 -0
  84. package/testaro/bulk.js +32 -33
  85. package/testaro/bulk.ts +55 -0
  86. package/testaro/buttonMenu.d.ts +9 -0
  87. package/testaro/buttonMenu.js +317 -319
  88. package/testaro/buttonMenu.ts +391 -0
  89. package/testaro/captionLoc.d.ts +3 -0
  90. package/testaro/captionLoc.js +17 -20
  91. package/testaro/captionLoc.ts +40 -0
  92. package/testaro/datalistRef.d.ts +3 -0
  93. package/testaro/datalistRef.js +33 -36
  94. package/testaro/datalistRef.ts +55 -0
  95. package/testaro/distortion.d.ts +3 -0
  96. package/testaro/distortion.js +57 -26
  97. package/testaro/distortion.ts +81 -0
  98. package/testaro/docType.d.ts +15 -0
  99. package/testaro/docType.js +25 -25
  100. package/testaro/docType.ts +45 -0
  101. package/testaro/dupAtt.d.ts +16 -0
  102. package/testaro/dupAtt.js +113 -104
  103. package/testaro/dupAtt.ts +144 -0
  104. package/testaro/elements.d.ts +6 -0
  105. package/testaro/elements.js +153 -153
  106. package/testaro/elements.ts +215 -0
  107. package/testaro/embAc.d.ts +3 -0
  108. package/testaro/embAc.js +19 -20
  109. package/testaro/embAc.ts +40 -0
  110. package/testaro/focAll.d.ts +13 -0
  111. package/testaro/focAll.js +185 -191
  112. package/testaro/focAll.ts +217 -0
  113. package/testaro/focAndOp.d.ts +3 -0
  114. package/testaro/focAndOp.js +100 -104
  115. package/testaro/focAndOp.ts +128 -0
  116. package/testaro/focInd.d.ts +3 -0
  117. package/testaro/focInd.js +64 -66
  118. package/testaro/focInd.ts +96 -0
  119. package/testaro/focVis.d.ts +3 -0
  120. package/testaro/focVis.js +28 -30
  121. package/testaro/focVis.ts +52 -0
  122. package/testaro/headEl.d.ts +10 -0
  123. package/testaro/headEl.js +61 -62
  124. package/testaro/headEl.ts +82 -0
  125. package/testaro/headingAmb.d.ts +3 -0
  126. package/testaro/headingAmb.js +54 -63
  127. package/testaro/headingAmb.ts +72 -0
  128. package/testaro/hovInd.d.ts +12 -0
  129. package/testaro/hovInd.js +163 -130
  130. package/testaro/hovInd.ts +199 -0
  131. package/testaro/hover.d.ts +3 -0
  132. package/testaro/hover.js +155 -126
  133. package/testaro/hover.ts +154 -0
  134. package/testaro/hr.d.ts +3 -0
  135. package/testaro/hr.js +14 -17
  136. package/testaro/hr.ts +36 -0
  137. package/testaro/imageLink.d.ts +3 -0
  138. package/testaro/imageLink.js +17 -20
  139. package/testaro/imageLink.ts +42 -0
  140. package/testaro/labClash.d.ts +3 -0
  141. package/testaro/labClash.js +31 -33
  142. package/testaro/labClash.ts +54 -0
  143. package/testaro/legendLoc.d.ts +3 -0
  144. package/testaro/legendLoc.js +17 -20
  145. package/testaro/legendLoc.ts +42 -0
  146. package/testaro/lineHeight.d.ts +3 -0
  147. package/testaro/lineHeight.js +43 -48
  148. package/testaro/lineHeight.ts +70 -0
  149. package/testaro/linkAmb.d.ts +7 -0
  150. package/testaro/linkAmb.js +79 -80
  151. package/testaro/linkAmb.ts +105 -0
  152. package/testaro/linkExt.d.ts +3 -0
  153. package/testaro/linkExt.js +13 -16
  154. package/testaro/linkExt.ts +35 -0
  155. package/testaro/linkOldAtt.d.ts +3 -0
  156. package/testaro/linkOldAtt.js +25 -28
  157. package/testaro/linkOldAtt.ts +48 -0
  158. package/testaro/linkTo.d.ts +3 -0
  159. package/testaro/linkTo.js +22 -22
  160. package/testaro/linkTo.ts +43 -0
  161. package/testaro/linkUl.d.ts +3 -0
  162. package/testaro/linkUl.js +30 -34
  163. package/testaro/linkUl.ts +54 -0
  164. package/testaro/miniText.d.ts +3 -0
  165. package/testaro/miniText.js +41 -44
  166. package/testaro/miniText.ts +68 -0
  167. package/testaro/motion.d.ts +10 -0
  168. package/testaro/motion.js +92 -96
  169. package/testaro/motion.ts +125 -0
  170. package/testaro/nonTable.d.ts +3 -0
  171. package/testaro/nonTable.js +39 -45
  172. package/testaro/nonTable.ts +66 -0
  173. package/testaro/optRoleSel.d.ts +3 -0
  174. package/testaro/optRoleSel.js +16 -19
  175. package/testaro/optRoleSel.ts +41 -0
  176. package/testaro/phOnly.d.ts +3 -0
  177. package/testaro/phOnly.js +18 -21
  178. package/testaro/phOnly.ts +43 -0
  179. package/testaro/pseudoP.d.ts +3 -0
  180. package/testaro/pseudoP.js +36 -38
  181. package/testaro/pseudoP.ts +59 -0
  182. package/testaro/radioSet.d.ts +3 -0
  183. package/testaro/radioSet.js +57 -59
  184. package/testaro/radioSet.ts +79 -0
  185. package/testaro/registry.d.ts +63 -0
  186. package/testaro/registry.js +67 -0
  187. package/testaro/registry.ts +141 -0
  188. package/testaro/role.d.ts +3 -0
  189. package/testaro/role.js +27 -29
  190. package/testaro/role.ts +53 -0
  191. package/testaro/secHeading.d.ts +3 -0
  192. package/testaro/secHeading.js +30 -33
  193. package/testaro/secHeading.ts +53 -0
  194. package/testaro/styleDiff.d.ts +25 -0
  195. package/testaro/styleDiff.js +248 -252
  196. package/testaro/styleDiff.ts +303 -0
  197. package/testaro/tabNav.d.ts +33 -0
  198. package/testaro/tabNav.js +272 -342
  199. package/testaro/tabNav.ts +454 -0
  200. package/testaro/targetsNear.d.ts +9 -0
  201. package/testaro/targetsNear.js +130 -132
  202. package/testaro/targetsNear.ts +160 -0
  203. package/testaro/textNodes.d.ts +6 -0
  204. package/testaro/textNodes.js +139 -135
  205. package/testaro/textNodes.ts +185 -0
  206. package/testaro/textSem.d.ts +3 -0
  207. package/testaro/textSem.js +25 -28
  208. package/testaro/textSem.ts +47 -0
  209. package/testaro/title.d.ts +9 -0
  210. package/testaro/title.js +16 -13
  211. package/testaro/title.ts +31 -0
  212. package/testaro/titledEl.d.ts +3 -0
  213. package/testaro/titledEl.js +15 -18
  214. package/testaro/titledEl.ts +38 -0
  215. package/testaro/zIndex.d.ts +3 -0
  216. package/testaro/zIndex.js +19 -22
  217. package/testaro/zIndex.ts +42 -0
  218. package/tests/alfa.d.ts +45 -0
  219. package/tests/alfa.js +138 -141
  220. package/tests/alfa.ts +214 -0
  221. package/tests/aslint.d.ts +33 -0
  222. package/tests/aslint.js +272 -249
  223. package/tests/aslint.ts +301 -0
  224. package/tests/axe.d.ts +27 -0
  225. package/tests/axe.js +199 -200
  226. package/tests/axe.ts +277 -0
  227. package/tests/ed11y.d.ts +28 -0
  228. package/tests/ed11y.js +141 -99
  229. package/tests/ed11y.ts +178 -0
  230. package/tests/htmlcs.d.ts +21 -0
  231. package/tests/htmlcs.js +174 -140
  232. package/tests/htmlcs.ts +181 -0
  233. package/tests/ibm.d.ts +52 -0
  234. package/tests/ibm.js +164 -166
  235. package/tests/ibm.ts +251 -0
  236. package/tests/nuVal.d.ts +13 -0
  237. package/tests/nuVal.js +107 -112
  238. package/tests/nuVal.ts +145 -0
  239. package/tests/nuVnu.d.ts +15 -0
  240. package/tests/nuVnu.js +141 -111
  241. package/tests/nuVnu.ts +144 -0
  242. package/tests/pour.d.ts +31 -0
  243. package/tests/pour.js +242 -0
  244. package/tests/pour.ts +273 -0
  245. package/tests/qualWeb.d.ts +39 -0
  246. package/tests/qualWeb.js +302 -272
  247. package/tests/qualWeb.ts +415 -0
  248. package/tests/surea11y.d.ts +33 -0
  249. package/tests/surea11y.js +288 -0
  250. package/tests/surea11y.ts +334 -0
  251. package/tests/testaro.d.ts +25 -0
  252. package/tests/testaro.js +745 -652
  253. package/tests/testaro.ts +862 -0
  254. package/tests/wave.d.ts +46 -0
  255. package/tests/wave.js +166 -177
  256. package/tests/wave.ts +252 -0
  257. package/tsconfig.json +17 -0
  258. package/types.d.ts +243 -0
  259. package/types.js +10 -0
  260. package/types.ts +376 -0
  261. package/validation/act/README.md +46 -0
  262. package/validation/act/capture.js +424 -0
  263. package/validation/act/chromium-issue-draft.md +66 -0
  264. package/validation/act/fp-triage-2026-08-22.md +86 -0
  265. package/validation/act/isolation-notes.md +159 -0
  266. package/validation/act/playwright-issue-draft.md +73 -0
  267. package/validation/act/propose-mappings.js +0 -0
  268. package/validation/act/repro-cdp-raw.js +105 -0
  269. package/validation/act/repro-metarefresh.js +65 -0
  270. package/validation/act/score.js +184 -0
  271. package/validation/act/stage3a-stress-report.md +69 -0
  272. package/validation/act/stage3b-mapping-proposals.md +94 -0
  273. package/validation/act/stage3b-triage-draft.md +138 -0
  274. package/validation/act/surea11y-track-a-2026-09-01.md +50 -0
  275. package/validation/executors/netWatch.js +180 -90
  276. package/validation/executors/test.js +17 -2
  277. package/validation/executors/tests.js +118 -10
  278. package/validation/jobs/reports/raw/260901T1000-surea11y-validation.json +964 -0
  279. package/validation/jobs/todo/240101T1200-simple-example.json +14 -6
  280. package/validation/jobs/todo/240101T1300-shoot-example.json +2 -1
  281. package/validation/jobs/todo/260821T1900-pour-validation.json +45 -0
  282. package/validation/jobs/todo/260901T1000-surea11y-validation.json +45 -0
  283. package/validation/knownFailures.json +1 -0
  284. package/validation/tests/jobProperties/adbID.json +27 -2
  285. package/validation/tests/jobProperties/{focOp.json → allCapStyle.json} +56 -53
  286. package/validation/tests/jobProperties/allCaps.json +25 -0
  287. package/validation/tests/jobProperties/allHidden.json +133 -13
  288. package/validation/tests/jobProperties/allSlanted.json +3 -3
  289. package/validation/tests/jobProperties/altScheme.json +23 -8
  290. package/validation/tests/jobProperties/attVal.json +57 -57
  291. package/validation/tests/jobProperties/autocomplete.json +11 -1
  292. package/validation/tests/jobProperties/bulk.json +6 -1
  293. package/validation/tests/jobProperties/buttonMenu.json +63 -42
  294. package/validation/tests/jobProperties/captionLoc.json +1 -6
  295. package/validation/tests/jobProperties/checkpoint-browser.json +401 -0
  296. package/validation/tests/jobProperties/checkpoint-page.json +397 -0
  297. package/validation/tests/jobProperties/checkpoint.json +395 -0
  298. package/validation/tests/jobProperties/datalistRef.json +20 -5
  299. package/validation/tests/jobProperties/distortion.json +28 -3
  300. package/validation/tests/jobProperties/docType.json +2 -2
  301. package/validation/tests/jobProperties/dupAtt.json +48 -33
  302. package/validation/tests/jobProperties/elements.json +28 -28
  303. package/validation/tests/jobProperties/embAc.json +36 -31
  304. package/validation/tests/jobProperties/focAndOp.json +284 -0
  305. package/validation/tests/jobProperties/focInd.json +34 -34
  306. package/validation/tests/jobProperties/focVis.json +1 -1
  307. package/validation/tests/jobProperties/hover.json +39 -37
  308. package/validation/tests/jobProperties/hr.json +13 -3
  309. package/validation/tests/jobProperties/imageLink.json +0 -5
  310. package/validation/tests/jobProperties/labClash.json +68 -33
  311. package/validation/tests/jobProperties/legendLoc.json +1 -6
  312. package/validation/tests/jobProperties/lineHeight.json +2 -2
  313. package/validation/tests/jobProperties/linkAmb.json +13 -18
  314. package/validation/tests/jobProperties/linkExt.json +1 -1
  315. package/validation/tests/jobProperties/linkOldAtt.json +12 -2
  316. package/validation/tests/jobProperties/linkTo.json +1 -1
  317. package/validation/tests/jobProperties/linkUl.json +65 -65
  318. package/validation/tests/jobProperties/miniText.json +7 -2
  319. package/validation/tests/jobProperties/motion.json +4 -50
  320. package/validation/tests/jobProperties/nonTable.json +48 -3
  321. package/validation/tests/jobProperties/optRoleSel.json +12 -2
  322. package/validation/tests/jobProperties/phOnly.json +6 -16
  323. package/validation/tests/jobProperties/pseudoP.json +17 -2
  324. package/validation/tests/jobProperties/radioSet.json +30 -30
  325. package/validation/tests/jobProperties/role.json +25 -5
  326. package/validation/tests/jobProperties/secHeading.json +26 -21
  327. package/validation/tests/jobProperties/styleDiff.json +35 -5
  328. package/validation/tests/jobProperties/tabNav.json +3 -1
  329. package/validation/tests/jobProperties/targetsNear.json +237 -0
  330. package/validation/tests/jobProperties/textNodes.json +29 -29
  331. package/validation/tests/jobProperties/textSem.json +26 -1
  332. package/validation/tests/jobProperties/title.json +12 -2
  333. package/validation/tests/jobProperties/titledEl.json +39 -9
  334. package/validation/tests/jobProperties/userPath.json +317 -0
  335. package/validation/tests/jobProperties/zIndex.json +40 -35
  336. package/validation/tests/targets/allCapStyle/index.html +26 -0
  337. package/validation/tests/targets/checkpoint/index.html +38 -0
  338. package/validation/tests/targets/datalistRef/index.html +1 -1
  339. package/validation/tests/targets/focAndOp/bad.html +29 -0
  340. package/validation/tests/targets/{focOp → focAndOp}/good.html +3 -1
  341. package/validation/tests/targets/focInd/bad.html +2 -1
  342. package/validation/tests/targets/headEl/index.html +10 -1
  343. package/validation/tests/targets/{targetSmall → targetsNear}/index.html +15 -1
  344. package/validation/tests/targets/userPath/index.html +42 -0
  345. package/validation/validateTest.js +61 -9
  346. package/.claude/settings.local.json +0 -11
  347. package/.eslintrc.json +0 -41
  348. package/htmlcs/.eslintrc.json +0 -67
  349. package/validation/tests/jobProperties/linkTitle.json +0 -127
  350. package/validation/tests/jobProperties/opFoc.json +0 -164
  351. package/validation/tests/jobProperties/targetSmall.json +0 -152
  352. package/validation/tests/jobProperties/targetTiny.json +0 -142
  353. package/validation/tests/targets/focOp/bad.html +0 -25
  354. package/validation/tests/targets/linkTitle/index.html +0 -24
  355. package/validation/tests/targets/opFoc/bad.html +0 -26
  356. package/validation/tests/targets/opFoc/good.html +0 -23
@@ -0,0 +1,165 @@
1
+ # Certainty in the standard result: the `outcome` field
2
+
3
+ **Status:** Phase A shipped in Testaro 78.1.0 (2026-09-01). Phases B–D are recommendations for
4
+ the Testilo fork and yra-monitor, and for a later Testaro major version.
5
+ **Companion:** yra-monitor `docs/plans/engine-candidacy-pipeline.md` (Stage-1 instance policy,
6
+ Stage-3b taxonomy mapping).
7
+
8
+ ## Why
9
+
10
+ Rule engines report two different things about a finding: how bad it is (impact) and whether
11
+ they are sure it is a defect (certainty). Every Testaro adapter used to fold certainty into
12
+ `ordinalSeverity`, and each did it differently:
13
+
14
+ | tool | uncertain native value | ordinal | certain native value | ordinal |
15
+ | --- | --- | --- | --- | --- |
16
+ | axe, pour, surea11y | incomplete / cantTell | 0–1 | violation / fail | 2–3 |
17
+ | htmlcs | Warning | 0 | Error | 2 |
18
+ | ibm | recommendation | 0 | violation and potential violation | 2 |
19
+ | alfa | cantTell (rule ID rewritten) | 0 | failed | 2 |
20
+ | aslint | warning | 1 | error | 2 |
21
+ | qualWeb act-rules | warning | 1 | failed | 3 |
22
+ | qualWeb best-practices | warning | 0 | failed | 1 |
23
+ | wave | alert | 0 | error, contrast | 3 |
24
+ | ed11y | dismissable warning | 0 | error | 2 |
25
+ | nuVal, nuVnu | info | 0 | error | 3 |
26
+
27
+ So severity 0 meant "definitely minor" for some tools and "possibly critical" for others, and
28
+ nothing downstream could recover certainty except by the heuristic "ordinal 2 or above means
29
+ asserted". The ACT validation harness had to read native results to score sensitivity and
30
+ specificity by certainty band. The Testilo issue classification (tic) grew 57 `*Risk` issues to
31
+ hold uncertain findings at weight 1, and its scorer counted an axe `incomplete` contrast finding
32
+ exactly like an asserted violation because it maps rule IDs only.
33
+
34
+ The two new candidate engines make the loss visible: pour separates `violations`, `incomplete`,
35
+ and `manualReview`; surea11y grades per occurrence (`fail` / `cantTell`) and publishes six
36
+ machine-readable `uncertainty` codes with a `needed` sentence saying what a reviewer must
37
+ determine.
38
+
39
+ ## The model
40
+
41
+ Four dimensions, kept separate:
42
+
43
+ | dimension | meaning | where it lives |
44
+ | --- | --- | --- |
45
+ | outcome (per instance) | did the engine assert a failure, or could it not tell | standard instance, set by the adapter |
46
+ | rule certainty (per rule) | is the check deterministic, or a heuristic that can only say "suspicious" | tic tool-rule entry, as an override |
47
+ | impact (per instance) | how bad for a user | `ordinalSeverity`, once it means impact only |
48
+ | issue weight (per issue) | severity of the defect class | tic `weight` |
49
+
50
+ Certainty exists at two levels because engines both under-assert (axe `incomplete`) and
51
+ over-assert (a heuristic reported as an error). The instance level is Testaro's job; the rule
52
+ level is the taxonomy's.
53
+
54
+ ## Phase A: Testaro 78.1.0 (shipped)
55
+
56
+ Every standard instance now has:
57
+
58
+ ```js
59
+ {
60
+ ruleID, what, ordinalSeverity, count, catalogIndex, // unchanged
61
+ outcome: 'failed' | 'cantTell', // required; ACT Rules Format vocabulary
62
+ uncertainty: 'not-computable' | 'judgement-required' | 'runtime-dependent'
63
+ | 'spec-only' | 'equivalence-unknown' | 'out-of-scope', // optional, cantTell only
64
+ needed: '<what a reviewer must determine>' // optional, cantTell only, ≤ 300 chars
65
+ }
66
+ ```
67
+
68
+ and `standardResult.outcomeTotals = {failed, cantTell}` (count-weighted).
69
+
70
+ - `procs/standard.ts` is the one place the shape is built (`getStandardResult`, `getInstance`,
71
+ `addInstance`, `pushInstance`). Adapters that compute `totals` from native counts (ibm, htmlcs,
72
+ ed11y, wave, testaro) use `pushInstance`; the rest use `addInstance`.
73
+ - `ordinalSeverity` and `totals` are unchanged for every tool. The golden diff on the pour and
74
+ surea11y validation jobs is identical after stripping the new fields.
75
+ - Per-tool mapping: axe/pour/surea11y violations → `failed`, incomplete → `cantTell`; htmlcs
76
+ Warning → `cantTell`; ibm potential violation, potential recommendation, and manual →
77
+ `cantTell`; alfa `cantTell` → `cantTell` (the adapter no longer rewrites the rule ID to
78
+ `cantTell` / `cantTellTextContrast` or prefixes `what`; r66 and r69 carry
79
+ `judgement-required`); aslint warning, qualWeb warning, wave alert, nuVal/nuVnu info →
80
+ `cantTell`; ed11y dismissable warning → `cantTell` with `judgement-required`.
81
+ - surea11y forwards `uncertainty.code` and `uncertainty.needed` (occurrence first, then check).
82
+ Its `confidence` value is dropped as non-portable.
83
+ - Testaro's own rules default to `failed`. An `allRules` entry may set `outcome` and
84
+ `uncertainty` (`allCaps` is `cantTell` / `judgement-required`, consistent with the earlier
85
+ ruling that AI confidence must not be encoded in `ordinalSeverity`). A violation description
86
+ may carry a prefix: `2:` severity only, `2?:` severity plus `cantTell`, `?:` `cantTell` at the
87
+ rule's default severity. `getBasicResult` accepts `outcome`, `uncertainty`, and `needed` on
88
+ each violation.
89
+ - `validation/act/capture.js` records `outcomeTotals` and per-instance `outcome` and
90
+ `uncertainty`, and marks a row as an error if any instance lacks a valid outcome.
91
+
92
+ Why `outcome` and not `certainty`: the ACT Rules Format and EARL already use `failed` /
93
+ `cantTell`, the ACT testcase feed the harness scores against uses `failed`, and a closed
94
+ two-value enum keeps consumer logic total. A graded `certainty` would invite scales no two
95
+ engines share and collide with surea11y's separate `confidence`.
96
+
97
+ Why `needed` is its own field: `what` is an identity key downstream (unique-issue rows, tsp
98
+ description sampling). Appending guidance to it would fracture identity across pages.
99
+
100
+ ## Phase B: Testilo fork (recommended)
101
+
102
+ Tool-rule entries in the tic gain optional properties; issues gain two:
103
+
104
+ ```js
105
+ tools: { htmlcs: { 'W-AAA.1_4_3.G18.BgImage': {
106
+ variable: false, quality: 1, what: '…',
107
+ outcome: 'cantTell', // override; 'cantTell' is the common case
108
+ uncertainty: 'not-computable', // rule-level default; the instance value wins
109
+ review: '…', // fallback "what to confirm" when the engine gives no `needed`
110
+ ignore: 'invalid' // replaces prose [invalid]/[irrelevant]/[duplicative]/[unreliable]
111
+ }}}
112
+ issue: { how: '<one imperative fix sentence>', group: 'landmarkNotTop' }
113
+ ```
114
+
115
+ - Precedence: `rule.outcome` > `instance.outcome` > legacy inference > `failed`. Legacy
116
+ inference (reports without `outcome`) is per tool: axe, pour, surea11y, htmlcs, ibm, wave,
117
+ qualWeb → `ordinalSeverity >= 2 ? failed : cantTell`; alfa → rule ID starts with `cantTell`;
118
+ testaro, ed11y, aslint, nuVal, nuVnu → `failed`.
119
+ - `[speculative]` becomes `outcome: 'cantTell'`; the other bracket tags become `ignore`. The
120
+ `ignorable` pseudo-issue dissolves into per-rule `ignore`. A loader assertion rejects any
121
+ `what` still carrying a bracket tag.
122
+ - Consolidate the 57 `*Risk` issues: merge into the base issue when one exists with the same fix
123
+ (7 name twins plus about 11 semantic twins such as contrastRisk → contrastAA/AAA by level);
124
+ rename (drop `Risk`) when the issue is the sole home of a defect class with a concrete fix
125
+ (pseudoHeadingRisk → pseudoHeading, which already holds axe `p-as-heading` and takes pour's
126
+ at `failed`; eventKeyboardRisk → eventKeyboard; labelConfusionRisk → labelPlacement with every
127
+ rule `cantTell` / `judgement-required`); keep three page-environment advisories
128
+ (applicationRisk, browserSupportRisk, noScriptRisk) with every rule `cantTell`. Export a
129
+ `migrations` map (`{contrastRisk: 'contrastAA', …}`) for downstream issue-ID rewrites.
130
+ - Scoring: `cantTellWeight = 0.25` per instance inside the quality-weighted count (a weight-1
131
+ Risk issue merged into a weight-4 base is score-neutral). Element-aware dedup: an element's
132
+ outcome is `failed` if any tool says so, corroborated when more than one does;
133
+ `effectiveCount = max(old per-tool max with the factor applied, element-union count)`.
134
+ Output stays additive (`instanceCounts` numeric; add `outcomeCounts`, `elementCounts`,
135
+ `details.elements`; `details.element` byte-identical).
136
+ - Granularity principle: one tic issue = one remediation class = one WCAG success criterion ×
137
+ one fix. `ruleID` and `what` carry the diagnosis; certainty is never a reason to split an
138
+ issue. Families get `group`; element-conditioned splits (pour `link-name` → image link vs text
139
+ link) are done in the adapter with a `.`-suffixed faceted rule ID, two tic entries each.
140
+
141
+ ## Phase C: yra-monitor (recommended)
142
+
143
+ Types, `tic-manager` `resolveOutcome`, scoring-service passthrough, standardized rows and DB
144
+ columns (`outcome`, `uncertainty`, `needed`) with a promote-only conflict rule (`failed` wins),
145
+ issue-ID rewrite from `migrations`, a "Needs review" badge and filter, and for `cantTell` rows
146
+ the text `instance.needed ?? rule.review ?? 'Manual review required'` under a "To confirm"
147
+ heading.
148
+
149
+ ## Phase D: Testaro 79 (recommended)
150
+
151
+ Redefine `ordinalSeverity` as impact only: 0 minor, 1 moderate, 2 serious, 3 critical, which is
152
+ what yra-monitor already labels it as. `totals` keeps its shape but its composition changes
153
+ (an axe incomplete + critical finding moves from `totals[1]` to `totals[3]`). Safe only after
154
+ Phases B and C, when every consumer reads `outcome`.
155
+
156
+ ## Open decisions
157
+
158
+ 1. `cantTellWeight = 0.25`: confirm against Stage-4 precision on surea11y's `cantTell` band.
159
+ 2. The semantic Risk merges need a "same fix?" pass; videoCaptionRisk → videoNoText and
160
+ fieldSetRisk → fieldSetMissing are the least certain.
161
+ 3. Weights for renamed heuristic issues once they can carry a `failed` band.
162
+ 4. The alfa rule-ID change is visible to the current Testilo now: r66/r69 `cantTell` instances
163
+ map to contrastAAA/contrastAA at full weight until the scorer reads `outcome`. Pin Testaro
164
+ 78.1 in the worker only together with the Phase-B Testilo.
165
+ 5. Whether `unique_issues.severity` should roll up (`GREATEST`) on conflict.
package/env.example CHANGED
@@ -2,8 +2,6 @@
2
2
  WAVE_KEY=__placeholder__
3
3
  # You can get an Anthropic API key at https://console.anthropic.com/.
4
4
  ANTHROPIC_API_KEY=__placeholder__
5
- # Name to identify this Testaro instance to a server.
6
- AGENT=__placeholder__
7
5
  # Whether to make the browser visible (normally false).
8
6
  HEADED_BROWSER=false
9
7
  # Whether to output even forked-job logging to the primary log (normally false).
@@ -12,23 +10,44 @@ DEBUG=false
12
10
  WAITS=0
13
11
  # See https://nodejs.org/api/cli.html#options for all permitted options.
14
12
  NODE_OPTIONS='--trace-uncaught --trace-warnings'
15
- # Suppresses a routine warning from QualWeb.
13
+ # Whether to suppress a routine warning from QualWeb.
16
14
  PUPPETEER_DISABLE_HEADLESS_WARNING=true
17
- # Replace the next 2 placeholders with http://localhost:3000 if Kilotest and Testaro are on the same host or the URL of the server (e.g., https://kilotest.com) if they are on different hosts.
18
- # URL to poll for available jobs when watching the network.
19
- NETWATCH_URL_JOB=__placeholder__/api/testaro-agent/job
20
- # URL to report results to when watching the network.
21
- NETWATCH_URL_REPORT=__placeholder__/api/testaro-agent/report
22
- # Password of this Testaro agent
23
- NETWATCH_URL_AUTH=__placeholder__
24
15
  # Directory (relative to project root) to watch for jobs.
25
16
  JOBDIR=__placeholder__
26
17
  # Directory (relative to project root) to write reports to when watching a directory for jobs.
27
18
  REPORTDIR=__placeholder__
28
19
  # Multiplier for time limits (normally 1).
29
20
  TIMEOUT_MULTIPLIER=1
21
+ # Default isolation of test acts when a job does not specify one: process (a child process and
22
+ # browser per test act), browser (one browser per job, a fresh context per test act), or page
23
+ # (test acts share the live page of the current checkpoint). See docs/checkpoint-scanning.md.
24
+ ISOLATION=process
30
25
  # Whether to abort the job when launch retries are exhausted or a test act crashes (default false).
31
26
  ABORT_ASSERTIVELY=false
27
+
28
+ # Deployment options. A job property of the same meaning overrides each of these.
29
+
30
+ # Load state a navigation waits for before tools run: networkidle (default), load, or
31
+ # domcontentloaded. Retries relax it one step. networkidle never arrives on pages whose
32
+ # network never quiets (beacons, polling), so a deployment scanning such pages may prefer load.
33
+ NAV_WAIT_UNTIL=networkidle
34
+ # Navigation time limit in milliseconds (default 10000).
35
+ NAV_TIMEOUT=10000
36
+ # Whether a 4xx response (other than 408 and 429) ends launch retries at once (default false).
37
+ NAV_FAIL_FAST_4XX=false
38
+ # Scanner identity sent as the X-YRA-Scanner request header, so firewalls can recognize the
39
+ # scanner by a stable value (default none; jobs may set scannerId).
40
+ SCANNER_ID=__placeholder__
41
+ # Whether to scroll the full page after navigation so lazily loaded content is present before
42
+ # cataloguing, imaging, and each tool (default false; jobs may set scroll).
43
+ PRESCAN_SCROLL=false
44
+ # Launch retries per rule of the testaro tool, which relaunches per contaminating rule
45
+ # (default 2; raise for non-Chromium browsers, which navigate flakily on relaunch).
46
+ TESTARO_RULE_RETRIES=2
47
+ # Whether the qualWeb tool's browser runs stealth evasions and blocks ads and trackers
48
+ # (default true; a qualWeb test act may set stealth and adBlock).
49
+ QUALWEB_STEALTH=true
50
+ QUALWEB_ADBLOCK=true
32
51
  # URL of any non-default (e.g., self-hosted) Nu Html Checker API (see ghcr.io/validator/validator).
33
52
  TESTARO_NU_URL=__placeholder__
34
53
  # Whether to launch the Playwright chromium browser without its sandbox (normally false).
@@ -37,6 +56,21 @@ TESTARO_NU_URL=__placeholder__
37
56
  # or run containers with a seccomp profile that permits user-namespace cloning.
38
57
  TESTARO_CHROMIUM_NO_SANDBOX=false
39
58
 
59
+ # netWatch variables
60
+
61
+ # Replace the next 2 placeholders with the URL of the server (e.g., http://localhost:3000 or https://kilotest.com), including the path required by the server.
62
+ # URL to poll for available jobs.
63
+ NETWATCH_URL_JOB=__placeholder__
64
+ # URL to send a job report.
65
+ NETWATCH_URL_REPORT=__placeholder__
66
+ # Type of authentication (none, pathBody, or header) required by the server.
67
+ NETWATCH_AUTH_TYPE=__placeholder__
68
+ # ID of this instance. Recorded in reports as sources.agent and used by header
69
+ # authentication (where it must not contain a colon).
70
+ NETWATCH_WORKER_ID=__placeholder__
71
+ # Password of this instance. Required when NETWATCH_AUTH_TYPE is pathBody or header.
72
+ NETWATCH_WORKER_SECRET=__placeholder__
73
+
40
74
  ## License
41
75
 
42
76
  # © 2021–2025 CVS Health and/or one of its affiliates. All rights reserved.
@@ -0,0 +1,101 @@
1
+ /*
2
+ © 2026 Jeff Witt.
3
+
4
+ Licensed under the MIT License. See LICENSE file at the project root or
5
+ https://opensource.org/license/mit/ for details.
6
+
7
+ SPDX-License-Identifier: MIT
8
+ */
9
+
10
+ /*
11
+ eslint.config.mjs
12
+ Flat ESLint configuration, replacing .eslintrc.json (unsupported since ESLint 9).
13
+ */
14
+
15
+ // IMPORTS
16
+
17
+ import js from '@eslint/js';
18
+ import globals from 'globals';
19
+ import {defineConfig, globalIgnores} from 'eslint/config';
20
+
21
+ // CONFIGURATION
22
+
23
+ export default defineConfig([
24
+ globalIgnores([
25
+ // Build output.
26
+ 'dist/',
27
+ // Vendored HTML CodeSniffer bundle; not to be reformatted.
28
+ 'htmlcs/HTMLCS.js',
29
+ // Vendored Editoria11y bundles.
30
+ 'ed11y/',
31
+ // Vendored SureA11y standalone browser bundle (MPL-2.0; not to be modified).
32
+ 'surea11y/surea11y.browser.js',
33
+ // Vendored Pour Engine bundle, built with esbuild (see pour/README.md).
34
+ 'pour/pour.min.js',
35
+ // Files emitted by tsc from TypeScript sources (issue #73); lint the .ts sources instead.
36
+ 'types.js',
37
+ 'procs/catalog.js',
38
+ 'procs/standard.js',
39
+ 'procs/testaro.js',
40
+ 'procs/xPath.js',
41
+ 'testaro/*.js',
42
+ 'tests/*.js',
43
+ '**/*.d.ts',
44
+ // Validation fixtures, some of which are intentionally defective.
45
+ 'validation/tests/targets/'
46
+ ]),
47
+ {
48
+ files: ['**/*.js'],
49
+ extends: [js.configs.recommended],
50
+ languageOptions: {
51
+ ecmaVersion: 2021,
52
+ sourceType: 'commonjs',
53
+ globals: {
54
+ ...globals.browser,
55
+ ...globals.node
56
+ }
57
+ },
58
+ rules: {
59
+ indent: [
60
+ 'error',
61
+ 2,
62
+ {
63
+ MemberExpression: 0,
64
+ ObjectExpression: 'first'
65
+ }
66
+ ],
67
+ 'linebreak-style': [
68
+ 'error',
69
+ 'unix'
70
+ ],
71
+ quotes: [
72
+ 'error',
73
+ 'single'
74
+ ],
75
+ semi: [
76
+ 'error',
77
+ 'always'
78
+ ],
79
+ 'no-use-before-define': [
80
+ 'error'
81
+ ],
82
+ 'brace-style': [
83
+ 'error',
84
+ 'stroustrup'
85
+ ],
86
+ /*
87
+ Transitional demotions to warnings, so linting can gate changes now.
88
+ These rules have pre-existing violations, some of them latent defects.
89
+ Each is to be restored to an error once its violations are repaired.
90
+ */
91
+ 'no-async-promise-executor': 'warn',
92
+ 'no-const-assign': 'warn',
93
+ 'no-constant-binary-expression': 'warn',
94
+ 'no-empty': 'warn',
95
+ 'no-undef': 'warn',
96
+ 'no-unused-vars': 'warn',
97
+ 'no-use-before-define': 'warn',
98
+ 'no-useless-assignment': 'warn'
99
+ }
100
+ }
101
+ ]);