@sun-asterisk/sungen 3.2.32 → 3.2.34-beta.1

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 (503) hide show
  1. package/dist/cli/commands/audit.d.ts +5 -0
  2. package/dist/cli/commands/audit.d.ts.map +1 -1
  3. package/dist/cli/commands/audit.js +64 -11
  4. package/dist/cli/commands/audit.js.map +1 -1
  5. package/dist/cli/commands/capability.d.ts.map +1 -1
  6. package/dist/cli/commands/capability.js +40 -18
  7. package/dist/cli/commands/capability.js.map +1 -1
  8. package/dist/cli/commands/changed.d.ts.map +1 -1
  9. package/dist/cli/commands/changed.js +2 -3
  10. package/dist/cli/commands/changed.js.map +1 -1
  11. package/dist/cli/commands/dashboard.d.ts.map +1 -1
  12. package/dist/cli/commands/dashboard.js +2 -28
  13. package/dist/cli/commands/dashboard.js.map +1 -1
  14. package/dist/cli/commands/defect.d.ts +7 -0
  15. package/dist/cli/commands/defect.d.ts.map +1 -0
  16. package/dist/cli/commands/defect.js +68 -0
  17. package/dist/cli/commands/defect.js.map +1 -0
  18. package/dist/cli/commands/delivery.d.ts.map +1 -1
  19. package/dist/cli/commands/delivery.js +113 -59
  20. package/dist/cli/commands/delivery.js.map +1 -1
  21. package/dist/cli/commands/generate.d.ts.map +1 -1
  22. package/dist/cli/commands/generate.js +14 -7
  23. package/dist/cli/commands/generate.js.map +1 -1
  24. package/dist/cli/commands/results-merge.d.ts +9 -0
  25. package/dist/cli/commands/results-merge.d.ts.map +1 -1
  26. package/dist/cli/commands/results-merge.js +9 -12
  27. package/dist/cli/commands/results-merge.js.map +1 -1
  28. package/dist/cli/commands/results-sanitize.d.ts.map +1 -1
  29. package/dist/cli/commands/results-sanitize.js +2 -13
  30. package/dist/cli/commands/results-sanitize.js.map +1 -1
  31. package/dist/cli/commands/select.d.ts +12 -0
  32. package/dist/cli/commands/select.d.ts.map +1 -0
  33. package/dist/cli/commands/select.js +122 -0
  34. package/dist/cli/commands/select.js.map +1 -0
  35. package/dist/cli/commands/triage.d.ts +7 -0
  36. package/dist/cli/commands/triage.d.ts.map +1 -0
  37. package/dist/cli/commands/triage.js +98 -0
  38. package/dist/cli/commands/triage.js.map +1 -0
  39. package/dist/cli/commands/update.d.ts.map +1 -1
  40. package/dist/cli/commands/update.js +3 -0
  41. package/dist/cli/commands/update.js.map +1 -1
  42. package/dist/cli/commands/viewpoint.d.ts +7 -0
  43. package/dist/cli/commands/viewpoint.d.ts.map +1 -0
  44. package/dist/cli/commands/viewpoint.js +70 -0
  45. package/dist/cli/commands/viewpoint.js.map +1 -0
  46. package/dist/cli/index.js +13 -2
  47. package/dist/cli/index.js.map +1 -1
  48. package/dist/dashboard/snapshot-builder.d.ts.map +1 -1
  49. package/dist/dashboard/snapshot-builder.js +6 -10
  50. package/dist/dashboard/snapshot-builder.js.map +1 -1
  51. package/dist/dashboard/templates/index.html +1 -1
  52. package/dist/dashboard/types.d.ts +1 -0
  53. package/dist/dashboard/types.d.ts.map +1 -1
  54. package/dist/exporters/csv-exporter.d.ts +4 -0
  55. package/dist/exporters/csv-exporter.d.ts.map +1 -1
  56. package/dist/exporters/csv-exporter.js +12 -11
  57. package/dist/exporters/csv-exporter.js.map +1 -1
  58. package/dist/exporters/feature-parser.d.ts +29 -0
  59. package/dist/exporters/feature-parser.d.ts.map +1 -1
  60. package/dist/exporters/feature-parser.js +44 -1
  61. package/dist/exporters/feature-parser.js.map +1 -1
  62. package/dist/exporters/json-exporter.d.ts.map +1 -1
  63. package/dist/exporters/json-exporter.js +7 -0
  64. package/dist/exporters/json-exporter.js.map +1 -1
  65. package/dist/exporters/locale-variants.d.ts +7 -1
  66. package/dist/exporters/locale-variants.d.ts.map +1 -1
  67. package/dist/exporters/locale-variants.js +23 -16
  68. package/dist/exporters/locale-variants.js.map +1 -1
  69. package/dist/exporters/manual-hybrid-oracle.d.ts +54 -0
  70. package/dist/exporters/manual-hybrid-oracle.d.ts.map +1 -0
  71. package/dist/exporters/manual-hybrid-oracle.js +114 -0
  72. package/dist/exporters/manual-hybrid-oracle.js.map +1 -0
  73. package/dist/exporters/matrix/build.d.ts.map +1 -1
  74. package/dist/exporters/matrix/build.js +68 -19
  75. package/dist/exporters/matrix/build.js.map +1 -1
  76. package/dist/exporters/matrix/carry-manual-results.d.ts +89 -0
  77. package/dist/exporters/matrix/carry-manual-results.d.ts.map +1 -0
  78. package/dist/exporters/matrix/carry-manual-results.js +302 -0
  79. package/dist/exporters/matrix/carry-manual-results.js.map +1 -0
  80. package/dist/exporters/matrix/export.d.ts +9 -1
  81. package/dist/exporters/matrix/export.d.ts.map +1 -1
  82. package/dist/exporters/matrix/export.js +21 -3
  83. package/dist/exporters/matrix/export.js.map +1 -1
  84. package/dist/exporters/matrix/gates.js +6 -0
  85. package/dist/exporters/matrix/gates.js.map +1 -1
  86. package/dist/exporters/matrix/render-csv.js +1 -1
  87. package/dist/exporters/matrix/render-csv.js.map +1 -1
  88. package/dist/exporters/matrix/render-testcase-sheet.d.ts.map +1 -1
  89. package/dist/exporters/matrix/render-testcase-sheet.js +10 -4
  90. package/dist/exporters/matrix/render-testcase-sheet.js.map +1 -1
  91. package/dist/exporters/matrix/render-xlsx.d.ts.map +1 -1
  92. package/dist/exporters/matrix/render-xlsx.js +3 -0
  93. package/dist/exporters/matrix/render-xlsx.js.map +1 -1
  94. package/dist/exporters/matrix/types.d.ts +13 -1
  95. package/dist/exporters/matrix/types.d.ts.map +1 -1
  96. package/dist/exporters/matrix/types.js.map +1 -1
  97. package/dist/exporters/matrix/wording.d.ts +8 -1
  98. package/dist/exporters/matrix/wording.d.ts.map +1 -1
  99. package/dist/exporters/matrix/wording.js +37 -2
  100. package/dist/exporters/matrix/wording.js.map +1 -1
  101. package/dist/exporters/playwright-report-parser.d.ts.map +1 -1
  102. package/dist/exporters/playwright-report-parser.js +1 -0
  103. package/dist/exporters/playwright-report-parser.js.map +1 -1
  104. package/dist/exporters/run-environment.d.ts +32 -0
  105. package/dist/exporters/run-environment.d.ts.map +1 -0
  106. package/dist/exporters/run-environment.js +125 -0
  107. package/dist/exporters/run-environment.js.map +1 -0
  108. package/dist/exporters/scenario-merger.d.ts +18 -0
  109. package/dist/exporters/scenario-merger.d.ts.map +1 -1
  110. package/dist/exporters/scenario-merger.js +49 -3
  111. package/dist/exporters/scenario-merger.js.map +1 -1
  112. package/dist/exporters/test-data-resolver.d.ts +0 -4
  113. package/dist/exporters/test-data-resolver.d.ts.map +1 -1
  114. package/dist/exporters/test-data-resolver.js +0 -7
  115. package/dist/exporters/test-data-resolver.js.map +1 -1
  116. package/dist/exporters/types.d.ts +5 -0
  117. package/dist/exporters/types.d.ts.map +1 -1
  118. package/dist/exporters/xlsx-exporter.d.ts +2 -0
  119. package/dist/exporters/xlsx-exporter.d.ts.map +1 -1
  120. package/dist/exporters/xlsx-exporter.js +7 -2
  121. package/dist/exporters/xlsx-exporter.js.map +1 -1
  122. package/dist/generators/gherkin-parser/index.d.ts +11 -4
  123. package/dist/generators/gherkin-parser/index.d.ts.map +1 -1
  124. package/dist/generators/gherkin-parser/index.js +49 -19
  125. package/dist/generators/gherkin-parser/index.js.map +1 -1
  126. package/dist/generators/test-generator/adapters/adapter-interface.d.ts +4 -0
  127. package/dist/generators/test-generator/adapters/adapter-interface.d.ts.map +1 -1
  128. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/reinstall-app-action.hbs +2 -2
  129. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/label-value-assertion.hbs +8 -2
  130. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/visible-with-role-variable-assertion.hbs +7 -3
  131. package/dist/generators/test-generator/adapters/appium/templates/test-file.hbs +68 -4
  132. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/click-select-action.hbs +1 -1
  133. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/select-action.hbs +1 -1
  134. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/label-value-assertion.hbs +7 -1
  135. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-role-variable-assertion.hbs +8 -4
  136. package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/pick-option.hbs +13 -0
  137. package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/url-assertion.hbs +5 -1
  138. package/dist/generators/test-generator/adapters/playwright/templates/test-file.hbs +16 -0
  139. package/dist/generators/test-generator/code-generator.d.ts +2 -1
  140. package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
  141. package/dist/generators/test-generator/code-generator.js +90 -5
  142. package/dist/generators/test-generator/code-generator.js.map +1 -1
  143. package/dist/generators/test-generator/diagnostics.d.ts +36 -5
  144. package/dist/generators/test-generator/diagnostics.d.ts.map +1 -1
  145. package/dist/generators/test-generator/diagnostics.js +35 -4
  146. package/dist/generators/test-generator/diagnostics.js.map +1 -1
  147. package/dist/generators/test-generator/patterns/index.d.ts +12 -2
  148. package/dist/generators/test-generator/patterns/index.d.ts.map +1 -1
  149. package/dist/generators/test-generator/patterns/index.js +15 -9
  150. package/dist/generators/test-generator/patterns/index.js.map +1 -1
  151. package/dist/generators/test-generator/patterns/types.d.ts +15 -0
  152. package/dist/generators/test-generator/patterns/types.d.ts.map +1 -1
  153. package/dist/generators/test-generator/patterns/with-parent-scope.d.ts +5 -0
  154. package/dist/generators/test-generator/patterns/with-parent-scope.d.ts.map +1 -1
  155. package/dist/generators/test-generator/patterns/with-parent-scope.js +6 -0
  156. package/dist/generators/test-generator/patterns/with-parent-scope.js.map +1 -1
  157. package/dist/generators/test-generator/step-mapper.d.ts +46 -0
  158. package/dist/generators/test-generator/step-mapper.d.ts.map +1 -1
  159. package/dist/generators/test-generator/step-mapper.js +84 -9
  160. package/dist/generators/test-generator/step-mapper.js.map +1 -1
  161. package/dist/generators/test-generator/utils/data-resolver.d.ts +25 -0
  162. package/dist/generators/test-generator/utils/data-resolver.d.ts.map +1 -1
  163. package/dist/generators/test-generator/utils/data-resolver.js +39 -8
  164. package/dist/generators/test-generator/utils/data-resolver.js.map +1 -1
  165. package/dist/generators/test-generator/utils/selector-entry-fields.d.ts.map +1 -1
  166. package/dist/generators/test-generator/utils/selector-entry-fields.js +1 -0
  167. package/dist/generators/test-generator/utils/selector-entry-fields.js.map +1 -1
  168. package/dist/generators/test-generator/utils/selector-resolver.d.ts +37 -4
  169. package/dist/generators/test-generator/utils/selector-resolver.d.ts.map +1 -1
  170. package/dist/generators/test-generator/utils/selector-resolver.js +212 -79
  171. package/dist/generators/test-generator/utils/selector-resolver.js.map +1 -1
  172. package/dist/harness/audit.d.ts +3 -0
  173. package/dist/harness/audit.d.ts.map +1 -1
  174. package/dist/harness/audit.js +60 -19
  175. package/dist/harness/audit.js.map +1 -1
  176. package/dist/harness/capability.d.ts +7 -1
  177. package/dist/harness/capability.d.ts.map +1 -1
  178. package/dist/harness/capability.js +15 -12
  179. package/dist/harness/capability.js.map +1 -1
  180. package/dist/harness/catalog/universal-viewpoints.yaml +5 -5
  181. package/dist/harness/config-file.d.ts +17 -0
  182. package/dist/harness/config-file.d.ts.map +1 -0
  183. package/dist/harness/config-file.js +100 -0
  184. package/dist/harness/config-file.js.map +1 -0
  185. package/dist/harness/counted-assertions.d.ts +2 -0
  186. package/dist/harness/counted-assertions.d.ts.map +1 -0
  187. package/dist/harness/counted-assertions.js +38 -0
  188. package/dist/harness/counted-assertions.js.map +1 -0
  189. package/dist/harness/data-driven-lint.d.ts.map +1 -1
  190. package/dist/harness/data-driven-lint.js +69 -27
  191. package/dist/harness/data-driven-lint.js.map +1 -1
  192. package/dist/harness/defect-draft.d.ts +14 -0
  193. package/dist/harness/defect-draft.d.ts.map +1 -0
  194. package/dist/harness/defect-draft.js +143 -0
  195. package/dist/harness/defect-draft.js.map +1 -0
  196. package/dist/harness/defects.d.ts +24 -0
  197. package/dist/harness/defects.d.ts.map +1 -0
  198. package/dist/harness/defects.js +118 -0
  199. package/dist/harness/defects.js.map +1 -0
  200. package/dist/harness/depth-lint.d.ts.map +1 -1
  201. package/dist/harness/depth-lint.js +2 -1
  202. package/dist/harness/depth-lint.js.map +1 -1
  203. package/dist/harness/flow-check.d.ts.map +1 -1
  204. package/dist/harness/flow-check.js +6 -2
  205. package/dist/harness/flow-check.js.map +1 -1
  206. package/dist/harness/keyword-match.d.ts +59 -0
  207. package/dist/harness/keyword-match.d.ts.map +1 -0
  208. package/dist/harness/keyword-match.js +86 -0
  209. package/dist/harness/keyword-match.js.map +1 -0
  210. package/dist/harness/manifest.d.ts.map +1 -1
  211. package/dist/harness/manifest.js +2 -2
  212. package/dist/harness/manifest.js.map +1 -1
  213. package/dist/harness/next-step.d.ts +2 -4
  214. package/dist/harness/next-step.d.ts.map +1 -1
  215. package/dist/harness/next-step.js +50 -5
  216. package/dist/harness/next-step.js.map +1 -1
  217. package/dist/harness/parse.d.ts +45 -0
  218. package/dist/harness/parse.d.ts.map +1 -1
  219. package/dist/harness/parse.js +142 -24
  220. package/dist/harness/parse.js.map +1 -1
  221. package/dist/harness/perf.d.ts +7 -1
  222. package/dist/harness/perf.d.ts.map +1 -1
  223. package/dist/harness/perf.js +13 -10
  224. package/dist/harness/perf.js.map +1 -1
  225. package/dist/harness/quality-gates.d.ts +9 -2
  226. package/dist/harness/quality-gates.d.ts.map +1 -1
  227. package/dist/harness/quality-gates.js +22 -8
  228. package/dist/harness/quality-gates.js.map +1 -1
  229. package/dist/harness/query-catalog.js +0 -0
  230. package/dist/harness/query-catalog.js.map +1 -1
  231. package/dist/harness/read-text.d.ts +21 -0
  232. package/dist/harness/read-text.d.ts.map +1 -1
  233. package/dist/harness/read-text.js +32 -1
  234. package/dist/harness/read-text.js.map +1 -1
  235. package/dist/harness/script-check.d.ts.map +1 -1
  236. package/dist/harness/script-check.js +7 -1
  237. package/dist/harness/script-check.js.map +1 -1
  238. package/dist/harness/secret-scan.d.ts +27 -1
  239. package/dist/harness/secret-scan.d.ts.map +1 -1
  240. package/dist/harness/secret-scan.js +57 -4
  241. package/dist/harness/secret-scan.js.map +1 -1
  242. package/dist/harness/select-by-ids.d.ts +31 -0
  243. package/dist/harness/select-by-ids.d.ts.map +1 -0
  244. package/dist/harness/select-by-ids.js +106 -0
  245. package/dist/harness/select-by-ids.js.map +1 -0
  246. package/dist/harness/sensors.d.ts +20 -1
  247. package/dist/harness/sensors.d.ts.map +1 -1
  248. package/dist/harness/sensors.js +133 -39
  249. package/dist/harness/sensors.js.map +1 -1
  250. package/dist/harness/spec-branches.d.ts +0 -18
  251. package/dist/harness/spec-branches.d.ts.map +1 -1
  252. package/dist/harness/spec-branches.js +24 -3
  253. package/dist/harness/spec-branches.js.map +1 -1
  254. package/dist/harness/spec-coverage.d.ts.map +1 -1
  255. package/dist/harness/spec-coverage.js +14 -4
  256. package/dist/harness/spec-coverage.js.map +1 -1
  257. package/dist/harness/triage-signals.d.ts +20 -0
  258. package/dist/harness/triage-signals.d.ts.map +1 -0
  259. package/dist/harness/triage-signals.js +30 -0
  260. package/dist/harness/triage-signals.js.map +1 -0
  261. package/dist/harness/triage-unit.d.ts +23 -0
  262. package/dist/harness/triage-unit.d.ts.map +1 -0
  263. package/dist/harness/triage-unit.js +142 -0
  264. package/dist/harness/triage-unit.js.map +1 -0
  265. package/dist/harness/triage.d.ts +28 -0
  266. package/dist/harness/triage.d.ts.map +1 -0
  267. package/dist/harness/triage.js +99 -0
  268. package/dist/harness/triage.js.map +1 -0
  269. package/dist/harness/ui-inventory.d.ts +40 -0
  270. package/dist/harness/ui-inventory.d.ts.map +1 -0
  271. package/dist/harness/ui-inventory.js +191 -0
  272. package/dist/harness/ui-inventory.js.map +1 -0
  273. package/dist/harness/viewpoint-baseline.d.ts.map +1 -1
  274. package/dist/harness/viewpoint-baseline.js +7 -1
  275. package/dist/harness/viewpoint-baseline.js.map +1 -1
  276. package/dist/harness/viewpoint-draft-header.d.ts +7 -0
  277. package/dist/harness/viewpoint-draft-header.d.ts.map +1 -0
  278. package/dist/harness/viewpoint-draft-header.js +100 -0
  279. package/dist/harness/viewpoint-draft-header.js.map +1 -0
  280. package/dist/harness/viewpoint-ledger.d.ts +13 -3
  281. package/dist/harness/viewpoint-ledger.d.ts.map +1 -1
  282. package/dist/harness/viewpoint-ledger.js +106 -19
  283. package/dist/harness/viewpoint-ledger.js.map +1 -1
  284. package/dist/harness/viewpoint-mode.d.ts +9 -0
  285. package/dist/harness/viewpoint-mode.d.ts.map +1 -0
  286. package/dist/harness/viewpoint-mode.js +52 -0
  287. package/dist/harness/viewpoint-mode.js.map +1 -0
  288. package/dist/harness/viewpoint-priority.d.ts +19 -0
  289. package/dist/harness/viewpoint-priority.d.ts.map +1 -0
  290. package/dist/harness/viewpoint-priority.js +36 -0
  291. package/dist/harness/viewpoint-priority.js.map +1 -0
  292. package/dist/harness/viewpoint-review-open.d.ts +6 -0
  293. package/dist/harness/viewpoint-review-open.d.ts.map +1 -0
  294. package/dist/harness/viewpoint-review-open.js +90 -0
  295. package/dist/harness/viewpoint-review-open.js.map +1 -0
  296. package/dist/harness/viewpoint-scan-refs.d.ts +50 -0
  297. package/dist/harness/viewpoint-scan-refs.d.ts.map +1 -0
  298. package/dist/harness/viewpoint-scan-refs.js +200 -0
  299. package/dist/harness/viewpoint-scan-refs.js.map +1 -0
  300. package/dist/harness/viewpoint-scan.d.ts +41 -0
  301. package/dist/harness/viewpoint-scan.d.ts.map +1 -0
  302. package/dist/harness/viewpoint-scan.js +118 -0
  303. package/dist/harness/viewpoint-scan.js.map +1 -0
  304. package/dist/harness/write-atomic.d.ts +2 -0
  305. package/dist/harness/write-atomic.d.ts.map +1 -0
  306. package/dist/harness/write-atomic.js +62 -0
  307. package/dist/harness/write-atomic.js.map +1 -0
  308. package/dist/orchestrator/ai-skills/writer.d.ts.map +1 -1
  309. package/dist/orchestrator/ai-skills/writer.js +15 -7
  310. package/dist/orchestrator/ai-skills/writer.js.map +1 -1
  311. package/dist/orchestrator/assets-drift.d.ts.map +1 -1
  312. package/dist/orchestrator/assets-drift.js +11 -6
  313. package/dist/orchestrator/assets-drift.js.map +1 -1
  314. package/dist/orchestrator/flow-manager.d.ts +0 -1
  315. package/dist/orchestrator/flow-manager.d.ts.map +1 -1
  316. package/dist/orchestrator/flow-manager.js +3 -52
  317. package/dist/orchestrator/flow-manager.js.map +1 -1
  318. package/dist/orchestrator/project-deps-sync.d.ts.map +1 -1
  319. package/dist/orchestrator/project-deps-sync.js +22 -1
  320. package/dist/orchestrator/project-deps-sync.js.map +1 -1
  321. package/dist/orchestrator/project-initializer.d.ts +8 -0
  322. package/dist/orchestrator/project-initializer.d.ts.map +1 -1
  323. package/dist/orchestrator/project-initializer.js +49 -7
  324. package/dist/orchestrator/project-initializer.js.map +1 -1
  325. package/dist/orchestrator/screen-manager.d.ts.map +1 -1
  326. package/dist/orchestrator/screen-manager.js +8 -62
  327. package/dist/orchestrator/screen-manager.js.map +1 -1
  328. package/dist/orchestrator/security-overrides-catalog.d.ts +39 -0
  329. package/dist/orchestrator/security-overrides-catalog.d.ts.map +1 -0
  330. package/dist/orchestrator/security-overrides-catalog.js +63 -0
  331. package/dist/orchestrator/security-overrides-catalog.js.map +1 -0
  332. package/dist/orchestrator/security-overrides.d.ts +51 -0
  333. package/dist/orchestrator/security-overrides.d.ts.map +1 -0
  334. package/dist/orchestrator/security-overrides.js +165 -0
  335. package/dist/orchestrator/security-overrides.js.map +1 -0
  336. package/dist/orchestrator/templates/ai-src/agents/discovery.md +11 -3
  337. package/dist/orchestrator/templates/ai-src/agents/reviewer.md +8 -0
  338. package/dist/orchestrator/templates/ai-src/commands/create-test.md +32 -24
  339. package/dist/orchestrator/templates/ai-src/commands/review.md +2 -2
  340. package/dist/orchestrator/templates/ai-src/commands/run-test.md +78 -15
  341. package/dist/orchestrator/templates/ai-src/skills/sungen-capture/mode-local.md +2 -2
  342. package/dist/orchestrator/templates/ai-src/skills/sungen-delivery/SKILL.md +14 -0
  343. package/dist/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +25 -1
  344. package/dist/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +26 -8
  345. package/dist/orchestrator/templates/ai-src/skills/sungen-harness-audit/SKILL.md +5 -1
  346. package/dist/orchestrator/templates/ai-src/skills/sungen-selector-fix/SKILL.md +58 -14
  347. package/dist/orchestrator/templates/ai-src/skills/sungen-selector-keys/SKILL.md +13 -1
  348. package/dist/orchestrator/templates/ai-src/skills/sungen-tc-generation/SKILL.md +42 -2
  349. package/dist/orchestrator/templates/ai-src/skills/sungen-tc-review/SKILL.md +7 -0
  350. package/dist/orchestrator/templates/ai-src/skills/sungen-viewpoint/SKILL.md +18 -0
  351. package/dist/orchestrator/templates/ai-src/skills/sungen-viewpoint/review-checklist.md +63 -0
  352. package/dist/orchestrator/templates/ai-src/skills/sungen-viewpoint/viewpoint-template.md +158 -0
  353. package/dist/orchestrator/templates/playwright.config.ts +4 -2
  354. package/dist/orchestrator/templates/specs-locale-fixture.ts +21 -9
  355. package/dist/orchestrator/templates/specs-pw-shape-reporter.ts +0 -0
  356. package/dist/orchestrator/templates/specs-url-assert.d.ts +17 -1
  357. package/dist/orchestrator/templates/specs-url-assert.d.ts.map +1 -1
  358. package/dist/orchestrator/templates/specs-url-assert.js +38 -4
  359. package/dist/orchestrator/templates/specs-url-assert.js.map +1 -1
  360. package/dist/orchestrator/templates/specs-url-assert.ts +47 -4
  361. package/dist/orchestrator/templates/wdio.conf.ts +24 -1
  362. package/dist/orchestrator/trace-mode-install.d.ts +14 -0
  363. package/dist/orchestrator/trace-mode-install.d.ts.map +1 -0
  364. package/dist/orchestrator/trace-mode-install.js +132 -0
  365. package/dist/orchestrator/trace-mode-install.js.map +1 -0
  366. package/dist/orchestrator/viewpoint-pattern-catalog.d.ts +23 -0
  367. package/dist/orchestrator/viewpoint-pattern-catalog.d.ts.map +1 -0
  368. package/dist/orchestrator/viewpoint-pattern-catalog.js +48 -0
  369. package/dist/orchestrator/viewpoint-pattern-catalog.js.map +1 -0
  370. package/dist/orchestrator/viewpoint-scaffold.d.ts +3 -0
  371. package/dist/orchestrator/viewpoint-scaffold.d.ts.map +1 -0
  372. package/dist/orchestrator/viewpoint-scaffold.js +70 -0
  373. package/dist/orchestrator/viewpoint-scaffold.js.map +1 -0
  374. package/package.json +3 -3
  375. package/src/cli/commands/audit.ts +59 -12
  376. package/src/cli/commands/capability.ts +54 -19
  377. package/src/cli/commands/changed.ts +2 -4
  378. package/src/cli/commands/dashboard.ts +1 -26
  379. package/src/cli/commands/defect.ts +49 -0
  380. package/src/cli/commands/delivery.ts +106 -56
  381. package/src/cli/commands/generate.ts +15 -7
  382. package/src/cli/commands/results-merge.ts +9 -9
  383. package/src/cli/commands/results-sanitize.ts +2 -9
  384. package/src/cli/commands/select.ts +88 -0
  385. package/src/cli/commands/triage.ts +57 -0
  386. package/src/cli/commands/update.ts +3 -0
  387. package/src/cli/commands/viewpoint.ts +58 -0
  388. package/src/cli/index.ts +13 -2
  389. package/src/dashboard/snapshot-builder.ts +6 -8
  390. package/src/dashboard/templates/index.html +1 -1
  391. package/src/dashboard/types.ts +1 -0
  392. package/src/exporters/csv-exporter.ts +12 -11
  393. package/src/exporters/feature-parser.ts +44 -2
  394. package/src/exporters/json-exporter.ts +6 -1
  395. package/src/exporters/locale-variants.ts +23 -17
  396. package/src/exporters/manual-hybrid-oracle.ts +112 -0
  397. package/src/exporters/matrix/build.ts +71 -19
  398. package/src/exporters/matrix/carry-manual-results.ts +292 -0
  399. package/src/exporters/matrix/export.ts +24 -4
  400. package/src/exporters/matrix/gates.ts +6 -0
  401. package/src/exporters/matrix/render-csv.ts +1 -1
  402. package/src/exporters/matrix/render-testcase-sheet.ts +10 -4
  403. package/src/exporters/matrix/render-xlsx.ts +3 -0
  404. package/src/exporters/matrix/types.ts +13 -1
  405. package/src/exporters/matrix/wording.ts +36 -2
  406. package/src/exporters/playwright-report-parser.ts +1 -0
  407. package/src/exporters/run-environment.ts +89 -0
  408. package/src/exporters/scenario-merger.ts +51 -5
  409. package/src/exporters/test-data-resolver.ts +0 -6
  410. package/src/exporters/types.ts +5 -0
  411. package/src/exporters/xlsx-exporter.ts +7 -2
  412. package/src/generators/gherkin-parser/index.ts +50 -18
  413. package/src/generators/test-generator/adapters/adapter-interface.ts +6 -2
  414. package/src/generators/test-generator/adapters/appium/templates/steps/actions/reinstall-app-action.hbs +2 -2
  415. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/label-value-assertion.hbs +8 -2
  416. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/visible-with-role-variable-assertion.hbs +7 -3
  417. package/src/generators/test-generator/adapters/appium/templates/test-file.hbs +68 -4
  418. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/click-select-action.hbs +1 -1
  419. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/select-action.hbs +1 -1
  420. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/label-value-assertion.hbs +7 -1
  421. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-role-variable-assertion.hbs +8 -4
  422. package/src/generators/test-generator/adapters/playwright/templates/steps/partials/pick-option.hbs +13 -0
  423. package/src/generators/test-generator/adapters/playwright/templates/steps/partials/url-assertion.hbs +5 -1
  424. package/src/generators/test-generator/adapters/playwright/templates/test-file.hbs +16 -0
  425. package/src/generators/test-generator/code-generator.ts +77 -5
  426. package/src/generators/test-generator/diagnostics.ts +36 -5
  427. package/src/generators/test-generator/patterns/index.ts +15 -8
  428. package/src/generators/test-generator/patterns/types.ts +15 -0
  429. package/src/generators/test-generator/patterns/with-parent-scope.ts +6 -0
  430. package/src/generators/test-generator/step-mapper.ts +90 -8
  431. package/src/generators/test-generator/utils/data-resolver.ts +41 -12
  432. package/src/generators/test-generator/utils/selector-entry-fields.ts +1 -0
  433. package/src/generators/test-generator/utils/selector-resolver.ts +238 -82
  434. package/src/harness/audit.ts +69 -24
  435. package/src/harness/capability.ts +23 -12
  436. package/src/harness/catalog/universal-viewpoints.yaml +5 -5
  437. package/src/harness/config-file.ts +66 -0
  438. package/src/harness/counted-assertions.ts +33 -0
  439. package/src/harness/data-driven-lint.ts +82 -24
  440. package/src/harness/defect-draft.ts +115 -0
  441. package/src/harness/defects.ts +94 -0
  442. package/src/harness/depth-lint.ts +2 -1
  443. package/src/harness/flow-check.ts +6 -2
  444. package/src/harness/keyword-match.ts +85 -0
  445. package/src/harness/manifest.ts +2 -2
  446. package/src/harness/next-step.ts +47 -5
  447. package/src/harness/parse.ts +151 -27
  448. package/src/harness/perf.ts +15 -7
  449. package/src/harness/quality-gates.ts +22 -8
  450. package/src/harness/query-catalog.ts +0 -0
  451. package/src/harness/read-text.ts +32 -1
  452. package/src/harness/script-check.ts +7 -1
  453. package/src/harness/secret-scan.ts +60 -4
  454. package/src/harness/select-by-ids.ts +83 -0
  455. package/src/harness/sensors.ts +141 -40
  456. package/src/harness/spec-branches.ts +6 -3
  457. package/src/harness/spec-coverage.ts +14 -4
  458. package/src/harness/triage-signals.ts +46 -0
  459. package/src/harness/triage-unit.ts +113 -0
  460. package/src/harness/triage.ts +127 -0
  461. package/src/harness/ui-inventory.ts +164 -0
  462. package/src/harness/viewpoint-baseline.ts +7 -1
  463. package/src/harness/viewpoint-draft-header.ts +55 -0
  464. package/src/harness/viewpoint-ledger.ts +113 -25
  465. package/src/harness/viewpoint-mode.ts +49 -0
  466. package/src/harness/viewpoint-priority.ts +38 -0
  467. package/src/harness/viewpoint-review-open.ts +51 -0
  468. package/src/harness/viewpoint-scan-refs.ts +154 -0
  469. package/src/harness/viewpoint-scan.ts +111 -0
  470. package/src/harness/write-atomic.ts +22 -0
  471. package/src/orchestrator/ai-skills/writer.ts +18 -3
  472. package/src/orchestrator/assets-drift.ts +10 -5
  473. package/src/orchestrator/flow-manager.ts +3 -53
  474. package/src/orchestrator/project-deps-sync.ts +23 -1
  475. package/src/orchestrator/project-initializer.ts +54 -6
  476. package/src/orchestrator/screen-manager.ts +7 -61
  477. package/src/orchestrator/security-overrides-catalog.ts +69 -0
  478. package/src/orchestrator/security-overrides.ts +149 -0
  479. package/src/orchestrator/templates/ai-src/agents/discovery.md +11 -3
  480. package/src/orchestrator/templates/ai-src/agents/reviewer.md +8 -0
  481. package/src/orchestrator/templates/ai-src/commands/create-test.md +32 -24
  482. package/src/orchestrator/templates/ai-src/commands/review.md +2 -2
  483. package/src/orchestrator/templates/ai-src/commands/run-test.md +78 -15
  484. package/src/orchestrator/templates/ai-src/skills/sungen-capture/mode-local.md +2 -2
  485. package/src/orchestrator/templates/ai-src/skills/sungen-delivery/SKILL.md +14 -0
  486. package/src/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +25 -1
  487. package/src/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +26 -8
  488. package/src/orchestrator/templates/ai-src/skills/sungen-harness-audit/SKILL.md +5 -1
  489. package/src/orchestrator/templates/ai-src/skills/sungen-selector-fix/SKILL.md +58 -14
  490. package/src/orchestrator/templates/ai-src/skills/sungen-selector-keys/SKILL.md +13 -1
  491. package/src/orchestrator/templates/ai-src/skills/sungen-tc-generation/SKILL.md +42 -2
  492. package/src/orchestrator/templates/ai-src/skills/sungen-tc-review/SKILL.md +7 -0
  493. package/src/orchestrator/templates/ai-src/skills/sungen-viewpoint/SKILL.md +18 -0
  494. package/src/orchestrator/templates/ai-src/skills/sungen-viewpoint/review-checklist.md +63 -0
  495. package/src/orchestrator/templates/ai-src/skills/sungen-viewpoint/viewpoint-template.md +158 -0
  496. package/src/orchestrator/templates/playwright.config.ts +4 -2
  497. package/src/orchestrator/templates/specs-locale-fixture.ts +21 -9
  498. package/src/orchestrator/templates/specs-pw-shape-reporter.ts +0 -0
  499. package/src/orchestrator/templates/specs-url-assert.ts +47 -4
  500. package/src/orchestrator/templates/wdio.conf.ts +24 -1
  501. package/src/orchestrator/trace-mode-install.ts +94 -0
  502. package/src/orchestrator/viewpoint-pattern-catalog.ts +61 -0
  503. package/src/orchestrator/viewpoint-scaffold.ts +36 -0
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.titlesToGrep = titlesToGrep;
37
+ exports.parseIdList = parseIdList;
38
+ exports.selectByIds = selectByIds;
39
+ /**
40
+ * Select scenarios by test-case ID — backs `sungen select` and `run-test --ids` (#835).
41
+ *
42
+ * An ID means what it means everywhere else in the harness: `vpId`, the leading ID token of the
43
+ * scenario title (`VP-UI-001`, `MS-HP-001`, `VP0-001`). Matching is exact and case-insensitive —
44
+ * `VP-UI-001` never selects `VP-UI-0010` or `VP-UI-001-B` — and every ID that selects nothing
45
+ * runnable is reported, because the alternative is a 0-test run that reports green.
46
+ */
47
+ const path = __importStar(require("path"));
48
+ /**
49
+ * Escape scenario titles into one `-g` / `--mochaOpts.grep` regex. Full titles, not bare IDs:
50
+ * a title starts with its own ID, so it can only appear inside its own test's title — and a
51
+ * `@cases` row test (`<title> — <row label>`) still contains it.
52
+ */
53
+ function titlesToGrep(titles) {
54
+ return titles.map((t) => t.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|');
55
+ }
56
+ /** `"VP-UI-001, vp-ui-002 VP-UI-001"` → `['VP-UI-001', 'VP-UI-002']`. */
57
+ function parseIdList(raw) {
58
+ return [...new Set(raw.split(/[\s,]+/).map((s) => s.trim().toUpperCase()).filter(Boolean))];
59
+ }
60
+ /** `VP-C-002.` → `VP-C-002`: the title token may carry trailing punctuation the user never types. */
61
+ const idOf = (s) => s.vpId?.replace(/[.-]+$/, '') || undefined;
62
+ function notRunnableReason(s, enabledCaps) {
63
+ if (s.deferredToFlow)
64
+ return `owned by a flow${s.ownedByFlow ? ` (${s.ownedByFlow})` : ''} — run it there`;
65
+ if (s.featureManual)
66
+ return 'its Feature is @manual — no spec is generated for it';
67
+ if (s.manual)
68
+ return 'manual — no automated test exists';
69
+ // Compiled as `test.skip` while the capability is off: the run would report a skip, not a result.
70
+ const missing = (s.requiresCaps ?? []).filter((c) => !enabledCaps.has(c));
71
+ if (missing.length)
72
+ return `needs capability ${missing.join(', ')} — compiled as a skip until \`sungen capability add ${missing.join(' ')}\``;
73
+ return null;
74
+ }
75
+ function selectByIds(scenarios, ids, unit, enabledCaps = new Set()) {
76
+ const out = { features: [], unknown: [], notRunnable: [] };
77
+ const groups = new Map();
78
+ const allIds = [...new Set(scenarios.map(idOf).filter((v) => !!v))];
79
+ for (const id of ids) {
80
+ const hits = scenarios.filter((s) => idOf(s) === id);
81
+ if (hits.length === 0) {
82
+ const didYouMean = allIds.filter((v) => v.startsWith(`${id}-`) || id.startsWith(`${v}-`)).slice(0, 5);
83
+ out.unknown.push({ id, didYouMean });
84
+ continue;
85
+ }
86
+ const runnable = hits.filter((s) => !notRunnableReason(s, enabledCaps));
87
+ if (runnable.length === 0) {
88
+ out.notRunnable.push({ id, reason: notRunnableReason(hits[0], enabledCaps) });
89
+ continue;
90
+ }
91
+ for (const s of runnable) {
92
+ const feature = s.sourceFile ? path.basename(s.sourceFile, '.feature') : unit;
93
+ const g = groups.get(feature) ?? { feature, ids: [], titles: [], grep: '' };
94
+ if (!g.ids.includes(id))
95
+ g.ids.push(id);
96
+ if (!g.titles.includes(s.name))
97
+ g.titles.push(s.name);
98
+ groups.set(feature, g);
99
+ }
100
+ }
101
+ for (const g of groups.values())
102
+ g.grep = titlesToGrep(g.titles);
103
+ out.features = [...groups.values()];
104
+ return out;
105
+ }
106
+ //# sourceMappingURL=select-by-ids.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select-by-ids.js","sourceRoot":"","sources":["../../src/harness/select-by-ids.ts"],"names":[],"mappings":"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"}
@@ -41,6 +41,17 @@ export interface GateResult {
41
41
  status: 'missing' | 'shallow';
42
42
  }[];
43
43
  universalGaps: string[];
44
+ /**
45
+ * WHICH scenario covered each satisfied theme, and on which keyword — the audit's second line of
46
+ * defence against a bogus coverage claim (#776). A bare count ("themes 3/3") gives a reviewer
47
+ * nothing to check, so a nonsense match survives; naming the evidence makes it obvious on sight.
48
+ * Mirrors how the Claim-Proof section already names the scenario behind each claim.
49
+ */
50
+ coveredBy: {
51
+ theme: string;
52
+ by: string;
53
+ keyword: string;
54
+ }[];
44
55
  }
45
56
  /**
46
57
  * An explicit `page-type: <id>` line in test-viewpoint.md — the project stating what
@@ -134,6 +145,7 @@ export interface OracleStrengthResult {
134
145
  code?: string;
135
146
  }[];
136
147
  facetClaims: number;
148
+ weakFacet: number;
137
149
  ratio: number;
138
150
  }
139
151
  export declare function oracleStrength(scenarios: ScenarioInfo[]): OracleStrengthResult;
@@ -210,6 +222,9 @@ export interface TraceResult {
210
222
  mappedToOverview: number;
211
223
  withVpCodeRatio: number;
212
224
  mappedRatio: number;
225
+ /** Viewpoint IDs read from test-viewpoint.md. 0 = nothing to map to, so `mappedRatio` is not a
226
+ * measurement — the scenario IDs were never checked (#832). */
227
+ overviewIds: number;
213
228
  note: string;
214
229
  }
215
230
  export declare function traceability(scenarios: ScenarioInfo[], viewpoints: ViewpointEntry[]): TraceResult;
@@ -267,8 +282,12 @@ export declare function numericClaimGaps(scenarios: ScenarioInfo[]): Array<{
267
282
  * The Priority-Viewpoints table is where release selection is supposed to come from. When the
268
283
  * table says a flow is `Low` and its scenario is tagged `@high`, a smoke run picks up work the QA
269
284
  * deliberately deprioritised — and nobody can tell which of the two was the decision (#622).
285
+ *
286
+ * Reads the SAME parse traceability does (`parseViewpointOverview`). It used to scan the raw text
287
+ * for any `| VP-… | high |` row, so one audit run "saw" an id for this check and not for
288
+ * traceability (#833), and a row in a Known Issues table could raise a contradiction.
270
289
  */
271
- export declare function priorityMismatches(viewpointText: string, scenarios: ScenarioInfo[]): Array<{
290
+ export declare function priorityMismatches(viewpoints: ViewpointEntry[], scenarios: ScenarioInfo[]): Array<{
272
291
  id: string;
273
292
  declared: string;
274
293
  tagged: string;
@@ -1 +1 @@
1
- {"version":3,"file":"sensors.d.ts","sourceRoot":"","sources":["../../src/harness/sensors.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sensors.d.ts","sourceRoot":"","sources":["../../src/harness/sensors.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,YAAY,EAAE,cAAc,EAAY,MAAM,SAAS,CAAC;AA6CjE,6FAA6F;AAC7F,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAYtE;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AACD,MAAM,WAAW,YAAY;IAAG,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,UAAU,CAAA;CAAE;AACvF,MAAM,WAAW,OAAO;IACtB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,eAAe,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,EAAE,YAAY,EAAE,CAAA;KAAE,CAAC,CAAC;IACtF,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B;mGAC+F;IAC/F,gBAAgB,CAAC,EAAE,YAAY,EAAE,CAAC;CACnC;AAED,wBAAgB,WAAW,IAAI,OAAO,CAGrC;AAUD,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,sFAAsF;IACtF,cAAc,CAAC,EAAE,UAAU,GAAG,UAAU,GAAG,cAAc,CAAC;IAC1D,4EAA4E;IAC5E,gBAAgB,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACtD,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,EAAE,SAAS,GAAG,SAAS,CAAA;KAAE,EAAE,CAAC;IAC7E,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB;;;;;OAKG;IACH,SAAS,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC7D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAKvF;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,YAAY,EAAE,EAAE,UAAU,EAAE,cAAc,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,UAAQ,EAAE,aAAa,SAAK,GAAG,UAAU,CAgGzJ;AAID,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAEpD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,uBAAuB,EAAE,MAAM,CAAC;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,uBAAuB,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAK/D,wBAAwB,EAAE,MAAM,CAAC;IAEjC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,YAAY,CAAC;CACvB;AASD;sGACsG;AACtG,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEvD;AACD,sEAAsE;AACtE,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,YAAY,EAAE,EACzB,UAAU,GAAE,YAAY,EAAO,EAC/B,KAAK,SAAe,GACnB,WAAW,CAuCb;AAID,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAClD;AAWD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,YAAY,EAAE,GAAG,uBAAuB,CAQpF;AAID;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,EAAE,EAC7C,aAAa,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,EAAE,GACjE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CAOnC;AAID,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,YAAY,EAAE,GAAG,eAAe,CAiB9E;AAID,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACtD,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AAcD,wBAAgB,cAAc,CAAC,SAAS,EAAE,YAAY,EAAE,GAAG,oBAAoB,CA2C9E;AAED,oFAAoF;AACpF,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,YAAY,EAAE,CAKvF;AAID,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,YAAY,EAAE,GAAG,aAAa,CA6BxE;AAID,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,EAAE,CAAC;QAAC,cAAc,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;IAC/E,mBAAmB,EAAE,MAAM,CAAC;IAC5B,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,YAAY,EAAE,GAAG,eAAe,CAwB5E;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,oGAAoG;IACpG,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,YAAY,EAAE,GAAG,gBAAgB,EAAE,CAmB7E;AAID,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB;oEACgE;IAChE,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd;AA4BD,wBAAgB,YAAY,CAAC,SAAS,EAAE,YAAY,EAAE,EAAE,UAAU,EAAE,cAAc,EAAE,GAAG,WAAW,CA6BjG;AAUD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,YAAY,CAAC;CACvB;AAkND,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,eAAe,EAAE,CAAC;CAC/B;AA0CD,wBAAgB,YAAY,CAAC,SAAS,EAAE,YAAY,EAAE,GAAG,cAAc,CA0BtE;AAED,wBAAgB,UAAU,CAAC,SAAS,EAAE,YAAY,EAAE,EAAE,KAAK,SAAe,GAAG,gBAAgB,CAmC5F;AAQD;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,YAAY,EAAE,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAcpI;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,cAAc,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE,GACtD,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAqB3E"}
@@ -57,6 +57,9 @@ const path = __importStar(require("path"));
57
57
  const yaml_1 = require("yaml");
58
58
  const parse_1 = require("./parse");
59
59
  const read_text_1 = require("./read-text");
60
+ const keyword_match_1 = require("./keyword-match");
61
+ const viewpoint_priority_1 = require("./viewpoint-priority");
62
+ const counted_assertions_1 = require("./counted-assertions");
60
63
  // Business-critical category keywords (matched by CONTAINMENT against the VP category, so a
61
64
  // compound category like LIST-DISPLAY / ADD-TO-CART / PRODUCT-DISCOVERY classifies correctly).
62
65
  const BUSINESS_CRITICAL_CATS = [
@@ -114,18 +117,11 @@ function loadCatalog() {
114
117
  const p = path.join(__dirname, 'catalog', 'universal-viewpoints.yaml');
115
118
  return (0, yaml_1.parse)((0, read_text_1.readTextFile)(p));
116
119
  }
117
- // Word-aware keyword match: `\b<kw>(s|es|ed|ing)?\b`, so a keyword matches whole words (plus
118
- // simple plural/verb suffixes) but NOT as a substring of a larger word — e.g. `form` must not
119
- // match inside `Format` or `@platform`, while `product` still matches `products`. Multi-word
120
- // keywords ("add to cart", "is hidden") match the phrase with a boundary at each end.
121
- const wordRe = (kw) => {
122
- const esc = kw.toLowerCase().replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
123
- return new RegExp(`\\b${esc}(?:s|es|ed|ing)?\\b`);
124
- };
125
- const has = (haystacks, kw) => {
126
- const re = wordRe(kw);
127
- return haystacks.some((h) => re.test(h));
128
- };
120
+ // Word-aware keyword match — one rule for every sensor, in ./keyword-match (#776). A keyword
121
+ // matches at a word START but may carry any suffix, so `form` does not match inside `Format` or
122
+ // `@platform` while `submit` still matches `submitted`. The old local copy anchored BOTH ends,
123
+ // which silently dropped every inflected true positive; see that module for the measurements.
124
+ const has = keyword_match_1.hasKeyword;
129
125
  /**
130
126
  * An explicit `page-type: <id>` line in test-viewpoint.md — the project stating what
131
127
  * kind of screen this is. A declaration always beats keyword detection.
@@ -188,13 +184,15 @@ function viewpointGate(scenarios, viewpoints, catalog, isMobile = false, viewpoi
188
184
  }
189
185
  const evidence = { hits: best, runnerUp };
190
186
  const gaps = [];
187
+ const coveredBy = [];
191
188
  let total = 0, covered = 0;
192
189
  if (pageType) {
193
190
  for (const t of catalog.page_types[pageType].must_cover) {
194
191
  total++;
195
192
  // Scenarios that cover this theme by keyword (include @manual — a manual
196
193
  // scenario with a real assertion still covers the viewpoint for design).
197
- const coverers = scenarios.filter((s) => t.keywords.some((k) => s.haystack.includes(k.toLowerCase())));
194
+ // Word-aware since #776: a substring match let `information` satisfy `format-boundary`.
195
+ const coverers = scenarios.filter((s) => t.keywords.some((k) => (0, keyword_match_1.keywordHit)(s.haystack, k)));
198
196
  if (coverers.length === 0) {
199
197
  gaps.push({ theme: t.theme, keywords: t.keywords, status: 'missing' });
200
198
  continue;
@@ -203,12 +201,26 @@ function viewpointGate(scenarios, viewpoints, catalog, isMobile = false, viewpoi
203
201
  // assertion, so mere presence covers it. Only DATA-correctness themes (depth.requires:
204
202
  // data-assertion) need a data assertion to count as deeply covered.
205
203
  const needsDepth = t.depth?.requires === 'data-assertion';
206
- if (!needsDepth) {
204
+ // Name the evidence for whichever scenario actually carries the theme — the one with the
205
+ // data assertion when depth is required, since that is the scenario the credit rests on.
206
+ const proof = (needsDepth ? coverers.find((s) => s.hasDataAssertion) : undefined) ?? coverers[0];
207
+ const credit = () => {
207
208
  covered++;
209
+ coveredBy.push({
210
+ theme: t.theme,
211
+ by: proof.haystack,
212
+ // `proof` came out of `coverers`, which was filtered on this same predicate, so the find
213
+ // always lands — the `!` states that rather than inventing a fallback keyword that would
214
+ // misattribute the credit if the invariant ever broke.
215
+ keyword: t.keywords.find((k) => (0, keyword_match_1.keywordHit)(proof.haystack, k)),
216
+ });
217
+ };
218
+ if (!needsDepth) {
219
+ credit();
208
220
  continue;
209
221
  }
210
222
  if (coverers.some((s) => s.hasDataAssertion))
211
- covered++;
223
+ credit();
212
224
  else
213
225
  gaps.push({ theme: t.theme, keywords: t.keywords, status: 'shallow' });
214
226
  }
@@ -231,6 +243,7 @@ function viewpointGate(scenarios, viewpoints, catalog, isMobile = false, viewpoi
231
243
  coverageRatio: total ? covered / total : 1,
232
244
  gaps,
233
245
  universalGaps,
246
+ coveredBy,
234
247
  };
235
248
  }
236
249
  // Intent → required depth ratio + whether a miss WARNs (smoke) or FAILs the gate.
@@ -264,7 +277,7 @@ function assertionDepth(scenarios, dataThemes = [], focus = 'functional') {
264
277
  // dialog") assert a HIDDEN state — that IS the correct, data-light assertion for the
265
278
  // behavior. They only match a data keyword incidentally (e.g. "added"), so exclude them.
266
279
  const isDismissBehavior = (s) => /\bis hidden\b|\bare hidden\b|\bdismiss|\bdisappear|\bno longer (visible|shown|present|displayed)\b|\bcloses? the (modal|dialog|popup|overlay|panel|menu)\b/.test(s.haystack);
267
- const isDepthRequired = (s) => s.category !== 'NAV' && !isDismissBehavior(s) && depthKeywords.some((k) => s.haystack.includes(k.toLowerCase()));
280
+ const isDepthRequired = (s) => s.category !== 'NAV' && !isDismissBehavior(s) && depthKeywords.some((k) => (0, keyword_match_1.keywordHit)(s.haystack, k));
268
281
  const required = nonManual.filter(isDepthRequired);
269
282
  const reqShallow = required.filter((s) => s.shallow);
270
283
  // Business-critical scenarios deferred to @manual (match a data-theme but excluded above).
@@ -324,7 +337,7 @@ function automatableManual(scenarios) {
324
337
  function flowCoveredThemes(gaps, flowScenarios) {
325
338
  const out = [];
326
339
  for (const g of gaps) {
327
- const hit = flowScenarios.find((s) => s.deep && g.keywords.some((k) => s.haystack.includes(k.toLowerCase())));
340
+ const hit = flowScenarios.find((s) => s.deep && g.keywords.some((k) => (0, keyword_match_1.keywordHit)(s.haystack, k)));
328
341
  if (hit)
329
342
  out.push({ theme: g.theme, flow: hit.flow });
330
343
  }
@@ -386,10 +399,12 @@ function oracleStrength(scenarios) {
386
399
  hint: `every \`Then\` is a URL assertion${guardLike ? ' on a permission / guard scenario' : ''} — it proves the router pushed a path, not that the page rendered for this user${guardLike ? ', and this is exactly the scenario a late 403 redirect turns falsely green' : ''}. Give the page selector an \`anchor:\` (a heading/landmark only the rendered page has) — one line per screen, and every \`see [X] page\` on it becomes a content oracle — or add a content assertion after it.`,
387
400
  });
388
401
  }
402
+ let weakFacet = 0;
389
403
  for (const s of scenarios) {
390
404
  if (s.manual)
391
405
  continue; // a @manual facet check is a deliberate deferral, not a weak automated oracle
392
406
  if (WEAK_FACET_ORACLE.test(s.stepsText)) {
407
+ weakFacet++;
393
408
  weak.push({
394
409
  name: s.name.slice(0, 80),
395
410
  hint: 'asserting every item NAME contains a category/brand term does not prove facet membership — assert the results-page TITLE/header carries the facet, a detail-page facet field, or an API/DB oracle; or defer the exhaustive check to @manual:M2.',
@@ -397,7 +412,17 @@ function oracleStrength(scenarios) {
397
412
  }
398
413
  }
399
414
  const facetClaims = scenarios.filter((s) => FACET_REF.test(s.stepsText) || FACET_REF.test(s.name)).length;
400
- return { weak, facetClaims, ratio: facetClaims ? 1 - weak.length / Math.max(1, facetClaims) : 1 };
415
+ // Only the FACET class is denominated by `facetClaims`. `weak` also carries ORACLE-URL-ONLY
416
+ // findings (#662), which make no category/brand claim at all — averaging them into this axis
417
+ // drove `ratio` negative (5 URL-only over 2 facet claims → 1 - 5/2 = -1.5), which walked through
418
+ // the businessDepth floor and took the CLI's bar renderer down with it (#762). A URL-only oracle
419
+ // is NAMED as a finding and holds the score out of the senior band (`seniorBandedOverall`);
420
+ // it is not averaged into the facet axis — the invariant `url-only-oracle.run.ts` asserts.
421
+ // The clamp is not belt-and-braces: a weak-facet scenario need not itself satisfy FACET_REF
422
+ // (`see all [name] contains {{price.term}}` is weak but claims no facet), so `weakFacet` can
423
+ // still outrun `facetClaims`. This axis is declared 0..1; it leaves here inside 0..1.
424
+ const ratio = facetClaims ? Math.max(0, Math.min(1, 1 - weakFacet / facetClaims)) : 1;
425
+ return { weak, facetClaims, weakFacet, ratio };
401
426
  }
402
427
  /** Collect data-correctness themes (depth.requires) for a page-type + universal. */
403
428
  function dataThemesFor(catalog, pageType) {
@@ -490,6 +515,27 @@ function scenarioIdReuse(scenarios) {
490
515
  * a correctly-traced flow suite read as 15% traceable (#592).
491
516
  */
492
517
  const unprefixed = (id) => id.replace(/^(?:VP|FL)-/i, '').toUpperCase();
518
+ /**
519
+ * The traceability note, worded from the SAME ratio the audit's TRACE finding fires on —
520
+ * mapped / ALL scenarios (#852). It used to compare mapped against scenarios WITH an id, so 0 of
521
+ * 0 (no scenario yet, or none tagged) and 2 of 2 tagged out of 10 all read "Traceable." while
522
+ * the audit reported `TRACE: Traceable.` for a 0–20% mapping.
523
+ */
524
+ function traceNote(total, withCode, mapped, declared, exampleId) {
525
+ if (declared === 0) {
526
+ return 'No viewpoint ID found in test-viewpoint.md — the file is missing, or none of its sections declares one — so the scenario IDs were not checked. Declarations are read from a `## Priority Viewpoints` table, `### Required / Recommended / Optional` lists, and tables whose first column is a `VP-`/`FL-` ID or an ID of a family declared there (Known Issues / Traceability / References sections are skipped).';
527
+ }
528
+ if (total === 0)
529
+ return 'No scenarios yet — traceability is measured once the feature has scenarios.';
530
+ if (mapped >= total * 0.5)
531
+ return 'Traceable.';
532
+ const example = exampleId ? ` (e.g. \`${exampleId}-001 …\`)` : '';
533
+ if (withCode === 0)
534
+ return `No scenario carries a viewpoint ID — start each title with one of the IDs declared in test-viewpoint.md${example}.`;
535
+ if (mapped < withCode * 0.5)
536
+ return 'Scenario IDs do not match the viewpoint-overview ids (weak traceability — re-tag to the project viewpoint IDs).';
537
+ return `Only ${mapped} of ${total} scenarios carry a declared viewpoint ID — ${total - withCode} have no ID at all; tag them with the project's IDs${example}.`;
538
+ }
493
539
  function traceability(scenarios, viewpoints) {
494
540
  const overviewIds = new Set(viewpoints.map((v) => v.id.toUpperCase()));
495
541
  const overviewBare = new Set(viewpoints.map((v) => unprefixed(v.id)));
@@ -517,9 +563,10 @@ function traceability(scenarios, viewpoints) {
517
563
  mappedToOverview: mapped.length,
518
564
  withVpCodeRatio: scenarios.length ? withCode.length / scenarios.length : 0,
519
565
  mappedRatio: scenarios.length ? mapped.length / scenarios.length : 0,
520
- note: withCode.length && mapped.length < withCode.length * 0.5
521
- ? 'Scenario IDs do not match the viewpoint-overview ids (weak traceability — re-tag to the project viewpoint IDs).'
522
- : 'Traceable.',
566
+ overviewIds: overviewIds.size,
567
+ // With no ID read there is nothing to match against: telling the author to re-tag sends them
568
+ // to change scenarios that may be right (#832). Name the file and the sections read instead.
569
+ note: traceNote(scenarios.length, withCode.length, mapped.length, overviewIds.size, viewpoints[0]?.id),
523
570
  };
524
571
  }
525
572
  // Ordered by specificity; the first matching rule per scenario wins.
@@ -537,6 +584,31 @@ const CLAIM_RULES = [
537
584
  hint: 'swap `contains {{v}}` for `with {{v}}` on the continuity rows. A substring match cannot distinguish "unchanged" from "changed by adding a prefix" — and if the screen genuinely renders extra text around the value, say so in the title instead of claiming exactness.',
538
585
  severity: 'warn',
539
586
  },
587
+ {
588
+ // An ORDER claim ("sorted by date descending", "ties broken by last-updated") is invisible to
589
+ // a presence check: `see [List] table` passes whatever order the rows are in. It sits ahead of
590
+ // the generic rules so "all results sorted …" is judged as an ordering claim, not an all-claim.
591
+ // A tiebreaker is a Tier-1 guard in the tc-generation skill, yet no rule recognised it (#810).
592
+ claim: 'ordering/sort',
593
+ title: /\b(ascending|descending|sorted|sorts|sort order|ordered by|order by|in (?:chronological|alphabetical|reverse|numeric) order|(?:newest|oldest|latest|earliest|highest|lowest) first|tie-?break(?:s|er|ers)?|ties?)\b|降順|昇順|並び順|giảm dần|tăng dần|sắp xếp/,
594
+ proof: /match data|is sorted|sorted (?:ascending|descending)|\brow \d+\b|\.first\.|\.last\.|\[\d+\]\.|order by/,
595
+ need: 'an order-sensitive assertion (`table match data:` rows in the expected order, `is sorted ascending|descending`, or positional `row N` checks)',
596
+ hint: 'a presence check passes in any order — assert the rows in their expected sequence (`User see [T] table match data:`), or the column sort state; a tiebreak needs two rows sharing the primary key.',
597
+ severity: 'fail',
598
+ },
599
+ {
600
+ // A LIMIT claim ("never exceeds 10", "at most 5 files") is a count claim in disguise.
601
+ // Ahead of 'no-side-effect', whose negation+effect pattern would otherwise swallow
602
+ // "never exceeds 10 records" and ask for a duplicate-count proof.
603
+ claim: 'limit/cap',
604
+ // The quantity must be ≥2 ("at most ONE order" is a no-duplicate claim — left to the rules
605
+ // below) and not a duration ("up to 30 seconds" is a timing claim, not a cap).
606
+ title: /\b(?:never exceeds?|(?:does not|doesn['’]t|not) exceed|at most|no more than|up to|capped at|caps? at|maximum of|max(?:imum)?)\s+(?:\d{2,}|[2-9]|two|three|four|five|six|seven|eight|nine|ten)\b(?!\s*(?:ms|milliseconds?|s|secs?|seconds?|mins?|minutes?|hours?|days?)\b)|\b(?:never exceeds?|(?:does not|doesn['’]t) exceed) (?:the )?(?:limit|cap|quota|maximum)\b|以内|上限|tối đa/,
607
+ proof: /\bcount\b|tohavecount|table with|row with \{\{|match data|is at most|\bexactly\b|field with \{\{|\berror\b|invalid|is disabled/,
608
+ need: 'a count/boundary assertion (count is N, `is at most`, the N+1th input rejected or truncated)',
609
+ hint: 'assert the boundary itself — the count at the cap, or the value/error when one more is attempted — not just that the list or field is present.',
610
+ severity: 'fail',
611
+ },
540
612
  {
541
613
  claim: 'all/every/each',
542
614
  title: /\b(all|every|each)\b/,
@@ -681,6 +753,12 @@ const CLAIM_RULES = [
681
753
  },
682
754
  ];
683
755
  const TAXONOMY_KNOWN = new Set(['LIST', 'PRODUCT', 'CART', 'FILTER', 'NAV', 'VAL', 'SEC']);
756
+ /**
757
+ * Words of ACCESS — a title about who may reach something. They make the robustness/routing words
758
+ * below security evidence ("deep link without authentication"); alone those words describe routing.
759
+ */
760
+ const ACCESS_CONTEXT = /\b(xss|sql|injection|without authentication|unauthenticated|unauthori[sz]ed|without an? (?:authenticated|valid|active) \w+|without (?:permission|login|logging in|signing in|an? account|access)|not (?:logged|signed) in|logged[- ]out|direct(?:ly)? access\w*|auth[- ]?guard|forbidden|\b403\b|(?:no|insufficient|missing) permissions?|permission required|session expired|expired session|tamper\w*)\b/;
761
+ /** `requires`: the signal counts only when the title ALSO matches it (#888). */
684
762
  const CATEGORY_SIGNALS = [
685
763
  { cat: 'FILTER', re: /\b(categor(y|ies)|sub-?categor\w*|expand\w*|collaps\w*|\bfacet\b|filter\w*|belongs? to)\b/ },
686
764
  { cat: 'CART', re: /\b(add(ed|ing)? to cart|added (dialog|modal|message|confirmation)|cart (page|table|line|item)|view cart|continue shopping|quantit)\b/ },
@@ -693,8 +771,13 @@ const CATEGORY_SIGNALS = [
693
771
  // SEC, so the linter told QA to re-tag genuine auth-gate tests as navigation — diluting the
694
772
  // visibility of the security suite (QA field report, 3.2.23). The guard vocabulary below is
695
773
  // what makes the INTENT matchable, and GUARD_INTENT then wins over a mere observable.
696
- { cat: 'SEC', re: /\b(xss|sql|injection|payload|without authentication|unauthenticated|without an? (?:authenticated|valid|active) \w+|direct(?:ly)? access\w*|deep[- ]link\w*|auth[- ]?guard|not skippable|without having (?:completed|submitted|logged)|remains? unauthenticated|\binert\b|tamper\w*|malformed|url parameter|query param\w*|falls? back|gracefull?y|without a crash|not[- ]found|\b404\b|special character|abuse)\b/ },
774
+ { cat: 'SEC', re: /\b(xss|sql|injection|payload|without authentication|unauthenticated|without an? (?:authenticated|valid|active) \w+|direct(?:ly)? access\w*|auth[- ]?guard|not skippable|without having (?:completed|submitted|logged)|remains? unauthenticated|\binert\b|tamper\w*|malformed|special character|abuse)\b/ },
775
+ // Robustness and routing words are SEC evidence only beside an ACCESS word. Alone they describe
776
+ // routing — "Unknown route shows the 404 page", "Deep link opens the item", "the tab from the url
777
+ // parameter" — and the linter told QA to re-tag those navigation tests as VP-SEC (#888).
778
+ { cat: 'SEC', re: /\b(deep[- ]link\w*|url parameter|query param\w*|falls? back|gracefull?y|without a crash|not[- ]found|\b404\b)\b/, requires: ACCESS_CONTEXT },
697
779
  ];
780
+ const signalMatches = (c, title) => c.re.test(title) && (!c.requires || c.requires.test(title));
698
781
  /**
699
782
  * Categories whose signal describes the test's INTENT/risk rather than the observable action.
700
783
  * When one of these matches, a competing observable-only category (NAV: "redirects", "navigates")
@@ -712,15 +795,21 @@ function taxonomyLint(scenarios) {
712
795
  continue;
713
796
  checked++;
714
797
  const title = s.name.toLowerCase();
715
- const matched = [...new Set(CATEGORY_SIGNALS.filter((c) => c.re.test(title)).map((c) => c.cat))];
798
+ const matched = [...new Set(CATEGORY_SIGNALS.filter((c) => signalMatches(c, title)).map((c) => c.cat))];
716
799
  if (matched.includes(cat))
717
800
  continue; // title supports its own category → fine
801
+ // A gate (`requires`) only stops a word from SUGGESTING its category. An author who already
802
+ // chose that category is supported by the word alone: a VP-SEC "Deep link to the filtered
803
+ // list …" stays SEC instead of being pushed toward FILTER (#888 review).
804
+ if (CATEGORY_SIGNALS.some((c) => c.cat === cat && c.requires && c.re.test(title)))
805
+ continue;
718
806
  // The declared category may be an INTENT category whose signal this title spells
719
807
  // differently; never "correct" it toward a category that only names the observable.
720
808
  const suppressed = INTENT_OVER_OBSERVABLE[cat];
721
809
  const others = matched.filter((c) => c !== cat && !(suppressed && suppressed.has(c)));
722
810
  if (others.length === 1) { // unambiguous mismatch
723
- const sig = CATEGORY_SIGNALS.find((c) => c.cat === others[0]);
811
+ // The entry that MATCHED — a category can have several (SEC: guard words, gated robustness words).
812
+ const sig = CATEGORY_SIGNALS.find((c) => c.cat === others[0] && signalMatches(c, title));
724
813
  const m = title.match(sig.re);
725
814
  mislabeled.push({ name: s.name, current: cat, suggested: others[0], signal: m ? m[0] : others[0] });
726
815
  }
@@ -790,9 +879,8 @@ function numericClaimGaps(scenarios) {
790
879
  const claimed = NUMBER_WORDS[m[1]] ?? Number(m[1]);
791
880
  if (!Number.isFinite(claimed) || claimed < 2)
792
881
  continue;
793
- // Only value-bearing assertions count: `see [X] … with/contains {{v}}`. A visibility check
794
- // does not demonstrate one of N values.
795
- const asserted = (s.stepsText.match(/\bsee \[[^\]]+\][^|]*?\b(?:with|contains) \{\{/g) ?? []).length;
882
+ // Values, positive states and indicator presence count; plain text visibility does not (#866).
883
+ const asserted = (0, counted_assertions_1.countedAssertions)(s.stepsText);
796
884
  if (asserted > 0 && asserted < claimed)
797
885
  out.push({ name: s.name, claimed, asserted, noun: m[2] });
798
886
  }
@@ -804,16 +892,18 @@ function numericClaimGaps(scenarios) {
804
892
  * The Priority-Viewpoints table is where release selection is supposed to come from. When the
805
893
  * table says a flow is `Low` and its scenario is tagged `@high`, a smoke run picks up work the QA
806
894
  * deliberately deprioritised — and nobody can tell which of the two was the decision (#622).
895
+ *
896
+ * Reads the SAME parse traceability does (`parseViewpointOverview`). It used to scan the raw text
897
+ * for any `| VP-… | high |` row, so one audit run "saw" an id for this check and not for
898
+ * traceability (#833), and a row in a Known Issues table could raise a contradiction.
807
899
  */
808
- function priorityMismatches(viewpointText, scenarios) {
900
+ function priorityMismatches(viewpoints, scenarios) {
809
901
  const declared = new Map();
810
- for (const m of viewpointText.matchAll(/^\|\s*((?:VP|FL)[A-Z0-9._-]*)\s*\|\s*(critical|high|medium|normal|low|deferred)\s*\|/gim)) {
811
- declared.set(m[1].toUpperCase(), m[2].toLowerCase());
812
- }
902
+ for (const v of viewpoints)
903
+ if (v.priorityWord)
904
+ declared.set(v.id.toUpperCase(), v.priorityWord);
813
905
  if (declared.size === 0)
814
906
  return [];
815
- // `medium` and `normal` are the same rank under different names in real documents.
816
- const rank = (p) => (p === 'medium' ? 'normal' : p);
817
907
  const out = [];
818
908
  for (const s of scenarios) {
819
909
  const id = (s.vpId ?? '').toUpperCase();
@@ -823,13 +913,17 @@ function priorityMismatches(viewpointText, scenarios) {
823
913
  const key = [...declared.keys()].filter((k) => id.startsWith(k)).sort((a, b) => b.length - a.length)[0];
824
914
  if (!key)
825
915
  continue;
826
- const want = rank(declared.get(key));
827
- const got = rank(String(s.priority).toLowerCase());
828
- // `critical` and `deferred` have no tag equivalent — nothing to contradict.
829
- if (want === 'critical' || want === 'deferred')
916
+ // Both sides fold through the one priority reading (`critical` ≡ high, `medium`/`med` ≡ normal).
917
+ const want = (0, viewpoint_priority_1.parsePriority)(declared.get(key));
918
+ // `deferred` and `skip` (declared not applicable, #853) have no tag equivalent — nothing to contradict.
919
+ if (want === 'deferred' || want === 'skip')
920
+ continue;
921
+ // An untagged scenario states no priority, so it cannot contradict one (#861).
922
+ const tagged = s.priorityTag ?? (s.priority === 'unknown' ? undefined : String(s.priority));
923
+ if (!tagged)
830
924
  continue;
831
- if (want !== got)
832
- out.push({ id: key, declared: declared.get(key), tagged: got, scenario: s.name });
925
+ if (want !== (0, viewpoint_priority_1.parsePriority)(tagged))
926
+ out.push({ id: key, declared: declared.get(key), tagged, scenario: s.name });
833
927
  }
834
928
  return out;
835
929
  }