@e2edev/e2e 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (399) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +104 -0
  3. package/dist/agent/act-validation.d.ts +27 -0
  4. package/dist/agent/act-validation.d.ts.map +1 -0
  5. package/dist/agent/act-validation.js +121 -0
  6. package/dist/agent/act-validation.js.map +1 -0
  7. package/dist/agent/act.d.ts +27 -0
  8. package/dist/agent/act.d.ts.map +1 -0
  9. package/dist/agent/act.js +775 -0
  10. package/dist/agent/act.js.map +1 -0
  11. package/dist/agent/actions.d.ts +66 -0
  12. package/dist/agent/actions.d.ts.map +1 -0
  13. package/dist/agent/actions.js +82 -0
  14. package/dist/agent/actions.js.map +1 -0
  15. package/dist/agent/ai-sdk.d.ts +16 -0
  16. package/dist/agent/ai-sdk.d.ts.map +1 -0
  17. package/dist/agent/ai-sdk.js +59 -0
  18. package/dist/agent/ai-sdk.js.map +1 -0
  19. package/dist/agent/call-options.d.ts +10 -0
  20. package/dist/agent/call-options.d.ts.map +1 -0
  21. package/dist/agent/call-options.js +28 -0
  22. package/dist/agent/call-options.js.map +1 -0
  23. package/dist/agent/default-agent.d.ts +22 -0
  24. package/dist/agent/default-agent.d.ts.map +1 -0
  25. package/dist/agent/default-agent.js +354 -0
  26. package/dist/agent/default-agent.js.map +1 -0
  27. package/dist/agent/error.d.ts +53 -0
  28. package/dist/agent/error.d.ts.map +1 -0
  29. package/dist/agent/error.js +94 -0
  30. package/dist/agent/error.js.map +1 -0
  31. package/dist/agent/executor.d.ts +238 -0
  32. package/dist/agent/executor.d.ts.map +1 -0
  33. package/dist/agent/executor.js +56 -0
  34. package/dist/agent/executor.js.map +1 -0
  35. package/dist/agent/index.d.ts +15 -0
  36. package/dist/agent/index.d.ts.map +1 -0
  37. package/dist/agent/index.js +304 -0
  38. package/dist/agent/index.js.map +1 -0
  39. package/dist/agent/invocation.d.ts +194 -0
  40. package/dist/agent/invocation.d.ts.map +1 -0
  41. package/dist/agent/invocation.js +389 -0
  42. package/dist/agent/invocation.js.map +1 -0
  43. package/dist/agent/ledger.d.ts +24 -0
  44. package/dist/agent/ledger.d.ts.map +1 -0
  45. package/dist/agent/ledger.js +48 -0
  46. package/dist/agent/ledger.js.map +1 -0
  47. package/dist/agent/loop-guards.d.ts +35 -0
  48. package/dist/agent/loop-guards.d.ts.map +1 -0
  49. package/dist/agent/loop-guards.js +110 -0
  50. package/dist/agent/loop-guards.js.map +1 -0
  51. package/dist/agent/model/adapter.d.ts +97 -0
  52. package/dist/agent/model/adapter.d.ts.map +1 -0
  53. package/dist/agent/model/adapter.js +40 -0
  54. package/dist/agent/model/adapter.js.map +1 -0
  55. package/dist/agent/model/router.d.ts +36 -0
  56. package/dist/agent/model/router.d.ts.map +1 -0
  57. package/dist/agent/model/router.js +45 -0
  58. package/dist/agent/model/router.js.map +1 -0
  59. package/dist/agent/model/schema.d.ts +16 -0
  60. package/dist/agent/model/schema.d.ts.map +1 -0
  61. package/dist/agent/model/schema.js +37 -0
  62. package/dist/agent/model/schema.js.map +1 -0
  63. package/dist/agent/model/sdk.d.ts +28 -0
  64. package/dist/agent/model/sdk.d.ts.map +1 -0
  65. package/dist/agent/model/sdk.js +258 -0
  66. package/dist/agent/model/sdk.js.map +1 -0
  67. package/dist/agent/observation.d.ts +70 -0
  68. package/dist/agent/observation.d.ts.map +1 -0
  69. package/dist/agent/observation.js +174 -0
  70. package/dist/agent/observation.js.map +1 -0
  71. package/dist/agent/phases.d.ts +71 -0
  72. package/dist/agent/phases.d.ts.map +1 -0
  73. package/dist/agent/phases.js +124 -0
  74. package/dist/agent/phases.js.map +1 -0
  75. package/dist/agent/prompts.d.ts +40 -0
  76. package/dist/agent/prompts.d.ts.map +1 -0
  77. package/dist/agent/prompts.js +104 -0
  78. package/dist/agent/prompts.js.map +1 -0
  79. package/dist/agent/protocol.d.ts +31 -0
  80. package/dist/agent/protocol.d.ts.map +1 -0
  81. package/dist/agent/protocol.js +67 -0
  82. package/dist/agent/protocol.js.map +1 -0
  83. package/dist/agent/public.d.ts +12 -0
  84. package/dist/agent/public.d.ts.map +1 -0
  85. package/dist/agent/public.js +12 -0
  86. package/dist/agent/public.js.map +1 -0
  87. package/dist/agent/replay.d.ts +61 -0
  88. package/dist/agent/replay.d.ts.map +1 -0
  89. package/dist/agent/replay.js +185 -0
  90. package/dist/agent/replay.js.map +1 -0
  91. package/dist/agent/secrets.d.ts +22 -0
  92. package/dist/agent/secrets.d.ts.map +1 -0
  93. package/dist/agent/secrets.js +63 -0
  94. package/dist/agent/secrets.js.map +1 -0
  95. package/dist/agent/step-cache.d.ts +156 -0
  96. package/dist/agent/step-cache.d.ts.map +1 -0
  97. package/dist/agent/step-cache.js +301 -0
  98. package/dist/agent/step-cache.js.map +1 -0
  99. package/dist/agent/tool-loop.d.ts +51 -0
  100. package/dist/agent/tool-loop.d.ts.map +1 -0
  101. package/dist/agent/tool-loop.js +331 -0
  102. package/dist/agent/tool-loop.js.map +1 -0
  103. package/dist/agent/tool.d.ts +39 -0
  104. package/dist/agent/tool.d.ts.map +1 -0
  105. package/dist/agent/tool.js +52 -0
  106. package/dist/agent/tool.js.map +1 -0
  107. package/dist/backend/contract.d.ts +186 -0
  108. package/dist/backend/contract.d.ts.map +1 -0
  109. package/dist/backend/contract.js +65 -0
  110. package/dist/backend/contract.js.map +1 -0
  111. package/dist/backend/index.d.ts +316 -0
  112. package/dist/backend/index.d.ts.map +1 -0
  113. package/dist/backend/index.js +219 -0
  114. package/dist/backend/index.js.map +1 -0
  115. package/dist/backend/session.d.ts +23 -0
  116. package/dist/backend/session.d.ts.map +1 -0
  117. package/dist/backend/session.js +213 -0
  118. package/dist/backend/session.js.map +1 -0
  119. package/dist/backend/surface.d.ts +83 -0
  120. package/dist/backend/surface.d.ts.map +1 -0
  121. package/dist/backend/surface.js +11 -0
  122. package/dist/backend/surface.js.map +1 -0
  123. package/dist/cache/anchors.d.ts +37 -0
  124. package/dist/cache/anchors.d.ts.map +1 -0
  125. package/dist/cache/anchors.js +89 -0
  126. package/dist/cache/anchors.js.map +1 -0
  127. package/dist/cache/context.d.ts +74 -0
  128. package/dist/cache/context.d.ts.map +1 -0
  129. package/dist/cache/context.js +82 -0
  130. package/dist/cache/context.js.map +1 -0
  131. package/dist/cache/decide.d.ts +42 -0
  132. package/dist/cache/decide.d.ts.map +1 -0
  133. package/dist/cache/decide.js +47 -0
  134. package/dist/cache/decide.js.map +1 -0
  135. package/dist/cache/identity.d.ts +113 -0
  136. package/dist/cache/identity.d.ts.map +1 -0
  137. package/dist/cache/identity.js +109 -0
  138. package/dist/cache/identity.js.map +1 -0
  139. package/dist/cache/recorder.d.ts +76 -0
  140. package/dist/cache/recorder.d.ts.map +1 -0
  141. package/dist/cache/recorder.js +143 -0
  142. package/dist/cache/recorder.js.map +1 -0
  143. package/dist/cache/relocate.d.ts +69 -0
  144. package/dist/cache/relocate.d.ts.map +1 -0
  145. package/dist/cache/relocate.js +125 -0
  146. package/dist/cache/relocate.js.map +1 -0
  147. package/dist/cache/store.d.ts +68 -0
  148. package/dist/cache/store.d.ts.map +1 -0
  149. package/dist/cache/store.js +106 -0
  150. package/dist/cache/store.js.map +1 -0
  151. package/dist/cache/trace.d.ts +146 -0
  152. package/dist/cache/trace.d.ts.map +1 -0
  153. package/dist/cache/trace.js +249 -0
  154. package/dist/cache/trace.js.map +1 -0
  155. package/dist/cli/bin.d.ts +3 -0
  156. package/dist/cli/bin.d.ts.map +1 -0
  157. package/dist/cli/bin.js +4 -0
  158. package/dist/cli/bin.js.map +1 -0
  159. package/dist/cli/index.d.ts +4 -0
  160. package/dist/cli/index.d.ts.map +1 -0
  161. package/dist/cli/index.js +108 -0
  162. package/dist/cli/index.js.map +1 -0
  163. package/dist/cli/init.d.ts +6 -0
  164. package/dist/cli/init.d.ts.map +1 -0
  165. package/dist/cli/init.js +101 -0
  166. package/dist/cli/init.js.map +1 -0
  167. package/dist/collect/collect.d.ts +44 -0
  168. package/dist/collect/collect.d.ts.map +1 -0
  169. package/dist/collect/collect.js +89 -0
  170. package/dist/collect/collect.js.map +1 -0
  171. package/dist/collect/registry.d.ts +47 -0
  172. package/dist/collect/registry.d.ts.map +1 -0
  173. package/dist/collect/registry.js +262 -0
  174. package/dist/collect/registry.js.map +1 -0
  175. package/dist/collect/select.d.ts +54 -0
  176. package/dist/collect/select.d.ts.map +1 -0
  177. package/dist/collect/select.js +230 -0
  178. package/dist/collect/select.js.map +1 -0
  179. package/dist/config/agent.d.ts +91 -0
  180. package/dist/config/agent.d.ts.map +1 -0
  181. package/dist/config/agent.js +232 -0
  182. package/dist/config/agent.js.map +1 -0
  183. package/dist/config/load.d.ts +23 -0
  184. package/dist/config/load.d.ts.map +1 -0
  185. package/dist/config/load.js +75 -0
  186. package/dist/config/load.js.map +1 -0
  187. package/dist/config/resolve.d.ts +94 -0
  188. package/dist/config/resolve.d.ts.map +1 -0
  189. package/dist/config/resolve.js +500 -0
  190. package/dist/config/resolve.js.map +1 -0
  191. package/dist/config/validate.d.ts +6 -0
  192. package/dist/config/validate.d.ts.map +1 -0
  193. package/dist/config/validate.js +21 -0
  194. package/dist/config/validate.js.map +1 -0
  195. package/dist/credentials.d.ts +7 -0
  196. package/dist/credentials.d.ts.map +1 -0
  197. package/dist/credentials.js +42 -0
  198. package/dist/credentials.js.map +1 -0
  199. package/dist/expect/async.d.ts +5 -0
  200. package/dist/expect/async.d.ts.map +1 -0
  201. package/dist/expect/async.js +186 -0
  202. package/dist/expect/async.js.map +1 -0
  203. package/dist/expect/index.d.ts +7 -0
  204. package/dist/expect/index.d.ts.map +1 -0
  205. package/dist/expect/index.js +23 -0
  206. package/dist/expect/index.js.map +1 -0
  207. package/dist/expect/values.d.ts +4 -0
  208. package/dist/expect/values.d.ts.map +1 -0
  209. package/dist/expect/values.js +108 -0
  210. package/dist/expect/values.js.map +1 -0
  211. package/dist/index.d.ts +13 -0
  212. package/dist/index.d.ts.map +1 -0
  213. package/dist/index.js +15 -0
  214. package/dist/index.js.map +1 -0
  215. package/dist/internal/ai-trace.d.ts +151 -0
  216. package/dist/internal/ai-trace.d.ts.map +1 -0
  217. package/dist/internal/ai-trace.js +360 -0
  218. package/dist/internal/ai-trace.js.map +1 -0
  219. package/dist/internal/brands.d.ts +9 -0
  220. package/dist/internal/brands.d.ts.map +1 -0
  221. package/dist/internal/brands.js +9 -0
  222. package/dist/internal/brands.js.map +1 -0
  223. package/dist/internal/debug.d.ts +43 -0
  224. package/dist/internal/debug.d.ts.map +1 -0
  225. package/dist/internal/debug.js +102 -0
  226. package/dist/internal/debug.js.map +1 -0
  227. package/dist/internal/errors.d.ts +98 -0
  228. package/dist/internal/errors.d.ts.map +1 -0
  229. package/dist/internal/errors.js +212 -0
  230. package/dist/internal/errors.js.map +1 -0
  231. package/dist/internal/globs.d.ts +29 -0
  232. package/dist/internal/globs.d.ts.map +1 -0
  233. package/dist/internal/globs.js +126 -0
  234. package/dist/internal/globs.js.map +1 -0
  235. package/dist/internal/ids.d.ts +32 -0
  236. package/dist/internal/ids.d.ts.map +1 -0
  237. package/dist/internal/ids.js +124 -0
  238. package/dist/internal/ids.js.map +1 -0
  239. package/dist/internal/json-value.d.ts +15 -0
  240. package/dist/internal/json-value.d.ts.map +1 -0
  241. package/dist/internal/json-value.js +61 -0
  242. package/dist/internal/json-value.js.map +1 -0
  243. package/dist/internal/package-version.d.ts +6 -0
  244. package/dist/internal/package-version.d.ts.map +1 -0
  245. package/dist/internal/package-version.js +14 -0
  246. package/dist/internal/package-version.js.map +1 -0
  247. package/dist/internal/realm-slot.d.ts +13 -0
  248. package/dist/internal/realm-slot.d.ts.map +1 -0
  249. package/dist/internal/realm-slot.js +23 -0
  250. package/dist/internal/realm-slot.js.map +1 -0
  251. package/dist/internal/redact.d.ts +33 -0
  252. package/dist/internal/redact.d.ts.map +1 -0
  253. package/dist/internal/redact.js +56 -0
  254. package/dist/internal/redact.js.map +1 -0
  255. package/dist/internal/regexp.d.ts +10 -0
  256. package/dist/internal/regexp.d.ts.map +1 -0
  257. package/dist/internal/regexp.js +27 -0
  258. package/dist/internal/regexp.js.map +1 -0
  259. package/dist/internal/text.d.ts +39 -0
  260. package/dist/internal/text.d.ts.map +1 -0
  261. package/dist/internal/text.js +66 -0
  262. package/dist/internal/text.js.map +1 -0
  263. package/dist/internal/time.d.ts +37 -0
  264. package/dist/internal/time.d.ts.map +1 -0
  265. package/dist/internal/time.js +91 -0
  266. package/dist/internal/time.js.map +1 -0
  267. package/dist/internal/trace.d.ts +18 -0
  268. package/dist/internal/trace.d.ts.map +1 -0
  269. package/dist/internal/trace.js +46 -0
  270. package/dist/internal/trace.js.map +1 -0
  271. package/dist/internal/urls.d.ts +31 -0
  272. package/dist/internal/urls.d.ts.map +1 -0
  273. package/dist/internal/urls.js +95 -0
  274. package/dist/internal/urls.js.map +1 -0
  275. package/dist/locator/engine.d.ts +65 -0
  276. package/dist/locator/engine.d.ts.map +1 -0
  277. package/dist/locator/engine.js +164 -0
  278. package/dist/locator/engine.js.map +1 -0
  279. package/dist/locator/expression.d.ts +19 -0
  280. package/dist/locator/expression.d.ts.map +1 -0
  281. package/dist/locator/expression.js +85 -0
  282. package/dist/locator/expression.js.map +1 -0
  283. package/dist/locator/screen.d.ts +36 -0
  284. package/dist/locator/screen.d.ts.map +1 -0
  285. package/dist/locator/screen.js +281 -0
  286. package/dist/locator/screen.js.map +1 -0
  287. package/dist/report/build.d.ts +214 -0
  288. package/dist/report/build.d.ts.map +1 -0
  289. package/dist/report/build.js +346 -0
  290. package/dist/report/build.js.map +1 -0
  291. package/dist/report/code-frame.d.ts +20 -0
  292. package/dist/report/code-frame.d.ts.map +1 -0
  293. package/dist/report/code-frame.js +73 -0
  294. package/dist/report/code-frame.js.map +1 -0
  295. package/dist/report/debug-steps.d.ts +14 -0
  296. package/dist/report/debug-steps.d.ts.map +1 -0
  297. package/dist/report/debug-steps.js +85 -0
  298. package/dist/report/debug-steps.js.map +1 -0
  299. package/dist/report/list.d.ts +80 -0
  300. package/dist/report/list.d.ts.map +1 -0
  301. package/dist/report/list.js +372 -0
  302. package/dist/report/list.js.map +1 -0
  303. package/dist/report/live-status.d.ts +51 -0
  304. package/dist/report/live-status.d.ts.map +1 -0
  305. package/dist/report/live-status.js +162 -0
  306. package/dist/report/live-status.js.map +1 -0
  307. package/dist/report/write.d.ts +4 -0
  308. package/dist/report/write.d.ts.map +1 -0
  309. package/dist/report/write.js +13 -0
  310. package/dist/report/write.js.map +1 -0
  311. package/dist/run/app-process.d.ts +18 -0
  312. package/dist/run/app-process.d.ts.map +1 -0
  313. package/dist/run/app-process.js +112 -0
  314. package/dist/run/app-process.js.map +1 -0
  315. package/dist/run/artifacts.d.ts +51 -0
  316. package/dist/run/artifacts.d.ts.map +1 -0
  317. package/dist/run/artifacts.js +114 -0
  318. package/dist/run/artifacts.js.map +1 -0
  319. package/dist/run/events.d.ts +100 -0
  320. package/dist/run/events.d.ts.map +1 -0
  321. package/dist/run/events.js +59 -0
  322. package/dist/run/events.js.map +1 -0
  323. package/dist/run/execute.d.ts +119 -0
  324. package/dist/run/execute.d.ts.map +1 -0
  325. package/dist/run/execute.js +555 -0
  326. package/dist/run/execute.js.map +1 -0
  327. package/dist/run/fixtures.d.ts +40 -0
  328. package/dist/run/fixtures.d.ts.map +1 -0
  329. package/dist/run/fixtures.js +408 -0
  330. package/dist/run/fixtures.js.map +1 -0
  331. package/dist/run/in-process.d.ts +24 -0
  332. package/dist/run/in-process.d.ts.map +1 -0
  333. package/dist/run/in-process.js +120 -0
  334. package/dist/run/in-process.js.map +1 -0
  335. package/dist/run/public.d.ts +19 -0
  336. package/dist/run/public.d.ts.map +1 -0
  337. package/dist/run/public.js +11 -0
  338. package/dist/run/public.js.map +1 -0
  339. package/dist/run/realm.d.ts +52 -0
  340. package/dist/run/realm.d.ts.map +1 -0
  341. package/dist/run/realm.js +101 -0
  342. package/dist/run/realm.js.map +1 -0
  343. package/dist/run/records.d.ts +87 -0
  344. package/dist/run/records.d.ts.map +1 -0
  345. package/dist/run/records.js +3 -0
  346. package/dist/run/records.js.map +1 -0
  347. package/dist/run/retry.d.ts +18 -0
  348. package/dist/run/retry.d.ts.map +1 -0
  349. package/dist/run/retry.js +33 -0
  350. package/dist/run/retry.js.map +1 -0
  351. package/dist/run/runner.d.ts +49 -0
  352. package/dist/run/runner.d.ts.map +1 -0
  353. package/dist/run/runner.js +375 -0
  354. package/dist/run/runner.js.map +1 -0
  355. package/dist/run/scheduler.d.ts +45 -0
  356. package/dist/run/scheduler.d.ts.map +1 -0
  357. package/dist/run/scheduler.js +512 -0
  358. package/dist/run/scheduler.js.map +1 -0
  359. package/dist/run/serial.d.ts +52 -0
  360. package/dist/run/serial.d.ts.map +1 -0
  361. package/dist/run/serial.js +247 -0
  362. package/dist/run/serial.js.map +1 -0
  363. package/dist/run/sessions.d.ts +54 -0
  364. package/dist/run/sessions.d.ts.map +1 -0
  365. package/dist/run/sessions.js +221 -0
  366. package/dist/run/sessions.js.map +1 -0
  367. package/dist/run/steps.d.ts +196 -0
  368. package/dist/run/steps.d.ts.map +1 -0
  369. package/dist/run/steps.js +151 -0
  370. package/dist/run/steps.js.map +1 -0
  371. package/dist/run/unit-runner.d.ts +30 -0
  372. package/dist/run/unit-runner.d.ts.map +1 -0
  373. package/dist/run/unit-runner.js +11 -0
  374. package/dist/run/unit-runner.js.map +1 -0
  375. package/dist/run/units.d.ts +50 -0
  376. package/dist/run/units.d.ts.map +1 -0
  377. package/dist/run/units.js +103 -0
  378. package/dist/run/units.js.map +1 -0
  379. package/dist/run/worker/entry.d.ts +8 -0
  380. package/dist/run/worker/entry.d.ts.map +1 -0
  381. package/dist/run/worker/entry.js +137 -0
  382. package/dist/run/worker/entry.js.map +1 -0
  383. package/dist/run/worker/handle.d.ts +10 -0
  384. package/dist/run/worker/handle.d.ts.map +1 -0
  385. package/dist/run/worker/handle.js +74 -0
  386. package/dist/run/worker/handle.js.map +1 -0
  387. package/dist/run/worker/protocol.d.ts +129 -0
  388. package/dist/run/worker/protocol.d.ts.map +1 -0
  389. package/dist/run/worker/protocol.js +18 -0
  390. package/dist/run/worker/protocol.js.map +1 -0
  391. package/dist/run/worker/session.d.ts +69 -0
  392. package/dist/run/worker/session.d.ts.map +1 -0
  393. package/dist/run/worker/session.js +123 -0
  394. package/dist/run/worker/session.js.map +1 -0
  395. package/dist/types.d.ts +630 -0
  396. package/dist/types.d.ts.map +1 -0
  397. package/dist/types.js +6 -0
  398. package/dist/types.js.map +1 -0
  399. package/package.json +91 -0
@@ -0,0 +1,98 @@
1
+ /** Runner-owned error taxonomy and exit-code mapping (spec 06-cli.md). */
2
+ import { type BackendErrorCode } from '../backend/contract.ts';
3
+ /** Message of an arbitrary thrown value, for diagnostics that must not throw. */
4
+ export declare function errorMessage(cause: unknown): string;
5
+ export type ErrorCategory = 'test' | 'configuration' | 'infrastructure' | 'internal' | 'interrupted';
6
+ export type ErrorPhase = 'config' | 'collection' | 'launch' | 'beforeAll' | 'beforeEach' | 'body' | 'afterEach' | 'afterAll' | 'cleanup' | 'report';
7
+ export interface SerializedError {
8
+ category: ErrorCategory;
9
+ code: string;
10
+ message: string;
11
+ retryable: boolean;
12
+ phase?: ErrorPhase;
13
+ scopeId?: string;
14
+ stack?: string;
15
+ }
16
+ /** Marks classified errors so instances survive isolated module realms. */
17
+ declare const E2E_ERROR_MARKER: unique symbol;
18
+ /**
19
+ * Normalizes a backend failure, including one thrown by another copy of the
20
+ * backend module.
21
+ *
22
+ * A backend imported by a config file is loaded through a different module
23
+ * registry than the runner, so its `BackendError` is a different class and
24
+ * `instanceof` misses it. Detection is therefore structural, keyed on the
25
+ * closed code set: without this, every out-of-tree backend's typed failures
26
+ * silently degrade to a generic error and lose their taxonomy. A foreign
27
+ * instance is held to the same retryability rule as the local class.
28
+ */
29
+ export declare function asBackendError(value: unknown): {
30
+ code: BackendErrorCode;
31
+ message: string;
32
+ retryable: boolean;
33
+ } | undefined;
34
+ /** Base class for every runner-classified error. */
35
+ export declare class E2EError extends Error {
36
+ readonly category: ErrorCategory;
37
+ readonly code: string;
38
+ readonly retryable: boolean;
39
+ readonly [E2E_ERROR_MARKER] = true;
40
+ constructor(category: ErrorCategory, code: string, message: string, options?: {
41
+ retryable?: boolean;
42
+ cause?: unknown;
43
+ });
44
+ }
45
+ /** Detects an E2EError created by another copy of this module. */
46
+ export declare function isForeignE2EError(value: unknown): value is Error & {
47
+ category: ErrorCategory;
48
+ code: string;
49
+ retryable: boolean;
50
+ };
51
+ export declare class ConfigurationError extends E2EError {
52
+ constructor(code: string, message: string, options?: {
53
+ cause?: unknown;
54
+ });
55
+ }
56
+ export declare class CollectionError extends ConfigurationError {
57
+ constructor(message: string, options?: {
58
+ cause?: unknown;
59
+ });
60
+ }
61
+ export declare class InfrastructureError extends E2EError {
62
+ constructor(code: string, message: string, options?: {
63
+ cause?: unknown;
64
+ });
65
+ }
66
+ export declare class TestError extends E2EError {
67
+ constructor(code: string, message: string, options?: {
68
+ retryable?: boolean;
69
+ cause?: unknown;
70
+ });
71
+ }
72
+ export declare class TestTimeoutError extends TestError {
73
+ constructor(message: string);
74
+ }
75
+ /** Maps a category to its process exit code per 06-cli.md. */
76
+ export declare function exitCodeForCategory(category: ErrorCategory): 0 | 1 | 2 | 3 | 4 | 130;
77
+ /** Combines exit codes for mixed outcomes using precedence 130 > 4 > 3 > 2 > 1 > 0. */
78
+ export declare function combineExitCodes(codes: readonly number[]): 0 | 1 | 2 | 3 | 4 | 130;
79
+ /**
80
+ * Canonical BackendError -> runner taxonomy mapping.
81
+ * Applies to every backend surface: lifecycle, app, screen, artifacts,
82
+ * state capture/restore, and observation. Non-BackendError causes become
83
+ * non-retryable infrastructure BACKEND_FAILURE.
84
+ */
85
+ export declare function translateBackendError(cause: unknown, suffix?: string): E2EError;
86
+ /** Classifies an arbitrary thrown value into an E2EError; unknown values become test failures. */
87
+ export declare function classifyError(value: unknown): E2EError;
88
+ /** Serializes an error into the bounded report-1 error shape. */
89
+ export declare function serializeError(error: E2EError, extras?: {
90
+ phase?: ErrorPhase;
91
+ scopeId?: string;
92
+ }): SerializedError;
93
+ /** Strips C0/C1 control characters except tab and newline. */
94
+ export declare function sanitizeText(text: string): string;
95
+ /** Truncates a string so its UTF-8 encoding fits maxBytes without splitting a code point. */
96
+ export declare function truncateUtf8(text: string, maxBytes: number): string;
97
+ export {};
98
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/internal/errors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,212 @@
1
+ /** Runner-owned error taxonomy and exit-code mapping (spec 06-cli.md). */
2
+ import { BACKEND_ERROR_CODES, BackendError, RETRYABLE_BACKEND_ERROR_CODES, } from '../backend/contract.js';
3
+ /** Message of an arbitrary thrown value, for diagnostics that must not throw. */
4
+ export function errorMessage(cause) {
5
+ return cause instanceof Error ? cause.message : String(cause);
6
+ }
7
+ /** Marks classified errors so instances survive isolated module realms. */
8
+ const E2E_ERROR_MARKER = Symbol.for('e2e.error.v1');
9
+ /**
10
+ * Normalizes a backend failure, including one thrown by another copy of the
11
+ * backend module.
12
+ *
13
+ * A backend imported by a config file is loaded through a different module
14
+ * registry than the runner, so its `BackendError` is a different class and
15
+ * `instanceof` misses it. Detection is therefore structural, keyed on the
16
+ * closed code set: without this, every out-of-tree backend's typed failures
17
+ * silently degrade to a generic error and lose their taxonomy. A foreign
18
+ * instance is held to the same retryability rule as the local class.
19
+ */
20
+ export function asBackendError(value) {
21
+ if (value instanceof BackendError)
22
+ return value;
23
+ if (!(value instanceof Error) || value.name !== 'BackendError')
24
+ return undefined;
25
+ const code = value.code;
26
+ if (!isBackendErrorCode(code))
27
+ return undefined;
28
+ const retryable = value.retryable === true;
29
+ if (retryable && !RETRYABLE_BACKEND_ERROR_CODES.has(code)) {
30
+ return { code: 'BACKEND_FAILURE', message: value.message, retryable: false };
31
+ }
32
+ return { code, message: value.message, retryable };
33
+ }
34
+ function isBackendErrorCode(value) {
35
+ return typeof value === 'string' && BACKEND_ERROR_CODES.includes(value);
36
+ }
37
+ /** Base class for every runner-classified error. */
38
+ export class E2EError extends Error {
39
+ category;
40
+ code;
41
+ retryable;
42
+ [E2E_ERROR_MARKER] = true;
43
+ constructor(category, code, message, options = {}) {
44
+ super(message, options.cause === undefined ? undefined : { cause: options.cause });
45
+ this.name = 'E2EError';
46
+ this.category = category;
47
+ this.code = code;
48
+ this.retryable = options.retryable ?? false;
49
+ }
50
+ }
51
+ const CATEGORIES = new Set([
52
+ 'test',
53
+ 'configuration',
54
+ 'infrastructure',
55
+ 'internal',
56
+ 'interrupted',
57
+ ]);
58
+ /** Detects an E2EError created by another copy of this module. */
59
+ export function isForeignE2EError(value) {
60
+ return (value instanceof Error &&
61
+ value[E2E_ERROR_MARKER] === true &&
62
+ CATEGORIES.has(value.category) &&
63
+ typeof value.code === 'string');
64
+ }
65
+ export class ConfigurationError extends E2EError {
66
+ constructor(code, message, options = {}) {
67
+ super('configuration', code, message, options);
68
+ this.name = 'ConfigurationError';
69
+ }
70
+ }
71
+ export class CollectionError extends ConfigurationError {
72
+ constructor(message, options = {}) {
73
+ super('COLLECTION_ERROR', message, options);
74
+ this.name = 'CollectionError';
75
+ }
76
+ }
77
+ export class InfrastructureError extends E2EError {
78
+ constructor(code, message, options = {}) {
79
+ super('infrastructure', code, message, options);
80
+ this.name = 'InfrastructureError';
81
+ }
82
+ }
83
+ export class TestError extends E2EError {
84
+ constructor(code, message, options = {}) {
85
+ super('test', code, message, options);
86
+ this.name = 'TestError';
87
+ }
88
+ }
89
+ export class TestTimeoutError extends TestError {
90
+ constructor(message) {
91
+ super('TEST_TIMEOUT', message);
92
+ this.name = 'TestTimeoutError';
93
+ }
94
+ }
95
+ /** Maps a category to its process exit code per 06-cli.md. */
96
+ export function exitCodeForCategory(category) {
97
+ switch (category) {
98
+ case 'test':
99
+ return 1;
100
+ case 'configuration':
101
+ return 2;
102
+ case 'infrastructure':
103
+ return 3;
104
+ case 'internal':
105
+ return 4;
106
+ case 'interrupted':
107
+ return 130;
108
+ }
109
+ }
110
+ /** Combines exit codes for mixed outcomes using precedence 130 > 4 > 3 > 2 > 1 > 0. */
111
+ export function combineExitCodes(codes) {
112
+ const precedence = [130, 4, 3, 2, 1, 0];
113
+ for (const candidate of precedence) {
114
+ if (codes.includes(candidate))
115
+ return candidate;
116
+ }
117
+ return 0;
118
+ }
119
+ /**
120
+ * Canonical BackendError -> runner taxonomy mapping.
121
+ * Applies to every backend surface: lifecycle, app, screen, artifacts,
122
+ * state capture/restore, and observation. Non-BackendError causes become
123
+ * non-retryable infrastructure BACKEND_FAILURE.
124
+ */
125
+ export function translateBackendError(cause, suffix = '') {
126
+ if (cause instanceof E2EError)
127
+ return cause;
128
+ const backendError = asBackendError(cause);
129
+ if (backendError !== undefined) {
130
+ switch (backendError.code) {
131
+ case 'NODE_STALE':
132
+ return new TestError('LOCATOR_NOT_FOUND', `node became stale${suffix}`, { cause });
133
+ case 'FRAME_NOT_FOUND':
134
+ return new TestError('LOCATOR_NOT_FOUND', `${backendError.message}${suffix}`, { cause });
135
+ case 'FRAME_AMBIGUOUS':
136
+ return new TestError('LOCATOR_AMBIGUOUS', `${backendError.message}${suffix}`, { cause });
137
+ case 'NOT_ACTIONABLE':
138
+ return new TestError('ACTION_FAILED', `${backendError.message}${suffix}`, { cause });
139
+ case 'ACTION_MAY_HAVE_COMMITTED':
140
+ return new TestError('ACTION_FAILED', `${backendError.message}${suffix}`, { cause });
141
+ case 'OPERATION_TIMEOUT':
142
+ return new TestError('ACTION_FAILED', `operation timed out${suffix}`, { cause });
143
+ case 'CANCELLED':
144
+ return new E2EError('infrastructure', 'CANCELLED', 'operation cancelled', { cause });
145
+ case 'UNSUPPORTED_CAPABILITY':
146
+ return new E2EError('configuration', 'UNSUPPORTED_CAPABILITY', backendError.message, { cause });
147
+ case 'INVALID_STATE':
148
+ return new TestError('APP_NOT_OPEN', backendError.message, { cause });
149
+ case 'BACKEND_FAILURE':
150
+ return new E2EError('infrastructure', 'BACKEND_FAILURE', backendError.message, { cause });
151
+ }
152
+ }
153
+ return new E2EError('infrastructure', 'BACKEND_FAILURE', errorMessage(cause), { cause });
154
+ }
155
+ /** Classifies an arbitrary thrown value into an E2EError; unknown values become test failures. */
156
+ export function classifyError(value) {
157
+ if (value instanceof E2EError)
158
+ return value;
159
+ if (isForeignE2EError(value)) {
160
+ return new E2EError(value.category, value.code, value.message, {
161
+ retryable: value.retryable,
162
+ cause: value,
163
+ });
164
+ }
165
+ if (asBackendError(value) !== undefined) {
166
+ return translateBackendError(value);
167
+ }
168
+ if (value instanceof Error) {
169
+ return new TestError('ERROR', value.message, { cause: value });
170
+ }
171
+ return new TestError('ERROR', String(value));
172
+ }
173
+ const MAX_MESSAGE_BYTES = 8192;
174
+ /** Serializes an error into the bounded report-1 error shape. */
175
+ export function serializeError(error, extras = {}) {
176
+ const serialized = {
177
+ category: error.category,
178
+ code: error.code,
179
+ message: truncateUtf8(sanitizeText(error.message), MAX_MESSAGE_BYTES),
180
+ retryable: error.retryable,
181
+ };
182
+ if (extras.phase !== undefined)
183
+ serialized.phase = extras.phase;
184
+ if (extras.scopeId !== undefined)
185
+ serialized.scopeId = extras.scopeId;
186
+ const stack = (error.cause instanceof Error ? error.cause.stack : undefined) ?? error.stack;
187
+ if (stack !== undefined)
188
+ serialized.stack = truncateUtf8(sanitizeText(stack), 65536);
189
+ return serialized;
190
+ }
191
+ /** C0/C1 control characters except tab and newline. */
192
+ // oxlint-disable-next-line no-control-regex -- the control range is the point
193
+ const CONTROL_PATTERN = /[\u0000-\u0008\u000b-\u001f\u007f-\u009f]/g;
194
+ const UTF8 = new TextEncoder();
195
+ const UTF8_DECODER = new TextDecoder();
196
+ /** Strips C0/C1 control characters except tab and newline. */
197
+ export function sanitizeText(text) {
198
+ return text.replace(CONTROL_PATTERN, '\uFFFD');
199
+ }
200
+ /** Truncates a string so its UTF-8 encoding fits maxBytes without splitting a code point. */
201
+ export function truncateUtf8(text, maxBytes) {
202
+ const bytes = UTF8.encode(text);
203
+ if (bytes.byteLength <= maxBytes)
204
+ return text;
205
+ // Back up off any UTF-8 continuation bytes (10xxxxxx) so the cut lands on a
206
+ // code point boundary; the lead byte at the cut is excluded with its tail.
207
+ let end = Math.max(0, maxBytes);
208
+ while (end > 0 && (bytes[end] & 0xc0) === 0x80)
209
+ end -= 1;
210
+ return UTF8_DECODER.decode(bytes.subarray(0, end));
211
+ }
212
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/internal/errors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /** Test glob grammar per 05-config.md. */
2
+ interface CompiledGlob {
3
+ readonly segments: readonly GlobSegment[];
4
+ }
5
+ type GlobSegment = {
6
+ kind: 'globstar';
7
+ } | {
8
+ kind: 'pattern';
9
+ regexp: RegExp;
10
+ allowsDot: boolean;
11
+ };
12
+ /**
13
+ * Compiles one glob string. Supported: `*` (zero or more non-`/`), `?` (one
14
+ * non-`/`), a complete `**` segment (zero or more path segments). Braces,
15
+ * extglobs, and `!` exclusions are unsupported.
16
+ */
17
+ export declare function compileGlob(pattern: string): CompiledGlob;
18
+ /** Matches one already-normalized relative path (with `/` separators). */
19
+ export declare function matchesGlob(glob: CompiledGlob, relativePath: string): boolean;
20
+ /**
21
+ * Discovers regular files under `root` matching any glob. Matching is
22
+ * case-sensitive, does not follow directory symlinks, and results are sorted
23
+ * by Unicode code point.
24
+ */
25
+ export declare function discoverFiles(root: string, patterns: readonly string[]): string[];
26
+ /** Sorts strings by Unicode code point as required by 11-lifecycle.md. */
27
+ export declare function compareCodePoints(a: string, b: string): number;
28
+ export {};
29
+ //# sourceMappingURL=globs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"globs.d.ts","sourceRoot":"","sources":["../../src/internal/globs.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAO1C,UAAU,YAAY;IACpB,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAC;CAC3C;AAED,KAAK,WAAW,GACZ;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GACpB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAAC;AAE5D;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CAoBzD;AAaD,0EAA0E;AAC1E,wBAAgB,WAAW,CAAC,IAAI,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAG7E;AA2BD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAajF;AA0BD,0EAA0E;AAC1E,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAS9D"}
@@ -0,0 +1,126 @@
1
+ /** Test glob grammar per 05-config.md. */
2
+ import { readdirSync } from 'node:fs';
3
+ import path from 'node:path';
4
+ import { ConfigurationError } from './errors.js';
5
+ import { escapeRegexpChar } from './regexp.js';
6
+ /**
7
+ * Compiles one glob string. Supported: `*` (zero or more non-`/`), `?` (one
8
+ * non-`/`), a complete `**` segment (zero or more path segments). Braces,
9
+ * extglobs, and `!` exclusions are unsupported.
10
+ */
11
+ export function compileGlob(pattern) {
12
+ if (pattern.length === 0)
13
+ throw new ConfigurationError('INVALID_GLOB', 'empty glob pattern');
14
+ if (pattern.startsWith('!')) {
15
+ throw new ConfigurationError('INVALID_GLOB', `leading '!' exclusions are unsupported: ${pattern}`);
16
+ }
17
+ const segments = pattern.split('/').map((segment) => {
18
+ if (segment === '**')
19
+ return { kind: 'globstar' };
20
+ if (segment.includes('**')) {
21
+ throw new ConfigurationError('INVALID_GLOB', `'**' must be a complete path segment: ${pattern}`);
22
+ }
23
+ return {
24
+ kind: 'pattern',
25
+ regexp: compileSegment(segment),
26
+ allowsDot: segment.startsWith('.'),
27
+ };
28
+ });
29
+ return { segments };
30
+ }
31
+ function compileSegment(segment) {
32
+ let source = '^';
33
+ for (let i = 0; i < segment.length; i += 1) {
34
+ const ch = segment[i];
35
+ if (ch === '*')
36
+ source += '[^/]*';
37
+ else if (ch === '?')
38
+ source += '[^/]';
39
+ else
40
+ source += escapeRegexpChar(ch);
41
+ }
42
+ return new RegExp(`${source}$`);
43
+ }
44
+ /** Matches one already-normalized relative path (with `/` separators). */
45
+ export function matchesGlob(glob, relativePath) {
46
+ const parts = relativePath.split('/');
47
+ return matchFrom(glob.segments, 0, parts, 0);
48
+ }
49
+ function matchFrom(segments, segmentIndex, parts, partIndex) {
50
+ if (segmentIndex === segments.length)
51
+ return partIndex === parts.length;
52
+ const segment = segments[segmentIndex];
53
+ if (segment.kind === 'globstar') {
54
+ for (let skip = 0; skip <= parts.length - partIndex; skip += 1) {
55
+ for (let i = 0; i < skip; i += 1) {
56
+ const part = parts[partIndex + i];
57
+ if (part.startsWith('.'))
58
+ return false;
59
+ }
60
+ if (matchFrom(segments, segmentIndex + 1, parts, partIndex + skip))
61
+ return true;
62
+ }
63
+ return false;
64
+ }
65
+ if (partIndex >= parts.length)
66
+ return false;
67
+ const part = parts[partIndex];
68
+ if (part.startsWith('.') && !segment.allowsDot)
69
+ return false;
70
+ if (!segment.regexp.test(part))
71
+ return false;
72
+ return matchFrom(segments, segmentIndex + 1, parts, partIndex + 1);
73
+ }
74
+ /**
75
+ * Discovers regular files under `root` matching any glob. Matching is
76
+ * case-sensitive, does not follow directory symlinks, and results are sorted
77
+ * by Unicode code point.
78
+ */
79
+ export function discoverFiles(root, patterns) {
80
+ const compiled = patterns.map(compileGlob);
81
+ // No pattern segment can match a dot-directory unless it was spelled with
82
+ // a leading dot, so `.git`, `.e2e`, and friends are pruned at the walk
83
+ // instead of being read and rejected file by file.
84
+ const visitDotDirectories = compiled.some((glob) => glob.segments.some((segment) => segment.kind === 'pattern' && segment.allowsDot));
85
+ const matched = new Set();
86
+ walk(root, '', visitDotDirectories, (relative) => {
87
+ if (compiled.some((glob) => matchesGlob(glob, relative)))
88
+ matched.add(relative);
89
+ });
90
+ return [...matched].toSorted(compareCodePoints);
91
+ }
92
+ function walk(absoluteDir, relativeDir, visitDotDirectories, onFile) {
93
+ let entries;
94
+ try {
95
+ entries = readdirSync(absoluteDir, { withFileTypes: true });
96
+ }
97
+ catch {
98
+ return;
99
+ }
100
+ for (const entry of entries) {
101
+ const relative = relativeDir === '' ? entry.name : `${relativeDir}/${entry.name}`;
102
+ if (entry.isDirectory()) {
103
+ if (entry.name === 'node_modules')
104
+ continue;
105
+ if (!visitDotDirectories && entry.name.startsWith('.'))
106
+ continue;
107
+ walk(path.join(absoluteDir, entry.name), relative, visitDotDirectories, onFile);
108
+ }
109
+ else if (entry.isFile()) {
110
+ onFile(relative);
111
+ }
112
+ }
113
+ }
114
+ /** Sorts strings by Unicode code point as required by 11-lifecycle.md. */
115
+ export function compareCodePoints(a, b) {
116
+ const aPoints = [...a];
117
+ const bPoints = [...b];
118
+ const length = Math.min(aPoints.length, bPoints.length);
119
+ for (let i = 0; i < length; i += 1) {
120
+ const diff = aPoints[i].codePointAt(0) - bPoints[i].codePointAt(0);
121
+ if (diff !== 0)
122
+ return diff;
123
+ }
124
+ return aPoints.length - bPoints.length;
125
+ }
126
+ //# sourceMappingURL=globs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"globs.js","sourceRoot":"","sources":["../../src/internal/globs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Percent-encodes one title per 11-lifecycle.md: RFC 3986 unreserved characters
3
+ * stay literal, every other UTF-8 byte becomes uppercase %HH.
4
+ */
5
+ export declare function encodeTitle(title: string): string;
6
+ /** Validates one raw title per 11-lifecycle.md (1..512 UTF-8 bytes after NFC, no NUL). */
7
+ export declare function validateTitle(title: string): string | null;
8
+ /** Builds a stable test ID: `<normalized-relative-file>::<encoded-title-path>`. */
9
+ export declare function testId(relativeFile: string, titlePath: readonly string[]): string;
10
+ /**
11
+ * Canonical collision-free map key for a title path. Joins with NUL, which
12
+ * `validateTitle` forbids inside titles, so distinct paths never collide.
13
+ */
14
+ export declare function titlePathKey(titlePath: readonly string[]): string;
15
+ /** Builds a setup-test ID: `setup::<test-id>`. */
16
+ export declare function setupTestId(relativeFile: string, titlePath: readonly string[]): string;
17
+ /** SHA-256 of a UTF-8 string, lowercase hex. */
18
+ export declare function sha256Hex(input: string | Uint8Array): string;
19
+ /**
20
+ * RFC 8785 (JCS) canonical JSON serialization for JSON-safe values.
21
+ * Numbers must be finite; non-JSON values throw.
22
+ */
23
+ export declare function canonicalJson(value: unknown): string;
24
+ /** SHA-256 over the RFC 8785 canonical form, lowercase hex. */
25
+ export declare function canonicalDigest(value: unknown): string;
26
+ /** Result ID per 13-reporting.md: SHA-256/JCS of `{ testId, targetId }`. */
27
+ export declare function resultId(test: string, targetId: string): string;
28
+ /** Generates one lowercase UUIDv7 string. */
29
+ export declare function uuidv7(now?: number): string;
30
+ /** RFC 3339 UTC timestamp with exactly millisecond precision. */
31
+ export declare function timestamp(date?: Date): string;
32
+ //# sourceMappingURL=ids.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ids.d.ts","sourceRoot":"","sources":["../../src/internal/ids.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAqBjD;AAED,0FAA0F;AAC1F,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQ1D;AAED,mFAAmF;AACnF,wBAAgB,MAAM,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAEjF;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAEjE;AAED,kDAAkD;AAClD,wBAAgB,WAAW,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAEtF;AAED,gDAAgD;AAChD,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,CAE5D;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAuBpD;AAYD,+DAA+D;AAC/D,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEtD;AAED,4EAA4E;AAC5E,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED,6CAA6C;AAC7C,wBAAgB,MAAM,CAAC,GAAG,GAAE,MAAmB,GAAG,MAAM,CAavD;AAED,iEAAiE;AACjE,wBAAgB,SAAS,CAAC,IAAI,GAAE,IAAiB,GAAG,MAAM,CAEzD"}
@@ -0,0 +1,124 @@
1
+ import { createHash, randomBytes } from 'node:crypto';
2
+ /**
3
+ * Percent-encodes one title per 11-lifecycle.md: RFC 3986 unreserved characters
4
+ * stay literal, every other UTF-8 byte becomes uppercase %HH.
5
+ */
6
+ export function encodeTitle(title) {
7
+ const normalized = title.normalize('NFC');
8
+ const bytes = new TextEncoder().encode(normalized);
9
+ let out = '';
10
+ for (const byte of bytes) {
11
+ const ch = String.fromCharCode(byte);
12
+ if ((byte >= 0x41 && byte <= 0x5a) ||
13
+ (byte >= 0x61 && byte <= 0x7a) ||
14
+ (byte >= 0x30 && byte <= 0x39) ||
15
+ ch === '-' ||
16
+ ch === '.' ||
17
+ ch === '_' ||
18
+ ch === '~') {
19
+ out += ch;
20
+ }
21
+ else {
22
+ out += `%${byte.toString(16).toUpperCase().padStart(2, '0')}`;
23
+ }
24
+ }
25
+ return out;
26
+ }
27
+ /** Validates one raw title per 11-lifecycle.md (1..512 UTF-8 bytes after NFC, no NUL). */
28
+ export function validateTitle(title) {
29
+ const normalized = title.normalize('NFC');
30
+ const bytes = new TextEncoder().encode(normalized).byteLength;
31
+ if (bytes < 1 || bytes > 512) {
32
+ return `title must be 1 through 512 UTF-8 bytes after NFC, got ${bytes}`;
33
+ }
34
+ if (normalized.includes('\u0000'))
35
+ return 'title must not contain NUL';
36
+ return null;
37
+ }
38
+ /** Builds a stable test ID: `<normalized-relative-file>::<encoded-title-path>`. */
39
+ export function testId(relativeFile, titlePath) {
40
+ return `${relativeFile}::${titlePath.map(encodeTitle).join('::')}`;
41
+ }
42
+ /**
43
+ * Canonical collision-free map key for a title path. Joins with NUL, which
44
+ * `validateTitle` forbids inside titles, so distinct paths never collide.
45
+ */
46
+ export function titlePathKey(titlePath) {
47
+ return titlePath.join('\u0000');
48
+ }
49
+ /** Builds a setup-test ID: `setup::<test-id>`. */
50
+ export function setupTestId(relativeFile, titlePath) {
51
+ return `setup::${testId(relativeFile, titlePath)}`;
52
+ }
53
+ /** SHA-256 of a UTF-8 string, lowercase hex. */
54
+ export function sha256Hex(input) {
55
+ return createHash('sha256').update(input).digest('hex');
56
+ }
57
+ /**
58
+ * RFC 8785 (JCS) canonical JSON serialization for JSON-safe values.
59
+ * Numbers must be finite; non-JSON values throw.
60
+ */
61
+ export function canonicalJson(value) {
62
+ if (value === null)
63
+ return 'null';
64
+ switch (typeof value) {
65
+ case 'boolean':
66
+ return value ? 'true' : 'false';
67
+ case 'number': {
68
+ if (!Number.isFinite(value))
69
+ throw new TypeError('non-finite number in canonical JSON');
70
+ return JSON.stringify(value);
71
+ }
72
+ case 'string':
73
+ return JSON.stringify(value);
74
+ case 'object': {
75
+ if (Array.isArray(value)) {
76
+ return `[${value.map((item) => canonicalJson(item === undefined ? null : item)).join(',')}]`;
77
+ }
78
+ const entries = Object.entries(value)
79
+ .filter(([, v]) => v !== undefined)
80
+ .toSorted(([a], [b]) => compareStrings(a, b));
81
+ return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${canonicalJson(v)}`).join(',')}}`;
82
+ }
83
+ default:
84
+ throw new TypeError(`value of type ${typeof value} is not JSON-safe`);
85
+ }
86
+ }
87
+ /**
88
+ * Orders strings by UTF-16 code unit, the ordering RFC 8785 requires. Locale
89
+ * collation must never be used here: it is environment-dependent, and a digest
90
+ * that depends on the host locale is not canonical.
91
+ */
92
+ function compareStrings(a, b) {
93
+ if (a === b)
94
+ return 0;
95
+ return a < b ? -1 : 1;
96
+ }
97
+ /** SHA-256 over the RFC 8785 canonical form, lowercase hex. */
98
+ export function canonicalDigest(value) {
99
+ return sha256Hex(canonicalJson(value));
100
+ }
101
+ /** Result ID per 13-reporting.md: SHA-256/JCS of `{ testId, targetId }`. */
102
+ export function resultId(test, targetId) {
103
+ return canonicalDigest({ testId: test, targetId });
104
+ }
105
+ /** Generates one lowercase UUIDv7 string. */
106
+ export function uuidv7(now = Date.now()) {
107
+ const bytes = randomBytes(16);
108
+ const ts = BigInt(now);
109
+ bytes[0] = Number((ts >> 40n) & 0xffn);
110
+ bytes[1] = Number((ts >> 32n) & 0xffn);
111
+ bytes[2] = Number((ts >> 24n) & 0xffn);
112
+ bytes[3] = Number((ts >> 16n) & 0xffn);
113
+ bytes[4] = Number((ts >> 8n) & 0xffn);
114
+ bytes[5] = Number(ts & 0xffn);
115
+ bytes[6] = (bytes[6] & 0x0f) | 0x70;
116
+ bytes[8] = (bytes[8] & 0x3f) | 0x80;
117
+ const hex = Buffer.from(bytes).toString('hex');
118
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
119
+ }
120
+ /** RFC 3339 UTC timestamp with exactly millisecond precision. */
121
+ export function timestamp(date = new Date()) {
122
+ return date.toISOString();
123
+ }
124
+ //# sourceMappingURL=ids.js.map