@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,213 @@
1
+ /**
2
+ * The backend-to-session adapter (RFC0002). One adapter per attempt satisfies
3
+ * the internal `TargetSession` surface over the backend contract, so the agent
4
+ * tier, the judgment tier, the trace cache, and the fixture graph program
5
+ * against one shape. It is the single seam every backend call crosses, which
6
+ * makes it the one place two rules are enforced: a capability the backend does
7
+ * not declare fails loud with `UNSUPPORTED_CAPABILITY` at the moment of use,
8
+ * and anything a backend throws that is not a `BackendError` is normalized to
9
+ * a non-retryable `BACKEND_FAILURE`, so a crashed backend is an infrastructure
10
+ * failure everywhere and never a retry-eligible test failure.
11
+ */
12
+ import { asBackendError, ConfigurationError, E2EError, errorMessage, isForeignE2EError, } from '../internal/errors.js';
13
+ import { BackendError, } from './surface.js';
14
+ /** Located refs are pruned oldest-first past this bound so the map cannot grow unboundedly. */
15
+ const MAX_LOCATED_REFS = 2048;
16
+ /** Revision prefixes: the adapter mints `l<n>` for locate and `b<n>` for observe. */
17
+ const LOCATE_REVISION_PREFIX = 'l';
18
+ const OBSERVE_REVISION_PREFIX = 'b';
19
+ /**
20
+ * Stamps the adapter's revision onto every ref. Backends mint stable ids;
21
+ * the adapter owns revisions, so the staleness rule (act on the newest
22
+ * observation only) holds without every backend reimplementing it.
23
+ */
24
+ function stampRevision(node, revision) {
25
+ return {
26
+ ...node,
27
+ ref: { id: node.ref.id, revision },
28
+ ...(node.children === undefined
29
+ ? {}
30
+ : { children: node.children.map((child) => stampRevision(child, revision)) }),
31
+ };
32
+ }
33
+ /** Wraps a backend snapshot's root nodes into the single-root observation tree. */
34
+ function toTree(nodes, revision) {
35
+ const stamped = nodes.map((node) => stampRevision(node, revision));
36
+ const first = stamped[0];
37
+ if (stamped.length === 1 && first !== undefined)
38
+ return first;
39
+ return { ref: { id: 'root', revision }, role: 'root', children: stamped };
40
+ }
41
+ function countSecure(nodes) {
42
+ let count = 0;
43
+ for (const node of nodes) {
44
+ if (node.states?.secure === true)
45
+ count += 1;
46
+ if (node.children !== undefined)
47
+ count += countSecure(node.children);
48
+ }
49
+ return count;
50
+ }
51
+ /**
52
+ * Normalizes what a backend threw onto the error contract. `BackendError`
53
+ * (from any module copy) and runner errors pass through; anything else is the
54
+ * backend failing outside its contract, reported as infrastructure.
55
+ */
56
+ function normalize(cause, label) {
57
+ if (cause instanceof E2EError || isForeignE2EError(cause) || asBackendError(cause) !== undefined) {
58
+ throw cause;
59
+ }
60
+ throw new BackendError('BACKEND_FAILURE', `${label} failed: ${errorMessage(cause)}`, {
61
+ retryable: false,
62
+ cause,
63
+ });
64
+ }
65
+ /** The grammar verbs a backend declaration can honor. */
66
+ function declaredVerbs(backend) {
67
+ const verbs = new Set();
68
+ if (backend?.perform !== undefined) {
69
+ for (const verb of ['tap', 'type', 'typeSecret', 'press', 'select'])
70
+ verbs.add(verb);
71
+ }
72
+ if (backend?.swipe !== undefined)
73
+ verbs.add('scroll');
74
+ if (backend?.app?.navigate !== undefined)
75
+ verbs.add('navigate');
76
+ return verbs;
77
+ }
78
+ /**
79
+ * Builds one session over a backend. One adapter per attempt; revisions are
80
+ * minted per adapter, so refs can never leak across attempts.
81
+ */
82
+ export function createBackendSession(options) {
83
+ const { backend, targetName } = options;
84
+ let revision = 0;
85
+ let viewport = { width: 1, height: 1, scale: 1 };
86
+ const unsupported = (what) => {
87
+ throw new ConfigurationError('UNSUPPORTED_CAPABILITY', `target "${targetName}" has no backend capability for ${what}`);
88
+ };
89
+ /**
90
+ * One declared member as a guarded call: capability-checked at the moment of
91
+ * use and error-normalized. `defineBackend` bound every member to its body,
92
+ * so the function is called as is.
93
+ */
94
+ const guard = (what, fn) => async (...args) => {
95
+ if (fn === undefined)
96
+ return unsupported(what);
97
+ try {
98
+ return await fn(...args);
99
+ }
100
+ catch (cause) {
101
+ return normalize(cause, what);
102
+ }
103
+ };
104
+ // Located nodes, cached by id so `read(ref)` answers from the resolution
105
+ // that minted the ref. A read against an older resolution is NODE_STALE,
106
+ // which the engine treats as retryable: it re-resolves and reads again.
107
+ let locateRevision = 0;
108
+ const located = new Map();
109
+ const stale = (ref) => new BackendError('NODE_STALE', `node ${ref.id} is stale; re-resolve`, { retryable: true });
110
+ /**
111
+ * A located ref from a superseded resolution never reaches the backend.
112
+ * Observation refs are exempt: they are checked by the backend against its
113
+ * newest observation, and a backend with stable ids may legitimately hand
114
+ * the same id to both tiers.
115
+ */
116
+ const rejectSupersededLocate = (ref) => {
117
+ if (!ref.revision.startsWith(LOCATE_REVISION_PREFIX))
118
+ return;
119
+ const known = located.get(ref.id);
120
+ if (known !== undefined && known.ref.revision !== ref.revision)
121
+ throw stale(ref);
122
+ };
123
+ const locateRaw = guard('locators (screen)', backend?.locate);
124
+ const observeRaw = guard('observation', backend?.observe);
125
+ const app = {
126
+ open: guard('navigation', backend?.app?.navigate),
127
+ back: guard('back navigation', backend?.app?.back),
128
+ restart: guard('app restart', backend?.app?.restart),
129
+ clearState: guard('app state clearing', backend?.app?.clearState),
130
+ };
131
+ const artifacts = {
132
+ screenshot: guard('screenshots', backend?.artifacts?.screenshot),
133
+ ...(backend?.artifacts?.startTrace === undefined || backend.artifacts.stopTrace === undefined
134
+ ? {}
135
+ : {
136
+ startTrace: guard('traces', backend.artifacts.startTrace),
137
+ stopTrace: guard('traces', backend.artifacts.stopTrace),
138
+ }),
139
+ };
140
+ let ended = false;
141
+ return {
142
+ verbs: declaredVerbs(backend),
143
+ app,
144
+ artifacts,
145
+ ...(backend?.state === undefined
146
+ ? {}
147
+ : {
148
+ captureState: guard('state capture', backend.state.capture),
149
+ restoreState: guard('state restore', backend.state.restore),
150
+ }),
151
+ ...(backend?.url === undefined ? {} : { url: guard('the current URL', backend.url) }),
152
+ async observe(operation, observeOptions) {
153
+ const snapshot = await observeRaw(operation, observeOptions?.pixels === true ? { pixels: true } : {});
154
+ if (snapshot.viewport !== undefined)
155
+ viewport = snapshot.viewport;
156
+ revision += 1;
157
+ const minted = `${OBSERVE_REVISION_PREFIX}${revision}`;
158
+ return {
159
+ revision: minted,
160
+ capturedAt: new Date().toISOString(),
161
+ ...(snapshot.pixels === undefined ? {} : { pixels: snapshot.pixels }),
162
+ tree: toTree(snapshot.nodes, minted),
163
+ viewport,
164
+ redaction: {
165
+ secureNodeCount: countSecure(snapshot.nodes),
166
+ maskedRegionCount: snapshot.maskedRegionCount ?? 0,
167
+ },
168
+ };
169
+ },
170
+ async locate(expression, operation) {
171
+ const nodes = await locateRaw(expression, operation);
172
+ locateRevision += 1;
173
+ const locateRev = `${LOCATE_REVISION_PREFIX}${locateRevision}`;
174
+ const refs = [];
175
+ for (const node of nodes) {
176
+ const stamped = stampRevision(node, locateRev);
177
+ located.delete(stamped.ref.id);
178
+ located.set(stamped.ref.id, stamped);
179
+ refs.push(stamped.ref);
180
+ }
181
+ for (const oldest of located.keys()) {
182
+ if (located.size <= MAX_LOCATED_REFS)
183
+ break;
184
+ located.delete(oldest);
185
+ }
186
+ return refs;
187
+ },
188
+ async read(ref) {
189
+ if (backend?.locate === undefined)
190
+ unsupported('locators (screen)');
191
+ const node = located.get(ref.id);
192
+ if (node === undefined || node.ref.revision !== ref.revision)
193
+ throw stale(ref);
194
+ return node;
195
+ },
196
+ async perform(ref, action, operation) {
197
+ rejectSupersededLocate(ref);
198
+ if (action.kind === 'dragTo')
199
+ rejectSupersededLocate(action.target);
200
+ await guard(`the "${action.kind}" action`, backend?.perform)(ref, action, operation);
201
+ },
202
+ swipe: guard('swipe gestures', backend?.swipe),
203
+ // The backend outlives the attempt; only the per-attempt isolation ends
204
+ // here, exactly once. dispose() belongs to the worker.
205
+ close: guard('attempt end', async (operation) => {
206
+ if (ended)
207
+ return;
208
+ ended = true;
209
+ await backend?.endAttempt?.({ signal: operation.signal, timeoutMs: operation.timeoutMs });
210
+ }),
211
+ };
212
+ }
213
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/backend/session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,QAAQ,EACR,YAAY,EACZ,iBAAiB,GAClB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,YAAY,GAOb,MAAM,cAAc,CAAC;AAOtB,+FAA+F;AAC/F,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAE9B,qFAAqF;AACrF,MAAM,sBAAsB,GAAG,GAAG,CAAC;AACnC,MAAM,uBAAuB,GAAG,GAAG,CAAC;AAEpC;;;;GAIG;AACH,SAAS,aAAa,CAAC,IAAkB,EAAE,QAAgB;IACzD,OAAO;QACL,GAAG,IAAI;QACP,GAAG,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,EAAE;QAClC,GAAG,CAAC,IAAI,CAAC,QAAQ,KAAK,SAAS;YAC7B,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,aAAa,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC;KAChF,CAAC;AACJ,CAAC;AAED,mFAAmF;AACnF,SAAS,MAAM,CAAC,KAA8B,EAAE,QAAgB;IAC9D,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;IACnE,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACzB,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IAC9D,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;AAC5E,CAAC;AAED,SAAS,WAAW,CAAC,KAA8B;IACjD,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI;YAAE,KAAK,IAAI,CAAC,CAAC;QAC7C,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS;YAAE,KAAK,IAAI,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACvE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,SAAS,SAAS,CAAC,KAAc,EAAE,KAAa;IAC9C,IAAI,KAAK,YAAY,QAAQ,IAAI,iBAAiB,CAAC,KAAK,CAAC,IAAI,cAAc,CAAC,KAAK,CAAC,KAAK,SAAS,EAAE,CAAC;QACjG,MAAM,KAAK,CAAC;IACd,CAAC;IACD,MAAM,IAAI,YAAY,CAAC,iBAAiB,EAAE,GAAG,KAAK,YAAY,YAAY,CAAC,KAAK,CAAC,EAAE,EAAE;QACnF,SAAS,EAAE,KAAK;QAChB,KAAK;KACN,CAAC,CAAC;AACL,CAAC;AAED,yDAAyD;AACzD,SAAS,aAAa,CAAC,OAAkC;IACvD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAe,CAAC;IACrC,IAAI,OAAO,EAAE,OAAO,KAAK,SAAS,EAAE,CAAC;QACnC,KAAK,MAAM,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,CAAU;YAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAChG,CAAC;IACD,IAAI,OAAO,EAAE,KAAK,KAAK,SAAS;QAAE,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACtD,IAAI,OAAO,EAAE,GAAG,EAAE,QAAQ,KAAK,SAAS;QAAE,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAChE,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAA8B;IACjE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC;IACxC,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,QAAQ,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;IAEjD,MAAM,WAAW,GAAG,CAAC,IAAY,EAAS,EAAE;QAC1C,MAAM,IAAI,kBAAkB,CAC1B,wBAAwB,EACxB,WAAW,UAAU,mCAAmC,IAAI,EAAE,CAC/D,CAAC;IACJ,CAAC,CAAC;IAEF;;;;OAIG;IACH,MAAM,KAAK,GACT,CAAyB,IAAY,EAAE,EAA4C,EAAE,EAAE,CACvF,KAAK,EAAE,GAAG,IAAO,EAAc,EAAE;QAC/B,IAAI,EAAE,KAAK,SAAS;YAAE,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC;QAC/C,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;QAC3B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAChC,CAAC;IACH,CAAC,CAAC;IAEJ,yEAAyE;IACzE,yEAAyE;IACzE,wEAAwE;IACxE,IAAI,cAAc,GAAG,CAAC,CAAC;IACvB,MAAM,OAAO,GAAG,IAAI,GAAG,EAAwB,CAAC;IAEhD,MAAM,KAAK,GAAG,CAAC,GAAY,EAAgB,EAAE,CAC3C,IAAI,YAAY,CAAC,YAAY,EAAE,QAAQ,GAAG,CAAC,EAAE,uBAAuB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE7F;;;;;OAKG;IACH,MAAM,sBAAsB,GAAG,CAAC,GAAY,EAAQ,EAAE;QACpD,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,sBAAsB,CAAC;YAAE,OAAO;QAC7D,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,GAAG,CAAC,QAAQ,KAAK,GAAG,CAAC,QAAQ;YAAE,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;IACnF,CAAC,CAAC;IAEF,MAAM,SAAS,GAAG,KAAK,CAAC,mBAAmB,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAC9D,MAAM,UAAU,GAAG,KAAK,CAAC,aAAa,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAE1D,MAAM,GAAG,GAAe;QACtB,IAAI,EAAE,KAAK,CAAC,YAAY,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC;QACjD,IAAI,EAAE,KAAK,CAAC,iBAAiB,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC;QAClD,OAAO,EAAE,KAAK,CAAC,aAAa,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC;QACpD,UAAU,EAAE,KAAK,CAAC,oBAAoB,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,CAAC;KAClE,CAAC;IAEF,MAAM,SAAS,GAAqB;QAClC,UAAU,EAAE,KAAK,CAAC,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,CAAC;QAChE,GAAG,CAAC,OAAO,EAAE,SAAS,EAAE,UAAU,KAAK,SAAS,IAAI,OAAO,CAAC,SAAS,CAAC,SAAS,KAAK,SAAS;YAC3F,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC;gBACE,UAAU,EAAE,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,SAAS,CAAC,UAAU,CAAC;gBACzD,SAAS,EAAE,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,SAAS,CAAC,SAAS,CAAC;aACxD,CAAC;KACP,CAAC;IAEF,IAAI,KAAK,GAAG,KAAK,CAAC;IAElB,OAAO;QACL,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC;QAC7B,GAAG;QACH,SAAS;QACT,GAAG,CAAC,OAAO,EAAE,KAAK,KAAK,SAAS;YAC9B,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC;gBACE,YAAY,EAAE,KAAK,CAAC,eAAe,EAAE,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC;gBAC3D,YAAY,EAAE,KAAK,CAAC,eAAe,EAAE,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC;aAC5D,CAAC;QACN,GAAG,CAAC,OAAO,EAAE,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,iBAAiB,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACrF,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,cAAc;YACrC,MAAM,QAAQ,GAAG,MAAM,UAAU,CAC/B,SAAS,EACT,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CACxD,CAAC;YACF,IAAI,QAAQ,CAAC,QAAQ,KAAK,SAAS;gBAAE,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC;YAClE,QAAQ,IAAI,CAAC,CAAC;YACd,MAAM,MAAM,GAAG,GAAG,uBAAuB,GAAG,QAAQ,EAAE,CAAC;YACvD,OAAO;gBACL,QAAQ,EAAE,MAAM;gBAChB,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACpC,GAAG,CAAC,QAAQ,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;gBACrE,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBACpC,QAAQ;gBACR,SAAS,EAAE;oBACT,eAAe,EAAE,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC;oBAC5C,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB,IAAI,CAAC;iBACnD;aACF,CAAC;QACJ,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,SAAS;YAChC,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;YACrD,cAAc,IAAI,CAAC,CAAC;YACpB,MAAM,SAAS,GAAG,GAAG,sBAAsB,GAAG,cAAc,EAAE,CAAC;YAC/D,MAAM,IAAI,GAAc,EAAE,CAAC;YAC3B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;gBAC/C,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBAC/B,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;gBACrC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACzB,CAAC;YACD,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;gBACpC,IAAI,OAAO,CAAC,IAAI,IAAI,gBAAgB;oBAAE,MAAM;gBAC5C,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACzB,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,GAAG;YACZ,IAAI,OAAO,EAAE,MAAM,KAAK,SAAS;gBAAE,WAAW,CAAC,mBAAmB,CAAC,CAAC;YACpE,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACjC,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,KAAK,GAAG,CAAC,QAAQ;gBAAE,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;YAC/E,OAAO,IAAI,CAAC;QACd,CAAC;QACD,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS;YAClC,sBAAsB,CAAC,GAAG,CAAC,CAAC;YAC5B,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ;gBAAE,sBAAsB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACpE,MAAM,KAAK,CAAC,QAAQ,MAAM,CAAC,IAAI,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;QACvF,CAAC;QACD,KAAK,EAAE,KAAK,CAAC,gBAAgB,EAAE,OAAO,EAAE,KAAK,CAAC;QAC9C,wEAAwE;QACxE,uDAAuD;QACvD,KAAK,EAAE,KAAK,CAAC,aAAa,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE;YAC9C,IAAI,KAAK;gBAAE,OAAO;YAClB,KAAK,GAAG,IAAI,CAAC;YACb,MAAM,OAAO,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,CAAC,SAAS,EAAE,CAAC,CAAC;QAC5F,CAAC,CAAC;KACH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * The internal session surface the harness consumes for one attempt. It is
3
+ * produced only by `createBackendSession` (the backend-to-session adapter) and
4
+ * is never part of the public API: the locator engine, the agent tiers, and
5
+ * the attempt executor program against it so that revision minting, staleness
6
+ * checks, and capability gating exist exactly once.
7
+ *
8
+ * Re-exports the contract vocabulary so internal modules import one path.
9
+ */
10
+ import type { Momentum, ScrollDirection } from '../types.ts';
11
+ import type { LocatorAction, LocatorExpression, NodeRef, ObservationPixels, OperationContext, SemanticNode } from './contract.ts';
12
+ import type { BackendObserveOptions, BackendState } from './index.ts';
13
+ export type * from './contract.ts';
14
+ export { BackendError } from './contract.ts';
15
+ export type { BackendObserveOptions, BackendState } from './index.ts';
16
+ /**
17
+ * The agent's action grammar, by verb. A session declares which verbs its
18
+ * backend can honor so the agent offers the model exactly that vocabulary.
19
+ */
20
+ export type GrammarVerb = 'tap' | 'type' | 'typeSecret' | 'press' | 'select' | 'scroll' | 'navigate';
21
+ export interface Observation {
22
+ readonly revision: string;
23
+ readonly capturedAt: string;
24
+ readonly pixels?: ObservationPixels;
25
+ readonly tree: SemanticNode;
26
+ readonly viewport: {
27
+ readonly width: number;
28
+ readonly height: number;
29
+ readonly scale: number;
30
+ };
31
+ /**
32
+ * What the backend masked against what it saw. Pixel completeness is judged
33
+ * downstream from these counts: fewer masked regions than secure nodes
34
+ * withholds the pixels and keeps the tree.
35
+ */
36
+ readonly redaction: {
37
+ readonly secureNodeCount: number;
38
+ readonly maskedRegionCount: number;
39
+ };
40
+ }
41
+ export interface SessionApp {
42
+ /** Opens the app at one resolved URL. */
43
+ open(url: string, operation: OperationContext): Promise<void>;
44
+ /** Navigates back once. */
45
+ back(operation: OperationContext): Promise<void>;
46
+ /** Recreates the app context without clearing persisted state. */
47
+ restart(operation: OperationContext): Promise<void>;
48
+ /** Clears persisted client state and relaunches. */
49
+ clearState(operation: OperationContext): Promise<void>;
50
+ }
51
+ export interface SessionArtifacts {
52
+ /** Captures a redacted screenshot and returns an artifact-relative path. */
53
+ screenshot(label: string | undefined, operation: OperationContext): Promise<string>;
54
+ /** Starts trace recording. */
55
+ startTrace?(operation: OperationContext): Promise<void>;
56
+ /** Stops trace recording and returns an artifact-relative path. */
57
+ stopTrace?(operation: OperationContext): Promise<string>;
58
+ }
59
+ export interface TargetSession {
60
+ /** Grammar verbs the backend can honor, read from its declaration. */
61
+ readonly verbs: ReadonlySet<GrammarVerb>;
62
+ /** Captures one atomic agent observation; the harness redacts it downstream. */
63
+ observe(operation: OperationContext, options?: BackendObserveOptions): Promise<Observation>;
64
+ /** Resolves immediately; the runner owns query polling and strictness. */
65
+ locate(expression: LocatorExpression, operation: OperationContext): Promise<readonly NodeRef[]>;
66
+ /** Reads one node from the resolution that minted its ref. */
67
+ read(ref: NodeRef, operation: OperationContext): Promise<SemanticNode>;
68
+ /** Performs exactly one action on a located or observed node. */
69
+ perform(ref: NodeRef, action: LocatorAction, operation: OperationContext): Promise<void>;
70
+ /** Performs a viewport-level swipe. */
71
+ swipe(direction: ScrollDirection, momentum: Momentum | undefined, operation: OperationContext): Promise<void>;
72
+ readonly app: SessionApp;
73
+ readonly artifacts: SessionArtifacts;
74
+ /** Captures immutable app state for a session envelope. */
75
+ captureState?(operation: OperationContext): Promise<BackendState>;
76
+ /** Replaces current app state with an immutable captured state. */
77
+ restoreState?(state: BackendState, operation: OperationContext): Promise<void>;
78
+ /** Current top-level URL of the surface, when the platform has one. */
79
+ url?(operation: OperationContext): Promise<string>;
80
+ /** Ends the attempt's isolation within the operation's budget. Idempotent. */
81
+ close(operation: OperationContext): Promise<void>;
82
+ }
83
+ //# sourceMappingURL=surface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surface.d.ts","sourceRoot":"","sources":["../../src/backend/surface.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * The internal session surface the harness consumes for one attempt. It is
3
+ * produced only by `createBackendSession` (the backend-to-session adapter) and
4
+ * is never part of the public API: the locator engine, the agent tiers, and
5
+ * the attempt executor program against it so that revision minting, staleness
6
+ * checks, and capability gating exist exactly once.
7
+ *
8
+ * Re-exports the contract vocabulary so internal modules import one path.
9
+ */
10
+ export { BackendError } from './contract.js';
11
+ //# sourceMappingURL=surface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surface.js","sourceRoot":"","sources":["../../src/backend/surface.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAcH,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * End anchors (RFC0001 layer 3, cache-in decision).
3
+ *
4
+ * A recording run does not end when its last action commits; it ends when the
5
+ * executor looks at the screen and judges the step done. The trace used to
6
+ * keep only the actions and drop that look, so a replay could run every
7
+ * recorded action mechanically — a fill that never committed, a save that
8
+ * produced an unnamed record — and self-finalize with nothing checking the
9
+ * effect. Anchors restore the check as data: the descriptors of nodes that
10
+ * were on screen when the step passed and were not there when it began. They
11
+ * are the step's own delta, checked by the relocation vocabulary
12
+ * (`relocate.ts`) with two deliberate differences: every recorded field must
13
+ * be equal, text included, and presence is enough — uniqueness is not asked.
14
+ */
15
+ import type { SemanticNode } from '../backend/surface.ts';
16
+ import { type DescriptorMatchOptions } from './relocate.ts';
17
+ import { type TraceTargetDescriptor } from './trace.ts';
18
+ export type AnchorOptions = DescriptorMatchOptions;
19
+ /**
20
+ * Derives the end anchors of one step: relocatable descriptors present in the
21
+ * passing observation and absent from the starting one, deduplicated, capped.
22
+ * Leaves come first, then containers, each in document order: a container's
23
+ * accessible name is usually the concatenation of its children's, so it
24
+ * repeats what the leaves already say — and on a list-heavy screen those
25
+ * repeats would crowd the one status line that names the effect out of the
26
+ * cap.
27
+ */
28
+ export declare function describeAnchors(startNodes: ReadonlyMap<string, SemanticNode>, endNodes: ReadonlyMap<string, SemanticNode>, options: AnchorOptions): TraceTargetDescriptor[];
29
+ /**
30
+ * Whether every anchor is present in a fresh observation: some tier of the
31
+ * anchor (`descriptorTiers` — so a test id that churned per render is
32
+ * forgiven when the remaining fields still identify the node) equals some
33
+ * candidate on every anchor field. Two matching nodes are the effect twice
34
+ * over, not an ambiguity.
35
+ */
36
+ export declare function anchorsPresent(anchors: readonly TraceTargetDescriptor[], nodes: ReadonlyMap<string, SemanticNode>, options: AnchorOptions): boolean;
37
+ //# sourceMappingURL=anchors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anchors.d.ts","sourceRoot":"","sources":["../../src/cache/anchors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE1D,OAAO,EAKL,KAAK,sBAAsB,EAC5B,MAAM,eAAe,CAAC;AACvB,OAAO,EAAqB,KAAK,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAE3E,MAAM,MAAM,aAAa,GAAG,sBAAsB,CAAC;AAYnD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,EAC7C,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,EAC3C,OAAO,EAAE,aAAa,GACrB,qBAAqB,EAAE,CAkBzB;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,SAAS,qBAAqB,EAAE,EACzC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,EACxC,OAAO,EAAE,aAAa,GACrB,OAAO,CAOT"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * End anchors (RFC0001 layer 3, cache-in decision).
3
+ *
4
+ * A recording run does not end when its last action commits; it ends when the
5
+ * executor looks at the screen and judges the step done. The trace used to
6
+ * keep only the actions and drop that look, so a replay could run every
7
+ * recorded action mechanically — a fill that never committed, a save that
8
+ * produced an unnamed record — and self-finalize with nothing checking the
9
+ * effect. Anchors restore the check as data: the descriptors of nodes that
10
+ * were on screen when the step passed and were not there when it began. They
11
+ * are the step's own delta, checked by the relocation vocabulary
12
+ * (`relocate.ts`) with two deliberate differences: every recorded field must
13
+ * be equal, text included, and presence is enough — uniqueness is not asked.
14
+ */
15
+ import { describeTarget } from '../agent/actions.js';
16
+ import { describeNodes, descriptorTiers, fieldsEqual, } from './relocate.js';
17
+ import { MAX_TRACE_ANCHORS } from './trace.js';
18
+ /**
19
+ * Every field an anchor records. Unlike target relocation, text is never
20
+ * optional here: for a target, text is a fallback identity and a relabeled
21
+ * button is still the button, but for an anchor the text *is* the effect (a
22
+ * status reading "saved" rather than "empty"), so a looser match would pass a
23
+ * step whose save never took. The structural selector is left out — anchors
24
+ * ask whether an effect is visible, never where it sits in the document.
25
+ */
26
+ const ANCHOR_FIELDS = ['role', 'name', 'text', 'testId', 'placeholder', 'inputPurpose'];
27
+ /**
28
+ * Derives the end anchors of one step: relocatable descriptors present in the
29
+ * passing observation and absent from the starting one, deduplicated, capped.
30
+ * Leaves come first, then containers, each in document order: a container's
31
+ * accessible name is usually the concatenation of its children's, so it
32
+ * repeats what the leaves already say — and on a list-heavy screen those
33
+ * repeats would crowd the one status line that names the effect out of the
34
+ * cap.
35
+ */
36
+ export function describeAnchors(startNodes, endNodes, options) {
37
+ const before = new Set();
38
+ for (const node of startNodes.values()) {
39
+ const descriptor = anchorDescriptor(node, options);
40
+ if (descriptor !== undefined)
41
+ before.add(anchorKey(descriptor));
42
+ }
43
+ const seen = new Set();
44
+ const leaves = [];
45
+ const containers = [];
46
+ for (const node of endNodes.values()) {
47
+ const descriptor = anchorDescriptor(node, options);
48
+ if (descriptor === undefined)
49
+ continue;
50
+ const key = anchorKey(descriptor);
51
+ if (before.has(key) || seen.has(key))
52
+ continue;
53
+ seen.add(key);
54
+ (node.children === undefined || node.children.length === 0 ? leaves : containers).push(descriptor);
55
+ }
56
+ return [...leaves, ...containers].slice(0, MAX_TRACE_ANCHORS);
57
+ }
58
+ /**
59
+ * Whether every anchor is present in a fresh observation: some tier of the
60
+ * anchor (`descriptorTiers` — so a test id that churned per render is
61
+ * forgiven when the remaining fields still identify the node) equals some
62
+ * candidate on every anchor field. Two matching nodes are the effect twice
63
+ * over, not an ambiguity.
64
+ */
65
+ export function anchorsPresent(anchors, nodes, options) {
66
+ const candidates = describeNodes(nodes, options).map((node) => node.descriptor);
67
+ return anchors.every((anchor) => descriptorTiers(anchor).some((tier) => candidates.some((candidate) => fieldsEqual(tier, candidate, ANCHOR_FIELDS))));
68
+ }
69
+ /** One node's anchor projection, or undefined when it could identify nothing. */
70
+ function anchorDescriptor(node, options) {
71
+ const described = describeTarget(node, options.redact, options.testIdAttribute);
72
+ if (described === undefined || descriptorTiers(described).length === 0)
73
+ return undefined;
74
+ const { selector: _selector, ...anchor } = described;
75
+ return anchor;
76
+ }
77
+ /**
78
+ * Set key for one descriptor: its loosest identifying tier over the anchor
79
+ * fields, in fixed order. Keying on the semantic tier whenever it identifies
80
+ * the node means an app that mints test ids per render cannot make every
81
+ * unchanged control look new after a re-render and crowd the real effect out
82
+ * of the capped list; a node only a test id identifies keeps it.
83
+ */
84
+ function anchorKey(descriptor) {
85
+ const tiers = descriptorTiers(descriptor);
86
+ const loosest = tiers[tiers.length - 1] ?? descriptor;
87
+ return JSON.stringify(ANCHOR_FIELDS.map((field) => loosest[field]));
88
+ }
89
+ //# sourceMappingURL=anchors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anchors.js","sourceRoot":"","sources":["../../src/cache/anchors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EACL,aAAa,EACb,eAAe,EACf,WAAW,GAGZ,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,iBAAiB,EAA8B,MAAM,YAAY,CAAC;AAI3E;;;;;;;GAOG;AACH,MAAM,aAAa,GAA+B,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,cAAc,CAAC,CAAC;AAEpH;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAC7B,UAA6C,EAC7C,QAA2C,EAC3C,OAAsB;IAEtB,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAC;IACjC,KAAK,MAAM,IAAI,IAAI,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC;QACvC,MAAM,UAAU,GAAG,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACnD,IAAI,UAAU,KAAK,SAAS;YAAE,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC;IAClE,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,MAAM,GAA4B,EAAE,CAAC;IAC3C,MAAM,UAAU,GAA4B,EAAE,CAAC;IAC/C,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;QACrC,MAAM,UAAU,GAAG,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACnD,IAAI,UAAU,KAAK,SAAS;YAAE,SAAS;QACvC,MAAM,GAAG,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC;QAClC,IAAI,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QAC/C,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,CAAC,IAAI,CAAC,QAAQ,KAAK,SAAS,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACrG,CAAC;IACD,OAAO,CAAC,GAAG,MAAM,EAAE,GAAG,UAAU,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAC;AAChE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,OAAyC,EACzC,KAAwC,EACxC,OAAsB;IAEtB,MAAM,UAAU,GAAG,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAChF,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,EAAE,CAC9B,eAAe,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CACpC,UAAU,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC,CAC5E,CACF,CAAC;AACJ,CAAC;AAED,iFAAiF;AACjF,SAAS,gBAAgB,CAAC,IAAkB,EAAE,OAAsB;IAClE,MAAM,SAAS,GAAG,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IAChF,IAAI,SAAS,KAAK,SAAS,IAAI,eAAe,CAAC,SAAS,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACzF,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC;IACrD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;GAMG;AACH,SAAS,SAAS,CAAC,UAAiC;IAClD,MAAM,KAAK,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,UAAU,CAAC;IACtD,OAAO,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACtE,CAAC"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Per-attempt cache context (RFC0001 layer 3, cache-in decision).
3
+ *
4
+ * Built by the runner once per attempt and handed to the agent tier: the
5
+ * resolved store, key derivation over the attempt's fixed identity, and the
6
+ * staging ground for trace writes. Replay is eligible only on a first attempt
7
+ * — a retry exists because something already went wrong, so it runs fresh and
8
+ * re-records.
9
+ */
10
+ import type { ResolvedCacheConfig } from '../config/resolve.ts';
11
+ import { type CacheTargetIdentity, type TraceCacheKind } from './identity.ts';
12
+ import { type TraceCacheStore } from './store.ts';
13
+ import type { ActionTrace } from './trace.ts';
14
+ import type { JsonValue } from '../types.ts';
15
+ /** One trace write held back until the attempt confirms or implicates it. */
16
+ export interface StagedTraceWrite {
17
+ readonly keyHash: string;
18
+ readonly trace: ActionTrace;
19
+ /** Index of the recording step in the attempt's step timeline. */
20
+ readonly stepIndex: number;
21
+ }
22
+ export interface AgentCacheContext {
23
+ readonly mode: 'read-only' | 'read-write';
24
+ readonly store: TraceCacheStore;
25
+ /** Whether this attempt may replay; writes are governed by `mode` alone. */
26
+ readonly replayEligible: boolean;
27
+ /**
28
+ * Claims one step's key hash. Not a pure derivation: each claim advances
29
+ * the per-attempt occurrence index for its signature, which is what lets a
30
+ * test repeat the same instruction and cache each occurrence separately.
31
+ * Exactly one claim per dispatched step, in execution order — the
32
+ * `StepTraceSession` constructor is the sole caller and owns that
33
+ * invariant structurally.
34
+ */
35
+ claimKeyHash(kind: TraceCacheKind, instruction: string, params: Readonly<Record<string, JsonValue>> | undefined): string;
36
+ /**
37
+ * Trace writes staged during the attempt. A trace is not trusted the moment
38
+ * its own step passes — the verification step after it is what proves the
39
+ * flow reached the right state. The runner settles at attempt end via
40
+ * `flushStagedTraces`.
41
+ */
42
+ readonly staged: StagedTraceWrite[];
43
+ }
44
+ /**
45
+ * Settles the attempt's staged trace writes. A staged trace is confirmed only
46
+ * when a verification step — a deterministic assertion or an agent judgment
47
+ * (`run/steps.ts`, `StepRunOptions.verifies`) — passed after it: an act's own
48
+ * verdict is the recording executor's opinion of its work, and a later act
49
+ * passing says only that the executor coped with whatever state it found. A
50
+ * passing attempt confirms nothing by itself, so a flow no assertion ever
51
+ * checked is never replayed blind, and a failing attempt confirms exactly
52
+ * what had been verified before the failure landed. An unconfirmed trace is
53
+ * not merely withheld: its entry is evicted, so a cached flow implicated in
54
+ * a failure — or one that was never checked — re-records on the next pass
55
+ * instead of replaying a poisoned state forever. The runner does not call
56
+ * this for an interrupted attempt: interruption implicates nothing, so it
57
+ * writes nothing and evicts nothing.
58
+ */
59
+ export declare function flushStagedTraces(context: AgentCacheContext, lastVerifiedStepIndex: number): Promise<void>;
60
+ /**
61
+ * Builds one attempt's cache context, or undefined when the cache is off.
62
+ * A configured custom store replaces the file store wholesale — that is the
63
+ * seam a cloud-shared store (Redis, an API) plugs into. Its hits are
64
+ * re-validated at the one read site (`StepTraceSession.begin`), like
65
+ * every other store's.
66
+ */
67
+ export declare function createAgentCacheContext(options: {
68
+ readonly cache: ResolvedCacheConfig;
69
+ readonly projectId: string;
70
+ readonly testId: string;
71
+ readonly target: CacheTargetIdentity;
72
+ readonly attemptIndex: number;
73
+ }): AgentCacheContext | undefined;
74
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/cache/context.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAEhE,OAAO,EAML,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EAA6C,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7F,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,6EAA6E;AAC7E,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,kEAAkE;IAClE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,YAAY,CAAC;IAC1C,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,4EAA4E;IAC5E,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC;;;;;;;OAOG;IACH,YAAY,CACV,IAAI,EAAE,cAAc,EACpB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,GAAG,SAAS,GACtD,MAAM,CAAC;IACV;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAAC;CACrC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,iBAAiB,EAC1B,qBAAqB,EAAE,MAAM,GAC5B,OAAO,CAAC,IAAI,CAAC,CAYf;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE;IAC/C,QAAQ,CAAC,KAAK,EAAE,mBAAmB,CAAC;IACpC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAC;IACrC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B,GAAG,iBAAiB,GAAG,SAAS,CA+BhC"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Per-attempt cache context (RFC0001 layer 3, cache-in decision).
3
+ *
4
+ * Built by the runner once per attempt and handed to the agent tier: the
5
+ * resolved store, key derivation over the attempt's fixed identity, and the
6
+ * staging ground for trace writes. Replay is eligible only on a first attempt
7
+ * — a retry exists because something already went wrong, so it runs fresh and
8
+ * re-records.
9
+ */
10
+ import { REPLAY_POLICY_VERSION } from './relocate.js';
11
+ import { buildTraceCacheKey, createCallIndexer, projectIdentity, traceCacheKeyHash, traceCallSignature, } from './identity.js';
12
+ import { FileTraceCacheStore, MAX_CACHE_WIRE_BYTES } from './store.js';
13
+ /**
14
+ * Settles the attempt's staged trace writes. A staged trace is confirmed only
15
+ * when a verification step — a deterministic assertion or an agent judgment
16
+ * (`run/steps.ts`, `StepRunOptions.verifies`) — passed after it: an act's own
17
+ * verdict is the recording executor's opinion of its work, and a later act
18
+ * passing says only that the executor coped with whatever state it found. A
19
+ * passing attempt confirms nothing by itself, so a flow no assertion ever
20
+ * checked is never replayed blind, and a failing attempt confirms exactly
21
+ * what had been verified before the failure landed. An unconfirmed trace is
22
+ * not merely withheld: its entry is evicted, so a cached flow implicated in
23
+ * a failure — or one that was never checked — re-records on the next pass
24
+ * instead of replaying a poisoned state forever. The runner does not call
25
+ * this for an interrupted attempt: interruption implicates nothing, so it
26
+ * writes nothing and evicts nothing.
27
+ */
28
+ export async function flushStagedTraces(context, lastVerifiedStepIndex) {
29
+ const staged = context.staged.splice(0);
30
+ if (context.mode !== 'read-write')
31
+ return;
32
+ for (const write of staged) {
33
+ const confirmed = write.stepIndex < lastVerifiedStepIndex;
34
+ try {
35
+ if (confirmed)
36
+ await context.store.write(write.keyHash, write.trace);
37
+ else
38
+ await context.store.delete?.(write.keyHash);
39
+ }
40
+ catch {
41
+ // The cache is disposable; a failed flush is a slower next run only.
42
+ }
43
+ }
44
+ }
45
+ /**
46
+ * Builds one attempt's cache context, or undefined when the cache is off.
47
+ * A configured custom store replaces the file store wholesale — that is the
48
+ * seam a cloud-shared store (Redis, an API) plugs into. Its hits are
49
+ * re-validated at the one read site (`StepTraceSession.begin`), like
50
+ * every other store's.
51
+ */
52
+ export function createAgentCacheContext(options) {
53
+ const mode = options.cache.mode;
54
+ if (mode === 'off')
55
+ return undefined;
56
+ const store = options.cache.store ??
57
+ new FileTraceCacheStore({
58
+ directory: options.cache.dir,
59
+ maxBytes: MAX_CACHE_WIRE_BYTES,
60
+ writable: mode === 'read-write',
61
+ });
62
+ const project = projectIdentity(options.projectId);
63
+ const nextCallIndex = createCallIndexer();
64
+ return {
65
+ mode,
66
+ store,
67
+ replayEligible: options.attemptIndex === 0,
68
+ claimKeyHash: (kind, instruction, params) => {
69
+ const signature = traceCallSignature(kind, instruction, params);
70
+ return traceCacheKeyHash(buildTraceCacheKey({
71
+ project,
72
+ testId: options.testId,
73
+ target: options.target,
74
+ signature,
75
+ callIndex: nextCallIndex(signature),
76
+ policyVersion: REPLAY_POLICY_VERSION,
77
+ }));
78
+ },
79
+ staged: [],
80
+ };
81
+ }
82
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/cache/context.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,kBAAkB,GAGnB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAwB,MAAM,YAAY,CAAC;AAuC7F;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,OAA0B,EAC1B,qBAA6B;IAE7B,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACxC,IAAI,OAAO,CAAC,IAAI,KAAK,YAAY;QAAE,OAAO;IAC1C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,GAAG,qBAAqB,CAAC;QAC1D,IAAI,CAAC;YACH,IAAI,SAAS;gBAAE,MAAM,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;;gBAChE,MAAM,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACnD,CAAC;QAAC,MAAM,CAAC;YACP,qEAAqE;QACvE,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,uBAAuB,CAAC,OAMvC;IACC,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC;IAChC,IAAI,IAAI,KAAK,KAAK;QAAE,OAAO,SAAS,CAAC;IACrC,MAAM,KAAK,GACT,OAAO,CAAC,KAAK,CAAC,KAAK;QACnB,IAAI,mBAAmB,CAAC;YACtB,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG;YAC5B,QAAQ,EAAE,oBAAoB;YAC9B,QAAQ,EAAE,IAAI,KAAK,YAAY;SAChC,CAAC,CAAC;IACL,MAAM,OAAO,GAAG,eAAe,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACnD,MAAM,aAAa,GAAG,iBAAiB,EAAE,CAAC;IAC1C,OAAO;QACL,IAAI;QACJ,KAAK;QACL,cAAc,EAAE,OAAO,CAAC,YAAY,KAAK,CAAC;QAC1C,YAAY,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE;YAC1C,MAAM,SAAS,GAAG,kBAAkB,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;YAChE,OAAO,iBAAiB,CACtB,kBAAkB,CAAC;gBACjB,OAAO;gBACP,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,SAAS;gBACT,SAAS,EAAE,aAAa,CAAC,SAAS,CAAC;gBACnC,aAAa,EAAE,qBAAqB;aACrC,CAAC,CACH,CAAC;QACJ,CAAC;QACD,MAAM,EAAE,EAAE;KACX,CAAC;AACJ,CAAC"}