@sun-asterisk/sungen 3.2.28 → 3.2.30

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 (486) hide show
  1. package/dist/capabilities/discover.d.ts +29 -0
  2. package/dist/capabilities/discover.d.ts.map +1 -1
  3. package/dist/capabilities/discover.js +144 -10
  4. package/dist/capabilities/discover.js.map +1 -1
  5. package/dist/capabilities/registry.d.ts +18 -0
  6. package/dist/capabilities/registry.d.ts.map +1 -1
  7. package/dist/capabilities/registry.js +25 -0
  8. package/dist/capabilities/registry.js.map +1 -1
  9. package/dist/cli/commands/audit.d.ts.map +1 -1
  10. package/dist/cli/commands/audit.js +9 -0
  11. package/dist/cli/commands/audit.js.map +1 -1
  12. package/dist/cli/commands/capability.js +1 -1
  13. package/dist/cli/commands/capability.js.map +1 -1
  14. package/dist/cli/commands/delivery.d.ts.map +1 -1
  15. package/dist/cli/commands/delivery.js +2 -1
  16. package/dist/cli/commands/delivery.js.map +1 -1
  17. package/dist/cli/commands/generate.d.ts.map +1 -1
  18. package/dist/cli/commands/generate.js +6 -2
  19. package/dist/cli/commands/generate.js.map +1 -1
  20. package/dist/cli/commands/inspect.js +1 -1
  21. package/dist/cli/commands/inspect.js.map +1 -1
  22. package/dist/cli/commands/results-merge.d.ts.map +1 -1
  23. package/dist/cli/commands/results-merge.js +9 -2
  24. package/dist/cli/commands/results-merge.js.map +1 -1
  25. package/dist/cli/commands/results-sanitize.d.ts +24 -0
  26. package/dist/cli/commands/results-sanitize.d.ts.map +1 -0
  27. package/dist/cli/commands/results-sanitize.js +126 -0
  28. package/dist/cli/commands/results-sanitize.js.map +1 -0
  29. package/dist/cli/commands/script-check.d.ts.map +1 -1
  30. package/dist/cli/commands/script-check.js +3 -1
  31. package/dist/cli/commands/script-check.js.map +1 -1
  32. package/dist/cli/commands/update.d.ts.map +1 -1
  33. package/dist/cli/commands/update.js +3 -0
  34. package/dist/cli/commands/update.js.map +1 -1
  35. package/dist/dashboard/templates/index.html +1 -1
  36. package/dist/exporters/api-testcase-formatter.d.ts +3 -6
  37. package/dist/exporters/api-testcase-formatter.d.ts.map +1 -1
  38. package/dist/exporters/api-testcase-formatter.js +7 -10
  39. package/dist/exporters/api-testcase-formatter.js.map +1 -1
  40. package/dist/exporters/feature-parser.d.ts +1 -1
  41. package/dist/exporters/feature-parser.js +1 -1
  42. package/dist/exporters/matrix/build.d.ts.map +1 -1
  43. package/dist/exporters/matrix/build.js +18 -3
  44. package/dist/exporters/matrix/build.js.map +1 -1
  45. package/dist/exporters/matrix/item-labels.d.ts +35 -0
  46. package/dist/exporters/matrix/item-labels.d.ts.map +1 -0
  47. package/dist/exporters/matrix/item-labels.js +90 -0
  48. package/dist/exporters/matrix/item-labels.js.map +1 -0
  49. package/dist/exporters/matrix/render-coverage-sheet.d.ts +14 -0
  50. package/dist/exporters/matrix/render-coverage-sheet.d.ts.map +1 -0
  51. package/dist/exporters/matrix/render-coverage-sheet.js +162 -0
  52. package/dist/exporters/matrix/render-coverage-sheet.js.map +1 -0
  53. package/dist/exporters/matrix/render-csv.d.ts.map +1 -1
  54. package/dist/exporters/matrix/render-csv.js +3 -1
  55. package/dist/exporters/matrix/render-csv.js.map +1 -1
  56. package/dist/exporters/matrix/render-overview-sheet.d.ts +20 -0
  57. package/dist/exporters/matrix/render-overview-sheet.d.ts.map +1 -0
  58. package/dist/exporters/matrix/render-overview-sheet.js +32 -0
  59. package/dist/exporters/matrix/render-overview-sheet.js.map +1 -0
  60. package/dist/exporters/matrix/render-testcase-sheet.d.ts +30 -0
  61. package/dist/exporters/matrix/render-testcase-sheet.d.ts.map +1 -0
  62. package/dist/exporters/matrix/render-testcase-sheet.js +156 -0
  63. package/dist/exporters/matrix/render-testcase-sheet.js.map +1 -0
  64. package/dist/exporters/matrix/render-xlsx.d.ts +41 -31
  65. package/dist/exporters/matrix/render-xlsx.d.ts.map +1 -1
  66. package/dist/exporters/matrix/render-xlsx.js +72 -425
  67. package/dist/exporters/matrix/render-xlsx.js.map +1 -1
  68. package/dist/exporters/matrix/result-totals.d.ts +23 -0
  69. package/dist/exporters/matrix/result-totals.d.ts.map +1 -0
  70. package/dist/exporters/matrix/result-totals.js +21 -0
  71. package/dist/exporters/matrix/result-totals.js.map +1 -0
  72. package/dist/exporters/matrix/testcase-summary-band.d.ts +30 -0
  73. package/dist/exporters/matrix/testcase-summary-band.d.ts.map +1 -0
  74. package/dist/exporters/matrix/testcase-summary-band.js +71 -0
  75. package/dist/exporters/matrix/testcase-summary-band.js.map +1 -0
  76. package/dist/exporters/matrix/wording.d.ts.map +1 -1
  77. package/dist/exporters/matrix/wording.js +13 -0
  78. package/dist/exporters/matrix/wording.js.map +1 -1
  79. package/dist/exporters/matrix/xlsx-cells.d.ts +38 -0
  80. package/dist/exporters/matrix/xlsx-cells.d.ts.map +1 -0
  81. package/dist/exporters/matrix/xlsx-cells.js +52 -0
  82. package/dist/exporters/matrix/xlsx-cells.js.map +1 -0
  83. package/dist/exporters/qa-env-secret-denylist.js +2 -2
  84. package/dist/exporters/qa-env-secret-denylist.js.map +1 -1
  85. package/dist/exporters/report-path-sanitizer.d.ts +38 -0
  86. package/dist/exporters/report-path-sanitizer.d.ts.map +1 -0
  87. package/dist/exporters/report-path-sanitizer.js +137 -0
  88. package/dist/exporters/report-path-sanitizer.js.map +1 -0
  89. package/dist/exporters/result-variants.d.ts.map +1 -1
  90. package/dist/exporters/result-variants.js +2 -1
  91. package/dist/exporters/result-variants.js.map +1 -1
  92. package/dist/exporters/sensitive-key.d.ts +31 -0
  93. package/dist/exporters/sensitive-key.d.ts.map +1 -0
  94. package/dist/exporters/sensitive-key.js +50 -0
  95. package/dist/exporters/sensitive-key.js.map +1 -0
  96. package/dist/exporters/test-data-resolver.d.ts +4 -1
  97. package/dist/exporters/test-data-resolver.d.ts.map +1 -1
  98. package/dist/exporters/test-data-resolver.js +12 -2
  99. package/dist/exporters/test-data-resolver.js.map +1 -1
  100. package/dist/exporters/xlsx-report-builder.d.ts +12 -1
  101. package/dist/exporters/xlsx-report-builder.d.ts.map +1 -1
  102. package/dist/exporters/xlsx-report-builder.js +10 -2
  103. package/dist/exporters/xlsx-report-builder.js.map +1 -1
  104. package/dist/generators/gherkin-parser/index.d.ts +10 -0
  105. package/dist/generators/gherkin-parser/index.d.ts.map +1 -1
  106. package/dist/generators/gherkin-parser/index.js +20 -12
  107. package/dist/generators/gherkin-parser/index.js.map +1 -1
  108. package/dist/generators/gherkin-parser/parent-scope-clause.d.ts +54 -0
  109. package/dist/generators/gherkin-parser/parent-scope-clause.d.ts.map +1 -0
  110. package/dist/generators/gherkin-parser/parent-scope-clause.js +109 -0
  111. package/dist/generators/gherkin-parser/parent-scope-clause.js.map +1 -0
  112. package/dist/generators/test-generator/adapters/adapter-interface.d.ts +23 -18
  113. package/dist/generators/test-generator/adapters/adapter-interface.d.ts.map +1 -1
  114. package/dist/generators/test-generator/adapters/appium/appium-adapter.d.ts +4 -19
  115. package/dist/generators/test-generator/adapters/appium/appium-adapter.d.ts.map +1 -1
  116. package/dist/generators/test-generator/adapters/appium/appium-adapter.js.map +1 -1
  117. package/dist/generators/test-generator/adapters/appium/os-support.d.ts +53 -0
  118. package/dist/generators/test-generator/adapters/appium/os-support.d.ts.map +1 -0
  119. package/dist/generators/test-generator/adapters/appium/os-support.js +200 -0
  120. package/dist/generators/test-generator/adapters/appium/os-support.js.map +1 -0
  121. package/dist/generators/test-generator/adapters/appium/templates/after-all.hbs +18 -0
  122. package/dist/generators/test-generator/adapters/appium/templates/after-each.hbs +18 -0
  123. package/dist/generators/test-generator/adapters/appium/templates/before-all.hbs +18 -0
  124. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/alert-fill-action.hbs +9 -2
  125. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/capture-variable.hbs +24 -1
  126. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/click-at-position-action.hbs +1 -0
  127. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/click-element-with-text.hbs +1 -1
  128. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/double-click-action.hbs +7 -0
  129. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/frame-enter-action.hbs +3 -6
  130. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/hover-action.hbs +6 -2
  131. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/hover-element-with-text.hbs +4 -3
  132. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/table-paginate-action.hbs +3 -0
  133. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/unknown-element-action.hbs +9 -0
  134. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/have-value-assertion.hbs +34 -1
  135. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/label-value-assertion.hbs +14 -6
  136. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/visible-assertion.hbs +1 -1
  137. package/dist/generators/test-generator/adapters/appium/templates/steps/gestures/go-back-action.hbs +21 -0
  138. package/dist/generators/test-generator/adapters/appium/templates/steps/gestures/long-press-action.hbs +4 -0
  139. package/dist/generators/test-generator/adapters/appium/templates/steps/gestures/pinch-zoom-action.hbs +4 -0
  140. package/dist/generators/test-generator/adapters/appium/templates/steps/gestures/set-geolocation-action.hbs +16 -0
  141. package/dist/generators/test-generator/adapters/appium/templates/steps/partials/locator.hbs +9 -1
  142. package/dist/generators/test-generator/adapters/appium/templates/test-file.hbs +62 -23
  143. package/dist/generators/test-generator/adapters/index.d.ts +1 -1
  144. package/dist/generators/test-generator/adapters/index.d.ts.map +1 -1
  145. package/dist/generators/test-generator/adapters/playwright/playwright-adapter.d.ts +4 -19
  146. package/dist/generators/test-generator/adapters/playwright/playwright-adapter.d.ts.map +1 -1
  147. package/dist/generators/test-generator/adapters/playwright/playwright-adapter.js.map +1 -1
  148. package/dist/generators/test-generator/adapters/playwright/templates/after-all.hbs +19 -1
  149. package/dist/generators/test-generator/adapters/playwright/templates/after-each.hbs +18 -0
  150. package/dist/generators/test-generator/adapters/playwright/templates/before-all.hbs +19 -1
  151. package/dist/generators/test-generator/adapters/playwright/templates/imports.hbs +3 -0
  152. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/check-action.hbs +6 -1
  153. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/click-at-position-action.hbs +23 -0
  154. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/expand-action.hbs +8 -8
  155. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/fill-editor-action.hbs +7 -2
  156. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/table-action-in-row-nth.hbs +7 -2
  157. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/table-action-in-row.hbs +7 -2
  158. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/table-paginate-action.hbs +5 -0
  159. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/uncheck-action.hbs +3 -1
  160. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/unknown-element-action.hbs +1 -1
  161. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/wait-for-page.hbs +18 -1
  162. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/all-contain-assertion.hbs +32 -4
  163. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/all-contain-element.hbs +5 -2
  164. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/checked-assertion.hbs +5 -1
  165. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/column-cell-assertion.hbs +13 -2
  166. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/contain-text-assertion.hbs +1 -1
  167. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-role-variable-assertion.hbs +2 -2
  168. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-variable-assertion.hbs +1 -1
  169. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/have-text-assertion.hbs +1 -1
  170. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-role-variable-assertion.hbs +2 -2
  171. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-variable-assertion.hbs +1 -1
  172. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/not-checked-assertion.hbs +2 -1
  173. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/selected-assertion.hbs +21 -3
  174. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/state-with-filter-assertion.hbs +20 -2
  175. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-empty.hbs +4 -1
  176. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-match-data.hbs +4 -1
  177. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-count.hbs +4 -1
  178. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-exists.hbs +12 -4
  179. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-not-exists.hbs +14 -2
  180. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-role-variable-assertion.hbs +3 -3
  181. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-value-assertion.hbs +1 -1
  182. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-variable-assertion.hbs +1 -1
  183. package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/checked-opts.hbs +8 -0
  184. package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/locator-base.hbs +8 -8
  185. package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/locator-nth.hbs +1 -1
  186. package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/locator-strategies/id.hbs +1 -1
  187. package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/locator-strategies/testid.hbs +1 -1
  188. package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/locator.hbs +8 -8
  189. package/dist/generators/test-generator/adapters/playwright/templates/test-file.hbs +10 -8
  190. package/dist/generators/test-generator/code-generator.d.ts +37 -0
  191. package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
  192. package/dist/generators/test-generator/code-generator.js +165 -40
  193. package/dist/generators/test-generator/code-generator.js.map +1 -1
  194. package/dist/generators/test-generator/diagnostics.d.ts +116 -6
  195. package/dist/generators/test-generator/diagnostics.d.ts.map +1 -1
  196. package/dist/generators/test-generator/diagnostics.js +115 -5
  197. package/dist/generators/test-generator/diagnostics.js.map +1 -1
  198. package/dist/generators/test-generator/patterns/index.d.ts +57 -11
  199. package/dist/generators/test-generator/patterns/index.d.ts.map +1 -1
  200. package/dist/generators/test-generator/patterns/index.js +163 -21
  201. package/dist/generators/test-generator/patterns/index.js.map +1 -1
  202. package/dist/generators/test-generator/patterns/types.d.ts +8 -0
  203. package/dist/generators/test-generator/patterns/types.d.ts.map +1 -1
  204. package/dist/generators/test-generator/patterns/with-parent-scope.d.ts +18 -0
  205. package/dist/generators/test-generator/patterns/with-parent-scope.d.ts.map +1 -0
  206. package/dist/generators/test-generator/patterns/with-parent-scope.js +40 -0
  207. package/dist/generators/test-generator/patterns/with-parent-scope.js.map +1 -0
  208. package/dist/generators/test-generator/step-mapper.d.ts +103 -10
  209. package/dist/generators/test-generator/step-mapper.d.ts.map +1 -1
  210. package/dist/generators/test-generator/step-mapper.js +266 -45
  211. package/dist/generators/test-generator/step-mapper.js.map +1 -1
  212. package/dist/generators/test-generator/template-engine.d.ts +4 -19
  213. package/dist/generators/test-generator/template-engine.d.ts.map +1 -1
  214. package/dist/generators/test-generator/template-engine.js +17 -12
  215. package/dist/generators/test-generator/template-engine.js.map +1 -1
  216. package/dist/generators/test-generator/utils/data-resolver.d.ts +7 -0
  217. package/dist/generators/test-generator/utils/data-resolver.d.ts.map +1 -1
  218. package/dist/generators/test-generator/utils/data-resolver.js +19 -2
  219. package/dist/generators/test-generator/utils/data-resolver.js.map +1 -1
  220. package/dist/generators/test-generator/utils/dialog-scope-identity.d.ts +41 -0
  221. package/dist/generators/test-generator/utils/dialog-scope-identity.d.ts.map +1 -0
  222. package/dist/generators/test-generator/utils/dialog-scope-identity.js +61 -0
  223. package/dist/generators/test-generator/utils/dialog-scope-identity.js.map +1 -0
  224. package/dist/generators/test-generator/utils/escape-js-string.d.ts +17 -0
  225. package/dist/generators/test-generator/utils/escape-js-string.d.ts.map +1 -0
  226. package/dist/generators/test-generator/utils/escape-js-string.js +29 -0
  227. package/dist/generators/test-generator/utils/escape-js-string.js.map +1 -0
  228. package/dist/generators/test-generator/utils/nearest-match.d.ts +24 -0
  229. package/dist/generators/test-generator/utils/nearest-match.d.ts.map +1 -0
  230. package/dist/generators/test-generator/utils/nearest-match.js +56 -0
  231. package/dist/generators/test-generator/utils/nearest-match.js.map +1 -0
  232. package/dist/generators/test-generator/utils/selector-entry-fields.d.ts +58 -0
  233. package/dist/generators/test-generator/utils/selector-entry-fields.d.ts.map +1 -0
  234. package/dist/generators/test-generator/utils/selector-entry-fields.js +119 -0
  235. package/dist/generators/test-generator/utils/selector-entry-fields.js.map +1 -0
  236. package/dist/generators/test-generator/utils/selector-entry-walk.d.ts +25 -0
  237. package/dist/generators/test-generator/utils/selector-entry-walk.d.ts.map +1 -0
  238. package/dist/generators/test-generator/utils/selector-entry-walk.js +54 -0
  239. package/dist/generators/test-generator/utils/selector-entry-walk.js.map +1 -0
  240. package/dist/generators/test-generator/utils/selector-nth-validation.d.ts +59 -0
  241. package/dist/generators/test-generator/utils/selector-nth-validation.d.ts.map +1 -0
  242. package/dist/generators/test-generator/utils/selector-nth-validation.js +91 -0
  243. package/dist/generators/test-generator/utils/selector-nth-validation.js.map +1 -0
  244. package/dist/generators/test-generator/utils/selector-resolver.d.ts +53 -2
  245. package/dist/generators/test-generator/utils/selector-resolver.d.ts.map +1 -1
  246. package/dist/generators/test-generator/utils/selector-resolver.js +273 -27
  247. package/dist/generators/test-generator/utils/selector-resolver.js.map +1 -1
  248. package/dist/generators/test-generator/utils/selector-type-validation.d.ts +51 -0
  249. package/dist/generators/test-generator/utils/selector-type-validation.d.ts.map +1 -0
  250. package/dist/generators/test-generator/utils/selector-type-validation.js +77 -0
  251. package/dist/generators/test-generator/utils/selector-type-validation.js.map +1 -0
  252. package/dist/harness/audit.d.ts +3 -1
  253. package/dist/harness/audit.d.ts.map +1 -1
  254. package/dist/harness/audit.js +51 -28
  255. package/dist/harness/audit.js.map +1 -1
  256. package/dist/harness/capability-plan.d.ts +4 -0
  257. package/dist/harness/capability-plan.d.ts.map +1 -1
  258. package/dist/harness/capability-plan.js +32 -2
  259. package/dist/harness/capability-plan.js.map +1 -1
  260. package/dist/harness/catalog/drivers.yaml +1 -1
  261. package/dist/harness/catalog/universal-viewpoints.yaml +145 -0
  262. package/dist/harness/data-driven-lint.d.ts.map +1 -1
  263. package/dist/harness/data-driven-lint.js +217 -33
  264. package/dist/harness/data-driven-lint.js.map +1 -1
  265. package/dist/harness/parse.d.ts +6 -0
  266. package/dist/harness/parse.d.ts.map +1 -1
  267. package/dist/harness/parse.js +1 -1
  268. package/dist/harness/parse.js.map +1 -1
  269. package/dist/harness/repair.d.ts.map +1 -1
  270. package/dist/harness/repair.js +8 -1
  271. package/dist/harness/repair.js.map +1 -1
  272. package/dist/harness/script-check.d.ts +2 -2
  273. package/dist/harness/script-check.d.ts.map +1 -1
  274. package/dist/harness/script-check.js +186 -25
  275. package/dist/harness/script-check.js.map +1 -1
  276. package/dist/harness/sensors.d.ts +48 -0
  277. package/dist/harness/sensors.d.ts.map +1 -1
  278. package/dist/harness/sensors.js +26 -1
  279. package/dist/harness/sensors.js.map +1 -1
  280. package/dist/harness/viewpoint-ledger.d.ts +10 -0
  281. package/dist/harness/viewpoint-ledger.d.ts.map +1 -1
  282. package/dist/harness/viewpoint-ledger.js +23 -2
  283. package/dist/harness/viewpoint-ledger.js.map +1 -1
  284. package/dist/index.d.ts +2 -0
  285. package/dist/index.d.ts.map +1 -1
  286. package/dist/index.js +10 -1
  287. package/dist/index.js.map +1 -1
  288. package/dist/orchestrator/project-initializer.d.ts +6 -0
  289. package/dist/orchestrator/project-initializer.d.ts.map +1 -1
  290. package/dist/orchestrator/project-initializer.js +16 -0
  291. package/dist/orchestrator/project-initializer.js.map +1 -1
  292. package/dist/orchestrator/report-sanitize-reporter-install.d.ts +24 -0
  293. package/dist/orchestrator/report-sanitize-reporter-install.d.ts.map +1 -0
  294. package/dist/orchestrator/report-sanitize-reporter-install.js +161 -0
  295. package/dist/orchestrator/report-sanitize-reporter-install.js.map +1 -0
  296. package/dist/orchestrator/templates/ai-src/commands/delivery.md +4 -3
  297. package/dist/orchestrator/templates/ai-src/commands/run-test.md +9 -1
  298. package/dist/orchestrator/templates/ai-src/skills/sungen-api-coverage-model/SKILL.md +10 -0
  299. package/dist/orchestrator/templates/ai-src/skills/sungen-delivery/SKILL.md +14 -5
  300. package/dist/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +62 -3
  301. package/dist/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +126 -11
  302. package/dist/orchestrator/templates/ai-src/skills/sungen-mobile-gestures/SKILL.md +16 -1
  303. package/dist/orchestrator/templates/ai-src/skills/sungen-selector-fix/SKILL.md +12 -0
  304. package/dist/orchestrator/templates/ai-src/skills/sungen-selector-keys/SKILL.md +19 -5
  305. package/dist/orchestrator/templates/ai-src/skills/sungen-tc-generation/SKILL.md +88 -2
  306. package/dist/orchestrator/templates/ai-src/skills/sungen-tc-review/SKILL.md +62 -5
  307. package/dist/orchestrator/templates/ai-src/skills/sungen-test-design-techniques/SKILL.md +13 -0
  308. package/dist/orchestrator/templates/ai-src/skills/sungen-viewpoint/SKILL.md +59 -10
  309. package/dist/orchestrator/templates/ai-src/skills/sungen-viewpoint/group-f-mobile-native.md +419 -0
  310. package/dist/orchestrator/templates/playwright.config.ts +7 -0
  311. package/dist/orchestrator/templates/readme.md +1 -1
  312. package/dist/orchestrator/templates/specs-checked-state.d.ts +83 -0
  313. package/dist/orchestrator/templates/specs-checked-state.d.ts.map +1 -0
  314. package/dist/orchestrator/templates/specs-checked-state.js +261 -0
  315. package/dist/orchestrator/templates/specs-checked-state.js.map +1 -0
  316. package/dist/orchestrator/templates/specs-checked-state.ts +324 -0
  317. package/dist/orchestrator/templates/specs-pw-shape-reporter.ts +0 -0
  318. package/dist/orchestrator/templates/specs-report-path-sanitize-reporter.d.ts +36 -0
  319. package/dist/orchestrator/templates/specs-report-path-sanitize-reporter.d.ts.map +1 -0
  320. package/dist/orchestrator/templates/specs-report-path-sanitize-reporter.js +155 -0
  321. package/dist/orchestrator/templates/specs-report-path-sanitize-reporter.js.map +1 -0
  322. package/dist/orchestrator/templates/specs-report-path-sanitize-reporter.ts +142 -0
  323. package/dist/orchestrator/templates/specs-url-assert.d.ts +50 -25
  324. package/dist/orchestrator/templates/specs-url-assert.d.ts.map +1 -1
  325. package/dist/orchestrator/templates/specs-url-assert.js +65 -24
  326. package/dist/orchestrator/templates/specs-url-assert.js.map +1 -1
  327. package/dist/orchestrator/templates/specs-url-assert.ts +101 -28
  328. package/dist/orchestrator/templates/wdio.conf.ts +105 -1
  329. package/dist/utils/selector-types.d.ts +43 -1
  330. package/dist/utils/selector-types.d.ts.map +1 -1
  331. package/dist/utils/selector-types.js +51 -7
  332. package/dist/utils/selector-types.js.map +1 -1
  333. package/package.json +3 -3
  334. package/src/capabilities/discover.ts +146 -10
  335. package/src/capabilities/registry.ts +30 -0
  336. package/src/cli/commands/audit.ts +9 -0
  337. package/src/cli/commands/capability.ts +1 -1
  338. package/src/cli/commands/delivery.ts +2 -1
  339. package/src/cli/commands/generate.ts +5 -2
  340. package/src/cli/commands/inspect.ts +1 -1
  341. package/src/cli/commands/results-merge.ts +9 -2
  342. package/src/cli/commands/results-sanitize.ts +98 -0
  343. package/src/cli/commands/script-check.ts +3 -1
  344. package/src/cli/commands/update.ts +3 -0
  345. package/src/dashboard/templates/index.html +1 -1
  346. package/src/exporters/api-testcase-formatter.ts +5 -7
  347. package/src/exporters/feature-parser.ts +1 -1
  348. package/src/exporters/matrix/build.ts +17 -3
  349. package/src/exporters/matrix/item-labels.ts +78 -0
  350. package/src/exporters/matrix/render-coverage-sheet.ts +170 -0
  351. package/src/exporters/matrix/render-csv.ts +3 -1
  352. package/src/exporters/matrix/render-overview-sheet.ts +51 -0
  353. package/src/exporters/matrix/render-testcase-sheet.ts +178 -0
  354. package/src/exporters/matrix/render-xlsx.ts +67 -448
  355. package/src/exporters/matrix/result-totals.ts +37 -0
  356. package/src/exporters/matrix/testcase-summary-band.ts +74 -0
  357. package/src/exporters/matrix/wording.ts +13 -0
  358. package/src/exporters/matrix/xlsx-cells.ts +56 -0
  359. package/src/exporters/qa-env-secret-denylist.ts +1 -1
  360. package/src/exporters/report-path-sanitizer.ts +144 -0
  361. package/src/exporters/result-variants.ts +2 -1
  362. package/src/exporters/sensitive-key.ts +48 -0
  363. package/src/exporters/test-data-resolver.ts +12 -2
  364. package/src/exporters/xlsx-report-builder.ts +16 -2
  365. package/src/generators/gherkin-parser/index.ts +22 -11
  366. package/src/generators/gherkin-parser/parent-scope-clause.ts +130 -0
  367. package/src/generators/test-generator/adapters/adapter-interface.ts +25 -3
  368. package/src/generators/test-generator/adapters/appium/appium-adapter.ts +4 -4
  369. package/src/generators/test-generator/adapters/appium/os-support.ts +176 -0
  370. package/src/generators/test-generator/adapters/appium/templates/after-all.hbs +18 -0
  371. package/src/generators/test-generator/adapters/appium/templates/after-each.hbs +18 -0
  372. package/src/generators/test-generator/adapters/appium/templates/before-all.hbs +18 -0
  373. package/src/generators/test-generator/adapters/appium/templates/steps/actions/alert-fill-action.hbs +9 -2
  374. package/src/generators/test-generator/adapters/appium/templates/steps/actions/capture-variable.hbs +24 -1
  375. package/src/generators/test-generator/adapters/appium/templates/steps/actions/click-at-position-action.hbs +1 -0
  376. package/src/generators/test-generator/adapters/appium/templates/steps/actions/click-element-with-text.hbs +1 -1
  377. package/src/generators/test-generator/adapters/appium/templates/steps/actions/double-click-action.hbs +7 -0
  378. package/src/generators/test-generator/adapters/appium/templates/steps/actions/frame-enter-action.hbs +3 -6
  379. package/src/generators/test-generator/adapters/appium/templates/steps/actions/hover-action.hbs +6 -2
  380. package/src/generators/test-generator/adapters/appium/templates/steps/actions/hover-element-with-text.hbs +4 -3
  381. package/src/generators/test-generator/adapters/appium/templates/steps/actions/table-paginate-action.hbs +3 -0
  382. package/src/generators/test-generator/adapters/appium/templates/steps/actions/unknown-element-action.hbs +9 -0
  383. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/have-value-assertion.hbs +34 -1
  384. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/label-value-assertion.hbs +14 -6
  385. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/visible-assertion.hbs +1 -1
  386. package/src/generators/test-generator/adapters/appium/templates/steps/gestures/go-back-action.hbs +21 -0
  387. package/src/generators/test-generator/adapters/appium/templates/steps/gestures/long-press-action.hbs +4 -0
  388. package/src/generators/test-generator/adapters/appium/templates/steps/gestures/pinch-zoom-action.hbs +4 -0
  389. package/src/generators/test-generator/adapters/appium/templates/steps/gestures/set-geolocation-action.hbs +16 -0
  390. package/src/generators/test-generator/adapters/appium/templates/steps/partials/locator.hbs +9 -1
  391. package/src/generators/test-generator/adapters/appium/templates/test-file.hbs +62 -23
  392. package/src/generators/test-generator/adapters/index.ts +1 -1
  393. package/src/generators/test-generator/adapters/playwright/playwright-adapter.ts +4 -4
  394. package/src/generators/test-generator/adapters/playwright/templates/after-all.hbs +19 -1
  395. package/src/generators/test-generator/adapters/playwright/templates/after-each.hbs +18 -0
  396. package/src/generators/test-generator/adapters/playwright/templates/before-all.hbs +19 -1
  397. package/src/generators/test-generator/adapters/playwright/templates/imports.hbs +3 -0
  398. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/check-action.hbs +6 -1
  399. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/click-at-position-action.hbs +23 -0
  400. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/expand-action.hbs +8 -8
  401. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/fill-editor-action.hbs +7 -2
  402. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/table-action-in-row-nth.hbs +7 -2
  403. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/table-action-in-row.hbs +7 -2
  404. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/table-paginate-action.hbs +5 -0
  405. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/uncheck-action.hbs +3 -1
  406. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/unknown-element-action.hbs +1 -1
  407. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/wait-for-page.hbs +18 -1
  408. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/all-contain-assertion.hbs +32 -4
  409. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/all-contain-element.hbs +5 -2
  410. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/checked-assertion.hbs +5 -1
  411. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/column-cell-assertion.hbs +13 -2
  412. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/contain-text-assertion.hbs +1 -1
  413. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-role-variable-assertion.hbs +2 -2
  414. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-variable-assertion.hbs +1 -1
  415. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/have-text-assertion.hbs +1 -1
  416. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-role-variable-assertion.hbs +2 -2
  417. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-variable-assertion.hbs +1 -1
  418. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/not-checked-assertion.hbs +2 -1
  419. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/selected-assertion.hbs +21 -3
  420. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/state-with-filter-assertion.hbs +20 -2
  421. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-empty.hbs +4 -1
  422. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-match-data.hbs +4 -1
  423. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-count.hbs +4 -1
  424. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-exists.hbs +12 -4
  425. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-not-exists.hbs +14 -2
  426. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-role-variable-assertion.hbs +3 -3
  427. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-value-assertion.hbs +1 -1
  428. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-variable-assertion.hbs +1 -1
  429. package/src/generators/test-generator/adapters/playwright/templates/steps/partials/checked-opts.hbs +8 -0
  430. package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator-base.hbs +8 -8
  431. package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator-nth.hbs +1 -1
  432. package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator-strategies/id.hbs +1 -1
  433. package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator-strategies/testid.hbs +1 -1
  434. package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator.hbs +8 -8
  435. package/src/generators/test-generator/adapters/playwright/templates/test-file.hbs +10 -8
  436. package/src/generators/test-generator/code-generator.ts +181 -46
  437. package/src/generators/test-generator/diagnostics.ts +117 -6
  438. package/src/generators/test-generator/patterns/index.ts +175 -24
  439. package/src/generators/test-generator/patterns/types.ts +8 -0
  440. package/src/generators/test-generator/patterns/with-parent-scope.ts +41 -0
  441. package/src/generators/test-generator/step-mapper.ts +277 -43
  442. package/src/generators/test-generator/template-engine.ts +21 -21
  443. package/src/generators/test-generator/utils/data-resolver.ts +23 -2
  444. package/src/generators/test-generator/utils/dialog-scope-identity.ts +71 -0
  445. package/src/generators/test-generator/utils/escape-js-string.ts +24 -0
  446. package/src/generators/test-generator/utils/nearest-match.ts +55 -0
  447. package/src/generators/test-generator/utils/selector-entry-fields.ts +131 -0
  448. package/src/generators/test-generator/utils/selector-entry-walk.ts +58 -0
  449. package/src/generators/test-generator/utils/selector-nth-validation.ts +99 -0
  450. package/src/generators/test-generator/utils/selector-resolver.ts +333 -28
  451. package/src/generators/test-generator/utils/selector-type-validation.ts +87 -0
  452. package/src/harness/audit.ts +55 -30
  453. package/src/harness/capability-plan.ts +33 -1
  454. package/src/harness/catalog/drivers.yaml +1 -1
  455. package/src/harness/catalog/universal-viewpoints.yaml +145 -0
  456. package/src/harness/data-driven-lint.ts +192 -32
  457. package/src/harness/parse.ts +7 -1
  458. package/src/harness/repair.ts +8 -1
  459. package/src/harness/script-check.ts +186 -21
  460. package/src/harness/sensors.ts +75 -1
  461. package/src/harness/viewpoint-ledger.ts +26 -5
  462. package/src/index.ts +7 -0
  463. package/src/orchestrator/project-initializer.ts +17 -0
  464. package/src/orchestrator/report-sanitize-reporter-install.ts +109 -0
  465. package/src/orchestrator/templates/ai-src/commands/delivery.md +4 -3
  466. package/src/orchestrator/templates/ai-src/commands/run-test.md +9 -1
  467. package/src/orchestrator/templates/ai-src/skills/sungen-api-coverage-model/SKILL.md +10 -0
  468. package/src/orchestrator/templates/ai-src/skills/sungen-delivery/SKILL.md +14 -5
  469. package/src/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +62 -3
  470. package/src/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +126 -11
  471. package/src/orchestrator/templates/ai-src/skills/sungen-mobile-gestures/SKILL.md +16 -1
  472. package/src/orchestrator/templates/ai-src/skills/sungen-selector-fix/SKILL.md +12 -0
  473. package/src/orchestrator/templates/ai-src/skills/sungen-selector-keys/SKILL.md +19 -5
  474. package/src/orchestrator/templates/ai-src/skills/sungen-tc-generation/SKILL.md +88 -2
  475. package/src/orchestrator/templates/ai-src/skills/sungen-tc-review/SKILL.md +62 -5
  476. package/src/orchestrator/templates/ai-src/skills/sungen-test-design-techniques/SKILL.md +13 -0
  477. package/src/orchestrator/templates/ai-src/skills/sungen-viewpoint/SKILL.md +59 -10
  478. package/src/orchestrator/templates/ai-src/skills/sungen-viewpoint/group-f-mobile-native.md +419 -0
  479. package/src/orchestrator/templates/playwright.config.ts +7 -0
  480. package/src/orchestrator/templates/readme.md +1 -1
  481. package/src/orchestrator/templates/specs-checked-state.ts +324 -0
  482. package/src/orchestrator/templates/specs-pw-shape-reporter.ts +0 -0
  483. package/src/orchestrator/templates/specs-report-path-sanitize-reporter.ts +142 -0
  484. package/src/orchestrator/templates/specs-url-assert.ts +101 -28
  485. package/src/orchestrator/templates/wdio.conf.ts +105 -1
  486. package/src/utils/selector-types.ts +54 -5
@@ -13,20 +13,20 @@ import { checkViewpointBaseline, ViewpointBaseline } from './viewpoint-baseline'
13
13
  import { flowQuality, statefulDepthFor, continuityGaps, flowInventory, misfiledPhases, FlowQualityResult, InventoryResult } from './flow-contract';
14
14
  import { featureFilesFor } from './unit-paths';
15
15
  import {
16
- loadCatalog, viewpointGate, assertionDepth, dataThemesFor, depthThresholdFor, coverageBalance, duplicateClusters, traceability, claimProof, taxonomyLint,
16
+ loadCatalog, viewpointGate, assertionDepth, dataThemesFor, depthThresholdFor, coverageBalance, duplicateClusters, scenarioIdReuse, ReusedScenarioId, traceability, claimProof, taxonomyLint,
17
17
  automatableManual, flowCoveredThemes, flowRegressionDepth, oracleStrength, declaredPageType,
18
18
  numericClaimGaps, priorityMismatches,
19
19
  GateResult, DepthResult, BalanceResult, DuplicateResult, TraceResult, ClaimProofResult, TaxonomyResult, Catalog, AutomatableManualResult, FlowDepthResult, OracleStrengthResult,
20
20
  } from './sensors';
21
21
  import { loadFlowScenarios } from './flow-check';
22
- import { manualReasonMismatches, MANUAL_REASONS, buildPlan } from './capability-plan';
22
+ import { manualReasonMismatches, MANUAL_REASONS, buildPlan, KEEP_REASON_CODES, MANUAL_REASON_RANGE } from './capability-plan';
23
23
  import { readCapabilities, verificationScopeFindings } from './capability';
24
24
  import { readIntent, projectRootFromScreenDir, IntentProfile } from './intent';
25
25
  import { getProvenance, Provenance } from './provenance';
26
26
  import { specCoverage, SpecCoverageResult, parseSpecClauses, restatedRequirementSources } from './spec-coverage';
27
27
  import { downstreamScope, manualOracle, readText, DownstreamResult, ManualOracleResult,
28
28
  negativeSideEffect, sourceBacked, crossArtifactOwnership, isolationRisk, serialCascadeRisk } from './quality-gates';
29
- import { viewpointLedger, parseViewpointItems, browserGestureSubstitutions, viewpointIntegrity, LedgerResult } from './viewpoint-ledger';
29
+ import { viewpointLedger, parseViewpointItems, browserGestureSubstitutions, substitutionRemedy, viewpointIntegrity, LedgerResult } from './viewpoint-ledger';
30
30
  import { specBranches, unenumeratedBranches, sameOracleClusters, permissionPairGaps, awaitingSeedData, unconsideredRisks, MULTI_SCREEN_RISKS } from './spec-branches';
31
31
  const MULTI_SCREEN_RISK_COUNT = MULTI_SCREEN_RISKS.length;
32
32
  import { capabilityRegistry } from '../capabilities/registry';
@@ -45,6 +45,8 @@ export interface AuditReport {
45
45
  duplicates: DuplicateResult;
46
46
  trace: TraceResult;
47
47
  taxonomyMismatch: boolean; // scenarios use IDs not in the project's test-viewpoint.md
48
+ /** #694 — two different scenarios in one .feature carrying the same VP id. Gate-blocking. */
49
+ reusedScenarioIds: ReusedScenarioId[];
48
50
  downstream: DownstreamResult; // downstream screens referenced but under-covered
49
51
  manualOracle: ManualOracleResult; // @manual scenarios lacking setup/action/oracle
50
52
  automatableManual: AutomatableManualResult; // @manual that is actually automatable (deferred, not judgment) — TQ-2
@@ -460,30 +462,15 @@ export function runAudit(screenDir: string, screenName: string): AuditReport {
460
462
  if (!flowQ.contract!.minimalGuarantee) {
461
463
  findings.push('FLOW-GUARANTEE-MISSING: the contract declares no `minimalGuarantee:` — the postcondition that must hold in EVERY flow, including failure ("no second account for the same email", "no verification mail on a rejected submit"). Exception/guard scenarios have nothing to assert against without it; add it (and `successGuarantee:` for the goal-reached side).');
462
464
  }
463
- // #599 — integrity of the DECLARATION itself: three ways it can be internally wrong while
464
- // every coverage number still reads well.
465
- {
466
- const testDataDir = path.join(screenDir, 'test-data');
467
- const extra: Array<{ label: string; text: string }> = [];
468
- try {
469
- for (const f of fs.readdirSync(testDataDir).filter((x) => x.endsWith('.yaml'))) {
470
- extra.push({ label: `test-data/${f}`, text: readTextFile(path.join(testDataDir, f)) ?? '' });
471
- }
472
- } catch { /* api units and fresh scaffolds carry none */ }
473
- const vi = viewpointIntegrity(viewpointPath, scenarios.map((sc) => sc.vpId ?? '').filter(Boolean), extra);
474
- for (const d of vi.duplicateIds.slice(0, 4)) {
475
- findings.push(`VIEWPOINT-ID-REUSED: "${d.id}" labels ${d.count} different claims (${d.texts.map((t) => `"${t.slice(0, 44)}…"`).join(' · ')}). The ledger then counts ${d.count} items while traceability sees ONE id, so both the coverage arithmetic and "which test proves this?" go wrong — and neither number looks suspicious. Give each atomic claim its own id; several ids may share a flow.`);
476
- }
477
- for (const d of vi.danglingRefs.slice(0, 5)) {
478
- findings.push(`TRACE-REF-DANGLING: ${d.where} cites "${d.ref}", which no scenario carries. Nothing breaks at runtime, so a wrong pointer survives every refactor and quietly misleads the next maintainer. Fix the reference, or the scenario id it was meant to name.`);
479
- }
480
- if (vi.uniformPriority) {
481
- findings.push(`VIEWPOINT-PRIORITY-UNIFORM: all ${vi.uniformPriority.rows} rows of the Priority Viewpoints table are "${vi.uniformPriority.levels[0]}". That is a formality, not a priority: nothing can be selected for a smoke run and the release conversation has no input. Rank by business impact and risk — the basic flow and the data-integrity guards are not the same bet as an exit path a screen suite already covers.`);
482
- }
483
- }
484
465
  // #595 — a viewpoint item naming a browser-level gesture, answered with an in-app control.
485
466
  for (const g of browserGestureSubstitutions(viewpointPath, scenarios, platform).slice(0, 4)) {
486
- findings.push(`VIEWPOINT-GESTURE-SUBSTITUTED: the viewpoint asks for "${g.gesture}" ("${g.item.slice(0, 80)}…") but the suite exercises an in-app control instead. They are different mechanisms — an app button runs the screen's own re-hydrate logic, browser history does not, and a defect that only shows on history navigation lives in exactly that gap. The step vocabulary has no reload/back step (#593), so defer it with \`@manual\` naming the gesture rather than substituting silently.`);
467
+ // The remedy is not the same on both platforms, and getting it wrong is the difference between
468
+ // useful advice and a lie: web still has no reload/back step (#593), so `@manual` is the honest
469
+ // reply — but every mobile gesture in this set now compiles, so telling a mobile author to defer
470
+ // would send them to a manual procedure for work the compiler does. Read from the ledger entry
471
+ // (`substitutionRemedy`), never re-derived here, so a step landing for web needs no edit here.
472
+ const remedy = substitutionRemedy(g);
473
+ findings.push(`VIEWPOINT-GESTURE-SUBSTITUTED: the viewpoint asks for "${g.gesture}" ("${g.item.slice(0, 80)}…") but the suite exercises an in-app control instead. They are different mechanisms — an app button runs the screen's own re-hydrate logic and the gesture does not, so a defect that only shows on the gesture's own path lives in exactly that gap. ${remedy}`);
487
474
  }
488
475
  // #595 — a flow whose requirement list is a hand restatement of the screen specs it
489
476
  // traverses. `specFR` read 100% over two restated FRs while the guard clause the flow most
@@ -523,6 +510,41 @@ export function runAudit(screenDir: string, screenName: string): AuditReport {
523
510
  findings.push(`FLOW-HANDOFF-SHALLOW: only ${flowQ.handoffs.asserted}/${flowQ.handoffs.total} cross-screen transitions are followed by an assertion in the new screen — carried state (the thing a flow exists to verify) is unproven at the handoff. businessDepth is capped until asserted.`);
524
511
  }
525
512
  }
513
+ // #694 — two DIFFERENT scenarios wearing the same VP id. BLOCKING (it joins the gate
514
+ // conjunction below) where the declaration-integrity findings that follow are advisory: a
515
+ // reused id does not stop here, it reaches the customer. `generateTcId` builds the delivered
516
+ // testcase id straight out of the vpId, so the collision ships as two rows carrying ONE id in
517
+ // the deliverable — and the result-merge fallback has already attached one sibling's run
518
+ // result to another, delivering 7 never-executed testcases as "Passed" (see
519
+ // `exporters/scenario-merger.ts`). `matrix/gates.ts` already grades this `severity: 'error'`,
520
+ // but only at delivery; blocking at audit is what makes it cheap to fix (renumber, regenerate).
521
+ const reusedIds = scenarioIdReuse(scenarios);
522
+ for (const r of reusedIds.slice(0, 6)) {
523
+ findings.push(`SCENARIO-ID-REUSED: ${r.count} different scenarios in ${r.file || 'this feature'} carry the id "${r.id}" (${r.titles.map((t) => `"${t.slice(0, 52)}…"`).join(' · ')}). Every axis stays green — the duplicate sensor clusters identical STEPS, so scenarios that merely share an id sail past it — while the deliverable gets ${r.count} rows under one testcase id and the run-result merge can attach the wrong scenario's result. Give each scenario its own sequence number within its category; the ledger item that now reads UNCOVERED is the sibling that lost its number.`);
524
+ }
525
+ // #599 — integrity of the DECLARATION itself: three ways it can be internally wrong while
526
+ // every coverage number still reads well. Advisory. This used to sit inside the
527
+ // `flowQ.hasContract` branch above, so a SCREEN unit never reached it at all — the checks ran
528
+ // on flows only, silently, for every release since they landed (#694).
529
+ {
530
+ const testDataDir = path.join(screenDir, 'test-data');
531
+ const extra: Array<{ label: string; text: string }> = [];
532
+ try {
533
+ for (const f of fs.readdirSync(testDataDir).filter((x) => x.endsWith('.yaml'))) {
534
+ extra.push({ label: `test-data/${f}`, text: readTextFile(path.join(testDataDir, f)) ?? '' });
535
+ }
536
+ } catch { /* api units and fresh scaffolds carry none */ }
537
+ const vi = viewpointIntegrity(viewpointPath, scenarios.map((sc) => sc.vpId ?? '').filter(Boolean), extra);
538
+ for (const d of vi.duplicateIds.slice(0, 4)) {
539
+ findings.push(`VIEWPOINT-ID-REUSED: "${d.id}" labels ${d.count} different claims (${d.texts.map((t) => `"${t.slice(0, 44)}…"`).join(' · ')}). The ledger then counts ${d.count} items while traceability sees ONE id, so both the coverage arithmetic and "which test proves this?" go wrong — and neither number looks suspicious. Give each atomic claim its own id; several ids may share a flow.`);
540
+ }
541
+ for (const d of vi.danglingRefs.slice(0, 5)) {
542
+ findings.push(`TRACE-REF-DANGLING: ${d.where} cites "${d.ref}", which no scenario carries. Nothing breaks at runtime, so a wrong pointer survives every refactor and quietly misleads the next maintainer. Fix the reference, or the scenario id it was meant to name.`);
543
+ }
544
+ if (vi.uniformPriority) {
545
+ findings.push(`VIEWPOINT-PRIORITY-UNIFORM: all ${vi.uniformPriority.rows} rows of the Priority Viewpoints table are "${vi.uniformPriority.levels[0]}". That is a formality, not a priority: nothing can be selected for a smoke run and the release conversation has no input. Rank by business impact and risk — the basic flow and the data-integrity guards are not the same bet as an exit path a screen suite already covers.`);
546
+ }
547
+ }
526
548
  // #592 W5 — a continuity mechanism proved on one side only.
527
549
  if (isUiFlow) {
528
550
  const scenarioTexts = scenarios.map((s) => `${s.name} ${s.stepsText}`);
@@ -536,7 +558,7 @@ export function runAudit(screenDir: string, screenName: string): AuditReport {
536
558
  // manual, most of them M5-inbox — invisible while tagged bare).
537
559
  const bareManual = (featureText.match(/@manual(?![:\w])/g) || []).length;
538
560
  if (bareManual > 0) {
539
- findings.push(`MANUAL-CODE-MISSING: ${bareManual} @manual tag(s) carry no reason code — tag @manual:M1..M9 (M5 = external dependency e.g. inbox, M3 = mock/network, M7 = environment) so the capability planner can route what a driver would automate.`);
561
+ findings.push(`MANUAL-CODE-MISSING: ${bareManual} @manual tag(s) carry no reason code — tag @manual:${MANUAL_REASON_RANGE} (M5 = external dependency e.g. inbox, M3 = mock/network, M7 = environment, M10 = device/OS capability, M11 = real-device only) so the capability planner can route what a driver would automate.`);
540
562
  }
541
563
  }
542
564
  for (const c of flowCredits) {
@@ -671,7 +693,7 @@ export function runAudit(screenDir: string, screenName: string): AuditReport {
671
693
  const plan = buildPlan(screenDir, screenName, catalogScreenName, platform);
672
694
  if (plan.recommendations.length) {
673
695
  const recs = plan.recommendations.map((r) => `\`sungen capability add ${r.driver}\` (automates ${r.count})`).join(' · ');
674
- findings.push(`CAPABILITY-SUGGESTION: ${plan.capabilityManual} @manual scenario(s) are capability-manual (a driver could automate them) — ${recs}. Recommend-only: nothing is installed automatically; the ${plan.judgmentManual} judgment-manual (M6/M8/M9) correctly stay manual.`);
696
+ findings.push(`CAPABILITY-SUGGESTION: ${plan.capabilityManual} @manual scenario(s) are capability-manual (a driver could automate them) — ${recs}. Recommend-only: nothing is installed automatically; the ${plan.judgmentManual} judgment-manual (${KEEP_REASON_CODES.join('/')}) correctly stay manual.`);
675
697
  }
676
698
  // Named, not dropped: without this the scenarios read as "nothing could help", and the
677
699
  // operator's only clue was an install that dead-ends (#597).
@@ -835,15 +857,18 @@ export function runAudit(screenDir: string, screenName: string): AuditReport {
835
857
  const calibration = { axes, weakest, inflated, notApplicable, cappedAt: capped ? cap : undefined };
836
858
 
837
859
  // Gate spans coverage (viewpoint themes), depth, claim-proof, spec-clause coverage,
838
- // AND taxonomy-match (scenarios must use the project's viewpoint IDs when defined).
860
+ // taxonomy-match (scenarios must use the project's viewpoint IDs when defined),
861
+ // AND scenario-id uniqueness — a reused id reaches the customer's deliverable as two rows
862
+ // under one testcase id, and has already shipped a never-executed testcase as "Passed" (#694).
839
863
  const gateStatus: 'PASS' | 'FAIL' =
840
- gate.gaps.length === 0 && depth.verdict !== 'fail' && claim.verdict !== 'fail' && spec.verdict !== 'fail' && !taxonomyMismatch && !gateSensorError ? 'PASS' : 'FAIL';
864
+ gate.gaps.length === 0 && depth.verdict !== 'fail' && claim.verdict !== 'fail' && spec.verdict !== 'fail' && !taxonomyMismatch && !gateSensorError
865
+ && reusedIds.length === 0 ? 'PASS' : 'FAIL';
841
866
 
842
867
  return {
843
868
  screen: screenName,
844
869
  scenarioCount: scenarios.length,
845
870
  gate, depth, claim, taxonomy, balance, duplicates, trace, spec,
846
- taxonomyMismatch, downstream, manualOracle: manualOracleResult, automatableManual: autoManual, flowDepth, oracle, ledger, viewpointBaseline, calibration,
871
+ taxonomyMismatch, reusedScenarioIds: reusedIds, downstream, manualOracle: manualOracleResult, automatableManual: autoManual, flowDepth, oracle, ledger, viewpointBaseline, calibration,
847
872
  ...(isUiFlow ? { flowQuality: flowQ, flowInventory: inventory ?? undefined } : {}),
848
873
  score: {
849
874
  overall: Math.round(overall * 10) / 10,
@@ -2,7 +2,7 @@
2
2
  * Capability Planner (Phase 2b) — deterministic, recommend-only.
3
3
  *
4
4
  * Classifies each scenario's execution mode + each @manual case by reason code
5
- * (M1–M9), maps capability-reasons to drivers, and emits the manual-reason KPI.
5
+ * (M1–M11), maps capability-reasons to drivers, and emits the manual-reason KPI.
6
6
  * Never installs anything (that's `sungen capability add`). See
7
7
  * docs/spec/sungen_phase2b_spec.md.
8
8
  */
@@ -22,13 +22,37 @@ export const MANUAL_REASONS: Record<string, ReasonDef> = {
22
22
  M4: { code: 'M4', label: 'Missing stable selector/test-id', cls: 'capability', drivers: [] }, // locator contract, no driver
23
23
  M5: { code: 'M5', label: 'External dependency', cls: 'capability', drivers: ['mail-file', 'contract'] },
24
24
  M6: { code: 'M6', label: 'Visual / UX judgment', cls: 'keep', drivers: ['specialized'] },
25
+ // `capability` with no driver is deliberate and matches M4: the case IS automatable once the
26
+ // environment exists, it just is not an `sungen capability add` away. Reclassifying it as `keep`
27
+ // would claim the opposite — that no environment could ever run it — and would silently move
28
+ // every existing M7 scenario from the capability-manual count to judgment-manual.
25
29
  M7: { code: 'M7', label: 'Environment limitation', cls: 'capability', drivers: [] }, // testability, no driver
26
30
  M8: { code: 'M8', label: 'Not worth automating', cls: 'keep', drivers: [] },
27
31
  M9: { code: 'M9', label: 'True human judgment', cls: 'keep', drivers: [] },
32
+ // Mobile-specific (M10/M11). Both are `keep` with no driver, and that is the honest answer:
33
+ // nothing installable automates them, so the planner must not imply otherwise. Before these
34
+ // existed every mobile-specific reason collapsed into M7, which made "needs a real device" and
35
+ // "waiting on staging infra" indistinguishable in the report.
36
+ M10: { code: 'M10', label: 'Device/OS capability', cls: 'keep', drivers: [] },
37
+ M11: { code: 'M11', label: 'Real-device only', cls: 'keep', drivers: [] },
28
38
  // Not a single-screen driver gap: automatable cross-screen via a flow (/sungen:add-flow).
29
39
  XS: { code: 'XS', label: 'Cross-screen (automate via flow)', cls: 'flow', drivers: [] },
30
40
  };
31
41
 
42
+ /** Codes that stay manual whatever is installed — derived, so a new `keep` code joins by itself. */
43
+ export const KEEP_REASON_CODES: string[] = Object.values(MANUAL_REASONS)
44
+ .filter((r) => r.cls === 'keep')
45
+ .map((r) => r.code);
46
+
47
+ /** The documented reason-code range, e.g. "M1..M11". Derived so guidance can never go stale. */
48
+ export const MANUAL_REASON_RANGE: string = (() => {
49
+ const ns = Object.keys(MANUAL_REASONS)
50
+ .filter((c) => /^M\d+$/.test(c))
51
+ .map((c) => Number(c.slice(1)))
52
+ .sort((a, b) => a - b);
53
+ return ns.length ? `M${ns[0]}..M${ns[ns.length - 1]}` : '';
54
+ })();
55
+
32
56
  // Keyword inference (best-effort retrofit). Order matters — first match wins.
33
57
  // Cross-screen "deferred to a flow" is checked FIRST: it is not a driver gap on
34
58
  // this screen, it is handled by a flow — so it must not recommend a driver.
@@ -41,6 +65,14 @@ const INFER: { code: string; re: RegExp }[] = [
41
65
  // "email" alone is too greedy (every subscription test mentions it) → require a real external-mail
42
66
  // signal (verification mail / OTP / inbox), so an API/DB-oracle test isn't misread as M5.
43
67
  { code: 'M5', re: /\b(external|third[-\s]?party|sandbox|payment gateway|invoice|download|verification (e?mail|link)|otp|mailbox|inbox|e?mail link)\b/i },
68
+ // Mobile-specific, and they MUST sit ahead of M6/M7 or they never fire: M6 matches
69
+ // /keyboard|accessibilit|responsive/ and M7 matches /environment/, either of which would take a
70
+ // mobile reason first. They stay BEHIND M1–M5 on purpose, so a mobile phrasing of an ordinary
71
+ // driver gap ("assert via API", "needs a stable test-id") still routes to the driver that solves
72
+ // it. One known consequence of that order: "IAP sandbox" hits M5's `sandbox` before M10 — the
73
+ // external-payment reading is the more useful one, and the order test pins it either way.
74
+ { code: 'M11', re: /\b(real device|máy thật|physical device|nfc|biometric|fingerprint|face id|touch id|camera thật|real camera|push token)\b/i },
75
+ { code: 'M10', re: /\b(notification shade|app switcher|recents|in-app purchase|iap|interruption|incoming call|permission variance|os version)\b/i },
44
76
  { code: 'M6', re: /\b(visual|responsive|layout|accessibilit|a11y|keyboard|screen reader|ux|breakpoint)\b/i },
45
77
  { code: 'M7', re: /\b(environment|staging[-\s]?only|infra|env limitation)\b/i },
46
78
  { code: 'M8', re: /\b(not worth|exploratory|one[-\s]?off)\b/i },
@@ -10,7 +10,7 @@
10
10
  # status: shipped → published as an npm package (R5); planned → not built yet.
11
11
  # bundled: true → installed automatically (a dependency of @sun-asterisk/sungen),
12
12
  # so `capability add` is unnecessary.
13
- # unblocks: manual-reason codes (M1–M9) this driver resolves (Phase 2b taxonomy).
13
+ # unblocks: manual-reason codes (M1–M11) this driver resolves (Phase 2b taxonomy).
14
14
  #
15
15
  # R5 status: the three real capabilities ship as packages — @sungen/driver-ui (web UI,
16
16
  # bundled as the default), @sungen/driver-db, @sungen/driver-api. The web *platform*
@@ -106,6 +106,125 @@ page_types:
106
106
  - theme: navigation-correctness
107
107
  keywords: [tap, navigate, "leaves home", "is hidden", opens, navigation]
108
108
 
109
+ # ---- mobile page-types -------------------------------------------------------------------
110
+ # All `mobile-*`, so `sensors.ts` never offers them to a web target. Two rules shaped the
111
+ # keywords below:
112
+ # 1. Detection needs 2 distinct hits AND a 1-hit lead (MIN_HITS/MIN_MARGIN), so keywords must
113
+ # DISCRIMINATE, not merely occur. Generic mobile words ("tap", "screen") are absent.
114
+ # 2. A mobile target still considers the web types, and that is correct: a mobile commerce
115
+ # screen SHOULD select ecommerce-list, and a mobile form leaning on generic form
116
+ # vocabulary (field/submit/validation) SHOULD select `form`. These types are for what a
117
+ # web type has no concept of, so each keyword set is built from natively-distinctive nouns.
118
+ # Themes carry `depth:` wherever the honest oracle is a value rather than a sighting — that is
119
+ # what separates a suite that scrolls and asserts a value from one that only asserts presence.
120
+ # Every theme is expressible in the SHIPPED mobile vocabulary (scroll/swipe/pull-to-refresh/
121
+ # rotate/background/restart/grant-permission/set-connectivity/deep-link), so none of them forces
122
+ # an @manual. OS-back themes remain absent, but the REASON has changed: the `go back` step now
123
+ # exists (per-OS KEYCODE_BACK / WDA navigation-back), so the blocker is no longer vocabulary. What
124
+ # stops it now is blast radius — a new `must_cover` theme is a new gap for every existing mobile
125
+ # suite, which is a scoring decision for an owner, not a drive-by. `viewpoint-ledger` already
126
+ # covers the dangerous half by refusing `tap [Back]` as an answer to an OS-back viewpoint item.
127
+ mobile-list:
128
+ detect_keywords: [feed, "pull to refresh", "infinite scroll", "load more", "list item", "list row"]
129
+ must_cover:
130
+ - theme: list-data
131
+ keywords: [list, feed, row, "list item", displayed]
132
+ depth:
133
+ requires: data-assertion
134
+ cross_screen: false
135
+ keywords: ["row contains", "item contains", "every row", "all items", "each row", "list shows"]
136
+ template: "User see all [List Item] text contains {{expected_label}}"
137
+ - theme: refresh-correctness
138
+ keywords: ["pull to refresh", refresh, reload, refreshed]
139
+ depth:
140
+ requires: data-assertion
141
+ cross_screen: false
142
+ keywords: ["after refresh", "refreshed list", "new item", "updated list", "after pull to refresh"]
143
+ template: "User pull to refresh [List] … User see all [List Item] text contains {{expected_label}}"
144
+ - theme: scroll-reachability
145
+ keywords: [scroll, swipe, "load more", "infinite scroll", "below the fold"]
146
+ depth:
147
+ requires: data-assertion
148
+ cross_screen: false
149
+ keywords: ["after scrolling", "scrolled to", "last item", "load more", "next page"]
150
+ template: "User scroll to [Last List Item] … User see [Last List Item] text contains {{expected_last}}"
151
+
152
+ mobile-detail:
153
+ detect_keywords: ["detail screen", "detail view", "detail header", "item detail", "detail pane"]
154
+ must_cover:
155
+ - theme: detail-data
156
+ keywords: [detail, header, displayed, field]
157
+ depth:
158
+ requires: data-assertion
159
+ cross_screen: false
160
+ keywords: ["detail shows", "detail contains", "detail header", "detail value", "detail field"]
161
+ template: "User see [Detail Title] text contains {{expected_title}}"
162
+ - theme: list-detail-consistency
163
+ keywords: [consistent, consistency, match, "same item", "correct item"]
164
+ depth:
165
+ requires: data-assertion
166
+ cross_screen: true
167
+ keywords: ["same item name", "matching name", "same value", "consistency", "same title"]
168
+ template: "User remember [List Item] text as {{v}} … User see [Detail Title] text contains {{v}}"
169
+
170
+ mobile-form:
171
+ detect_keywords: ["soft keyboard", "keyboard overlap", "hide keyboard", "on-screen keyboard", "keyboard covers"]
172
+ must_cover:
173
+ - theme: field-validation
174
+ keywords: [validation, invalid, required, error]
175
+ depth:
176
+ requires: data-assertion
177
+ cross_screen: false
178
+ keywords: ["error message", "validation message", "invalid input", "required message"]
179
+ template: "User see [Field Error] message contains {{error_text}}"
180
+ # No `depth:` on purpose: the claim IS a sighting — after the keyboard is hidden the field
181
+ # and its action are visible again. Forcing a value assertion here would invent an oracle.
182
+ - theme: keyboard-overlap
183
+ keywords: ["soft keyboard", "keyboard overlap", "hide keyboard", "keyboard covers", "keyboard hides"]
184
+ - theme: submit-correctness
185
+ keywords: [submit, save, submitted, saved]
186
+ depth:
187
+ requires: data-assertion
188
+ cross_screen: false
189
+ keywords: ["after submit", "saved value", "success message", "after saving"]
190
+ template: "User see [Success Message] text contains {{success_text}}"
191
+
192
+ mobile-auth:
193
+ detect_keywords: [biometric, fingerprint, "face id", "touch id", "app lock"]
194
+ must_cover:
195
+ - theme: credential-validation
196
+ keywords: [invalid, "wrong password", error, incorrect]
197
+ depth:
198
+ requires: data-assertion
199
+ cross_screen: false
200
+ keywords: ["error message", "invalid credential", "wrong password", "incorrect password"]
201
+ template: "User see [Login Error] message contains {{error_text}}"
202
+ - theme: session-persistence
203
+ keywords: [session, restart, persist, "stays signed in"]
204
+ depth:
205
+ requires: data-assertion
206
+ cross_screen: false
207
+ keywords: ["after restart", "still signed in", "session persists", "remains signed in"]
208
+ template: "User restart the app … User see [Account Name] text contains {{user_name}}"
209
+
210
+ mobile-settings:
211
+ detect_keywords: ["settings screen", toggle, preference, "settings list", "settings item"]
212
+ must_cover:
213
+ - theme: toggle-state-correctness
214
+ keywords: [toggle, switch, enabled, disabled]
215
+ depth:
216
+ requires: data-assertion
217
+ cross_screen: false
218
+ keywords: ["toggle state", "switch is on", "enabled state", "reflects the", "shows enabled"]
219
+ template: "User see [Notifications Toggle] text contains {{expected_state}}"
220
+ - theme: setting-persistence
221
+ keywords: [persist, restart, saved, "after reopening"]
222
+ depth:
223
+ requires: data-assertion
224
+ cross_screen: false
225
+ keywords: ["after restart", "setting persists", "still enabled", "saved setting", "after reopening"]
226
+ template: "User restart the app … User see [Notifications Toggle] text contains {{expected_state}}"
227
+
109
228
  auth:
110
229
  detect_keywords: [login, logout, password, signin, "sign in", credential]
111
230
  must_cover:
@@ -127,3 +246,29 @@ universal:
127
246
  keywords: ["empty", "no data", "no result", "failed", "error state"]
128
247
  - theme: accessibility
129
248
  keywords: ["keyboard", "tab order", "accessible", "aria", "focus"]
249
+
250
+ # Same role as `universal`, but only offered to MOBILE targets — `universal` applies to web too,
251
+ # where "rotate to landscape" or "airplane mode" is meaningless.
252
+ #
253
+ # READ THIS BEFORE ADDING TEETH HERE: like `universal`, these themes are REMINDERS. They surface
254
+ # through `universalGaps`, which reaches the audit narrative and the capability sensors but is NOT
255
+ # an input to the score. A theme placed here can never move a number.
256
+ #
257
+ # That is deliberate, not an oversight. These concerns are real on every mobile screen, but not
258
+ # every mobile screen owes every one of them — a settings screen has no deep link, a read-only list
259
+ # has no permission prompt. Scoring them uniformly would penalise honest suites for gaps that are
260
+ # not gaps. The themes that DO carry weight sit in each page-type's `must_cover` above, where they
261
+ # apply to a screen that genuinely owes them.
262
+ mobile_universal:
263
+ - theme: orientation-stability
264
+ keywords: [rotate, landscape, portrait, orientation]
265
+ - theme: connectivity-degraded
266
+ keywords: ["airplane mode", offline, "wifi", "mobile data", "no connection"]
267
+ - theme: app-lifecycle-resume
268
+ keywords: [background, resume, foreground, "returns to the app", restart]
269
+ - theme: permission-prompt
270
+ keywords: [permission, grant, denied, allow]
271
+ - theme: gesture-reachability
272
+ keywords: [scroll, swipe, "off screen", "below the fold"]
273
+ - theme: deep-link-entry
274
+ keywords: ["deep link", deeplink, "universal link"]