@jinn-network/client 0.1.6 → 0.1.7-canary.08ebd916

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 (390) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +67 -1
  3. package/deployments/deployment-jinn-mvi-l1-sepolia-fast.json +23 -4
  4. package/deployments/deployment-jinn-mvi-l1-sepolia.json +23 -4
  5. package/deployments/deployment-jinn-mvi-l2-baseSepolia.json +5 -4
  6. package/dist/adapters/mech/adapter.d.ts +38 -2
  7. package/dist/adapters/mech/adapter.js +269 -62
  8. package/dist/adapters/mech/adapter.js.map +1 -1
  9. package/dist/adapters/mech/contracts.d.ts +17 -4
  10. package/dist/adapters/mech/contracts.js +8 -2
  11. package/dist/adapters/mech/contracts.js.map +1 -1
  12. package/dist/adapters/mech/safe-revert.d.ts +20 -0
  13. package/dist/adapters/mech/safe-revert.js +12 -4
  14. package/dist/adapters/mech/safe-revert.js.map +1 -1
  15. package/dist/adapters/mech/safe.d.ts +6 -2
  16. package/dist/adapters/mech/safe.js +32 -11
  17. package/dist/adapters/mech/safe.js.map +1 -1
  18. package/dist/adapters/mech/types.d.ts +6 -1
  19. package/dist/adapters/mech/types.js.map +1 -1
  20. package/dist/adapters/mech/verdict-code.d.ts +1 -0
  21. package/dist/adapters/mech/verdict-code.js +18 -0
  22. package/dist/adapters/mech/verdict-code.js.map +1 -1
  23. package/dist/agent/operator-claude.js +8 -0
  24. package/dist/agent/operator-claude.js.map +1 -1
  25. package/dist/api/activity-events-endpoint.d.ts +14 -0
  26. package/dist/api/activity-events-endpoint.js +59 -0
  27. package/dist/api/activity-events-endpoint.js.map +1 -0
  28. package/dist/api/admin-endpoint.d.ts +15 -3
  29. package/dist/api/admin-endpoint.js +24 -2
  30. package/dist/api/admin-endpoint.js.map +1 -1
  31. package/dist/api/bootstrap-endpoint.d.ts +1 -2
  32. package/dist/api/bootstrap-endpoint.js +85 -18
  33. package/dist/api/bootstrap-endpoint.js.map +1 -1
  34. package/dist/api/codex-doctor-endpoint.d.ts +90 -0
  35. package/dist/api/codex-doctor-endpoint.js +296 -0
  36. package/dist/api/codex-doctor-endpoint.js.map +1 -0
  37. package/dist/api/discovery-endpoint.d.ts +1 -0
  38. package/dist/api/discovery-endpoint.js +26 -0
  39. package/dist/api/discovery-endpoint.js.map +1 -1
  40. package/dist/api/fleet-build.d.ts +1 -0
  41. package/dist/api/fleet-build.js +2 -1
  42. package/dist/api/fleet-build.js.map +1 -1
  43. package/dist/api/gather-status.d.ts +37 -0
  44. package/dist/api/gather-status.js +572 -19
  45. package/dist/api/gather-status.js.map +1 -1
  46. package/dist/api/hermes-doctor-endpoint.d.ts +128 -3
  47. package/dist/api/hermes-doctor-endpoint.js +265 -22
  48. package/dist/api/hermes-doctor-endpoint.js.map +1 -1
  49. package/dist/api/launcher-status.d.ts +25 -17
  50. package/dist/api/launcher-status.js +13 -11
  51. package/dist/api/launcher-status.js.map +1 -1
  52. package/dist/api/launcher-tasks.d.ts +1 -1
  53. package/dist/api/launcher-tasks.js +12 -8
  54. package/dist/api/launcher-tasks.js.map +1 -1
  55. package/dist/api/operator-artifacts-endpoint.js +73 -6
  56. package/dist/api/operator-artifacts-endpoint.js.map +1 -1
  57. package/dist/api/portfolio-v0-build.d.ts +10 -0
  58. package/dist/api/portfolio-v0-build.js +24 -5
  59. package/dist/api/portfolio-v0-build.js.map +1 -1
  60. package/dist/api/prediction-v1-build.d.ts +10 -0
  61. package/dist/api/prediction-v1-build.js +7 -1
  62. package/dist/api/prediction-v1-build.js.map +1 -1
  63. package/dist/api/server.d.ts +31 -1
  64. package/dist/api/server.js +95 -2
  65. package/dist/api/server.js.map +1 -1
  66. package/dist/api/setup-endpoints.d.ts +16 -0
  67. package/dist/api/setup-endpoints.js +89 -135
  68. package/dist/api/setup-endpoints.js.map +1 -1
  69. package/dist/api/setup-retry-endpoint.d.ts +19 -0
  70. package/dist/api/setup-retry-endpoint.js +32 -0
  71. package/dist/api/setup-retry-endpoint.js.map +1 -0
  72. package/dist/api/solvernets-endpoints.d.ts +8 -0
  73. package/dist/api/solvernets-endpoints.js +99 -60
  74. package/dist/api/solvernets-endpoints.js.map +1 -1
  75. package/dist/api/status-build.d.ts +168 -2
  76. package/dist/api/status-build.js +116 -27
  77. package/dist/api/status-build.js.map +1 -1
  78. package/dist/api/status-harness-rollup.d.ts +35 -0
  79. package/dist/api/status-harness-rollup.js +45 -0
  80. package/dist/api/status-harness-rollup.js.map +1 -0
  81. package/dist/api/task-run-routing.d.ts +7 -0
  82. package/dist/api/task-run-routing.js +12 -0
  83. package/dist/api/task-run-routing.js.map +1 -0
  84. package/dist/api/task-runs-build.d.ts +21 -0
  85. package/dist/api/task-runs-build.js +14 -1
  86. package/dist/api/task-runs-build.js.map +1 -1
  87. package/dist/build-info.json +4 -4
  88. package/dist/build-meta.json +1 -1
  89. package/dist/captures/live-publisher.js +24 -4
  90. package/dist/captures/live-publisher.js.map +1 -1
  91. package/dist/captures/publish.d.ts +1 -1
  92. package/dist/chain-read-errors.d.ts +10 -0
  93. package/dist/chain-read-errors.js +15 -0
  94. package/dist/chain-read-errors.js.map +1 -1
  95. package/dist/cli/commands/auth.js +1 -1
  96. package/dist/cli/commands/auth.js.map +1 -1
  97. package/dist/cli/commands/create.js +3 -2
  98. package/dist/cli/commands/create.js.map +1 -1
  99. package/dist/cli/commands/doctor.d.ts +2 -0
  100. package/dist/cli/commands/doctor.js +2 -0
  101. package/dist/cli/commands/doctor.js.map +1 -1
  102. package/dist/cli/commands/rewards.js +11 -7
  103. package/dist/cli/commands/rewards.js.map +1 -1
  104. package/dist/cli/commands/solver-nets.js +101 -15
  105. package/dist/cli/commands/solver-nets.js.map +1 -1
  106. package/dist/cli/commands/solver-plugins-block.d.ts +33 -0
  107. package/dist/cli/commands/solver-plugins-block.js +118 -0
  108. package/dist/cli/commands/solver-plugins-block.js.map +1 -0
  109. package/dist/cli/commands/solver-plugins-feedback.d.ts +72 -0
  110. package/dist/cli/commands/solver-plugins-feedback.js +262 -0
  111. package/dist/cli/commands/solver-plugins-feedback.js.map +1 -0
  112. package/dist/cli/commands/solver-plugins-read.d.ts +54 -0
  113. package/dist/cli/commands/solver-plugins-read.js +259 -0
  114. package/dist/cli/commands/solver-plugins-read.js.map +1 -0
  115. package/dist/cli/commands/solver-plugins.d.ts +35 -0
  116. package/dist/cli/commands/solver-plugins.js +399 -2
  117. package/dist/cli/commands/solver-plugins.js.map +1 -1
  118. package/dist/cli/commands/status.js +1 -1
  119. package/dist/cli/commands/status.js.map +1 -1
  120. package/dist/cli/commands/tasks.js +101 -11
  121. package/dist/cli/commands/tasks.js.map +1 -1
  122. package/dist/cli/commands/update.d.ts +10 -0
  123. package/dist/cli/commands/update.js +36 -0
  124. package/dist/cli/commands/update.js.map +1 -1
  125. package/dist/cli/introspection-context.js +5 -0
  126. package/dist/cli/introspection-context.js.map +1 -1
  127. package/dist/cli/task-native-readiness.d.ts +10 -1
  128. package/dist/cli/task-native-readiness.js +30 -6
  129. package/dist/cli/task-native-readiness.js.map +1 -1
  130. package/dist/config.d.ts +273 -235
  131. package/dist/config.js +305 -114
  132. package/dist/config.js.map +1 -1
  133. package/dist/daemon/checkpoint-loop.d.ts +48 -0
  134. package/dist/daemon/checkpoint-loop.js +76 -0
  135. package/dist/daemon/checkpoint-loop.js.map +1 -0
  136. package/dist/daemon/creator.d.ts +1 -1
  137. package/dist/daemon/creator.js +7 -3
  138. package/dist/daemon/creator.js.map +1 -1
  139. package/dist/daemon/daemon.d.ts +22 -0
  140. package/dist/daemon/daemon.js +156 -23
  141. package/dist/daemon/daemon.js.map +1 -1
  142. package/dist/daemon/eviction-loop.d.ts +40 -0
  143. package/dist/daemon/eviction-loop.js +67 -0
  144. package/dist/daemon/eviction-loop.js.map +1 -0
  145. package/dist/daemon/gate-logger.d.ts +9 -0
  146. package/dist/daemon/gate-logger.js +2 -0
  147. package/dist/daemon/gate-logger.js.map +1 -0
  148. package/dist/daemon/jinn-claim-loop-wiring.d.ts +33 -0
  149. package/dist/daemon/jinn-claim-loop-wiring.js +40 -0
  150. package/dist/daemon/jinn-claim-loop-wiring.js.map +1 -0
  151. package/dist/daemon/jinn-claim-loop.d.ts +24 -17
  152. package/dist/daemon/jinn-claim-loop.js +77 -23
  153. package/dist/daemon/jinn-claim-loop.js.map +1 -1
  154. package/dist/daemon/readiness-gate.d.ts +1 -4
  155. package/dist/daemon/readiness-gate.js.map +1 -1
  156. package/dist/daemon/skip-log-dedup.d.ts +69 -0
  157. package/dist/daemon/skip-log-dedup.js +106 -0
  158. package/dist/daemon/skip-log-dedup.js.map +1 -0
  159. package/dist/daemon/spend-cap-gate.d.ts +40 -0
  160. package/dist/daemon/spend-cap-gate.js +46 -0
  161. package/dist/daemon/spend-cap-gate.js.map +1 -0
  162. package/dist/dashboard/assets/index-C4huIsUW.css +32 -0
  163. package/dist/dashboard/assets/index-DkTglWXU.js +345 -0
  164. package/dist/dashboard/index.html +2 -2
  165. package/dist/discovery/factory.d.ts +17 -5
  166. package/dist/discovery/factory.js +46 -18
  167. package/dist/discovery/factory.js.map +1 -1
  168. package/dist/discovery/http.js +216 -3
  169. package/dist/discovery/http.js.map +1 -1
  170. package/dist/discovery/onchain.d.ts +5 -0
  171. package/dist/discovery/onchain.js +418 -15
  172. package/dist/discovery/onchain.js.map +1 -1
  173. package/dist/discovery/types.d.ts +75 -1
  174. package/dist/discovery/types.js +8 -10
  175. package/dist/discovery/types.js.map +1 -1
  176. package/dist/discovery/with-fallback.d.ts +7 -0
  177. package/dist/discovery/with-fallback.js +20 -0
  178. package/dist/discovery/with-fallback.js.map +1 -1
  179. package/dist/earning/bootstrap.d.ts +100 -4
  180. package/dist/earning/bootstrap.js +221 -74
  181. package/dist/earning/bootstrap.js.map +1 -1
  182. package/dist/earning/contracts.d.ts +14 -0
  183. package/dist/earning/contracts.js +17 -5
  184. package/dist/earning/contracts.js.map +1 -1
  185. package/dist/earning/funding-plan.js +27 -18
  186. package/dist/earning/funding-plan.js.map +1 -1
  187. package/dist/earning/jinn-rewards.d.ts +46 -0
  188. package/dist/earning/jinn-rewards.js +32 -0
  189. package/dist/earning/jinn-rewards.js.map +1 -1
  190. package/dist/earning/safe-adapter.d.ts +2 -0
  191. package/dist/earning/safe-adapter.js +37 -11
  192. package/dist/earning/safe-adapter.js.map +1 -1
  193. package/dist/earning/store.d.ts +8 -0
  194. package/dist/earning/store.js.map +1 -1
  195. package/dist/earning/testnet-setup-migration.d.ts +12 -0
  196. package/dist/earning/testnet-setup-migration.js +27 -1
  197. package/dist/earning/testnet-setup-migration.js.map +1 -1
  198. package/dist/earning/types.d.ts +21 -6
  199. package/dist/earning/viem-clients.d.ts +11 -4
  200. package/dist/earning/viem-clients.js +14 -5
  201. package/dist/earning/viem-clients.js.map +1 -1
  202. package/dist/erc8004/identity.d.ts +19 -3
  203. package/dist/erc8004/identity.js +21 -6
  204. package/dist/erc8004/identity.js.map +1 -1
  205. package/dist/erc8004/index.d.ts +1 -1
  206. package/dist/erc8004/index.js.map +1 -1
  207. package/dist/erc8004/reputation.d.ts +8 -0
  208. package/dist/erc8004/reputation.js +22 -3
  209. package/dist/erc8004/reputation.js.map +1 -1
  210. package/dist/events/types.d.ts +2 -2
  211. package/dist/harnesses/cost-estimates.d.ts +145 -0
  212. package/dist/harnesses/cost-estimates.js +297 -0
  213. package/dist/harnesses/cost-estimates.js.map +1 -0
  214. package/dist/harnesses/engine/engine.d.ts +78 -0
  215. package/dist/harnesses/engine/engine.js +153 -11
  216. package/dist/harnesses/engine/engine.js.map +1 -1
  217. package/dist/harnesses/engine/persistence.d.ts +51 -1
  218. package/dist/harnesses/engine/persistence.js +118 -5
  219. package/dist/harnesses/engine/persistence.js.map +1 -1
  220. package/dist/harnesses/engine/work-dir-reaper.d.ts +65 -0
  221. package/dist/harnesses/engine/work-dir-reaper.js +100 -0
  222. package/dist/harnesses/engine/work-dir-reaper.js.map +1 -0
  223. package/dist/harnesses/impls/hermes-agent/adapter.js +40 -0
  224. package/dist/harnesses/impls/hermes-agent/adapter.js.map +1 -1
  225. package/dist/harnesses/impls/hermes-agent/bootstrap.d.ts +20 -0
  226. package/dist/harnesses/impls/hermes-agent/bootstrap.js +40 -6
  227. package/dist/harnesses/impls/hermes-agent/bootstrap.js.map +1 -1
  228. package/dist/harnesses/impls/hermes-agent/harness.d.ts +59 -1
  229. package/dist/harnesses/impls/hermes-agent/harness.js +104 -0
  230. package/dist/harnesses/impls/hermes-agent/harness.js.map +1 -1
  231. package/dist/harnesses/impls/hermes-agent/prompt.d.ts +6 -6
  232. package/dist/harnesses/impls/hermes-agent/prompt.js +6 -6
  233. package/dist/harnesses/impls/index.d.ts +7 -0
  234. package/dist/harnesses/impls/index.js +16 -1
  235. package/dist/harnesses/impls/index.js.map +1 -1
  236. package/dist/harnesses/impls/learner/adapters/codex-code.d.ts +9 -0
  237. package/dist/harnesses/impls/learner/adapters/codex-code.js +30 -8
  238. package/dist/harnesses/impls/learner/adapters/codex-code.js.map +1 -1
  239. package/dist/harnesses/impls/learner/harness.d.ts +38 -4
  240. package/dist/harnesses/impls/learner/harness.js +96 -2
  241. package/dist/harnesses/impls/learner/harness.js.map +1 -1
  242. package/dist/harnesses/impls/learner/harvest.d.ts +1 -1
  243. package/dist/harnesses/impls/learner/harvest.js +23 -5
  244. package/dist/harnesses/impls/learner/harvest.js.map +1 -1
  245. package/dist/harnesses/impls/learner/plugin-path.d.ts +0 -13
  246. package/dist/harnesses/impls/learner/plugin-path.js +35 -15
  247. package/dist/harnesses/impls/learner/plugin-path.js.map +1 -1
  248. package/dist/harnesses/impls/learner/restoration-patch.d.ts +2 -2
  249. package/dist/harnesses/impls/learner/restoration-patch.js +25 -6
  250. package/dist/harnesses/impls/learner/restoration-patch.js.map +1 -1
  251. package/dist/harnesses/impls/learner/types.d.ts +11 -0
  252. package/dist/harnesses/impls/stub.d.ts +58 -0
  253. package/dist/harnesses/impls/stub.js +89 -0
  254. package/dist/harnesses/impls/stub.js.map +1 -0
  255. package/dist/harnesses/impls/swe-rebench-v2-evaluator/eval-runner.d.ts +69 -50
  256. package/dist/harnesses/impls/swe-rebench-v2-evaluator/eval-runner.js +178 -93
  257. package/dist/harnesses/impls/swe-rebench-v2-evaluator/eval-runner.js.map +1 -1
  258. package/dist/harnesses/impls/swe-rebench-v2-evaluator/harness.d.ts +12 -1
  259. package/dist/harnesses/impls/swe-rebench-v2-evaluator/harness.js +121 -7
  260. package/dist/harnesses/impls/swe-rebench-v2-evaluator/harness.js.map +1 -1
  261. package/dist/harnesses/impls/swe-rebench-v2-evaluator/hf-fetcher.d.ts +88 -4
  262. package/dist/harnesses/impls/swe-rebench-v2-evaluator/hf-fetcher.js +143 -22
  263. package/dist/harnesses/impls/swe-rebench-v2-evaluator/hf-fetcher.js.map +1 -1
  264. package/dist/harnesses/impls/swe-rebench-v2-evaluator/index.d.ts +6 -0
  265. package/dist/harnesses/impls/swe-rebench-v2-evaluator/index.js +1 -1
  266. package/dist/harnesses/impls/swe-rebench-v2-evaluator/index.js.map +1 -1
  267. package/dist/harnesses/readiness-registry.d.ts +7 -0
  268. package/dist/harnesses/readiness-registry.js +18 -1
  269. package/dist/harnesses/readiness-registry.js.map +1 -1
  270. package/dist/main.js +419 -111
  271. package/dist/main.js.map +1 -1
  272. package/dist/observability/emit-event.d.ts +3 -2
  273. package/dist/observability/emit-event.js +22 -1
  274. package/dist/observability/emit-event.js.map +1 -1
  275. package/dist/operator-errors.d.ts +7 -0
  276. package/dist/operator-errors.js +13 -1
  277. package/dist/operator-errors.js.map +1 -1
  278. package/dist/plugins/learner/.claude-plugin/plugin.json +9 -0
  279. package/dist/plugins/learner/.codex-plugin/plugin.json +39 -0
  280. package/dist/plugins/learner/AGENTS.md +40 -0
  281. package/dist/plugins/learner/CLAUDE.md +33 -0
  282. package/dist/plugins/learner/README.md +59 -0
  283. package/dist/plugins/learner/hooks/hooks.json +16 -0
  284. package/dist/plugins/learner/hooks/session-start +38 -0
  285. package/dist/plugins/learner/skills/learn/SKILL.md +412 -0
  286. package/dist/plugins/learner/skills/learn/analyst-prompt.md +68 -0
  287. package/dist/plugins/learner/skills/learn/consolidator-prompt.md +94 -0
  288. package/dist/plugins/learner/skills/learn/explorer-prompt.md +53 -0
  289. package/dist/plugins/learner/skills/learn/planner-prompt.md +87 -0
  290. package/dist/plugins/learner/skills/learn/promoter-prompt.md +113 -0
  291. package/dist/plugins/learner/skills/learn/step-worker-prompt.md +47 -0
  292. package/dist/plugins/learner/skills/learn/strategist-prompt.md +85 -0
  293. package/dist/preflight/rpc-network.d.ts +40 -0
  294. package/dist/preflight/rpc-network.js +67 -1
  295. package/dist/preflight/rpc-network.js.map +1 -1
  296. package/dist/restart-daemon.d.ts +90 -0
  297. package/dist/restart-daemon.js +95 -0
  298. package/dist/restart-daemon.js.map +1 -0
  299. package/dist/rpc/transport.d.ts +109 -0
  300. package/dist/rpc/transport.js +220 -0
  301. package/dist/rpc/transport.js.map +1 -0
  302. package/dist/scripts/donation-consumption-acceptance.js +7 -28
  303. package/dist/scripts/donation-consumption-acceptance.js.map +1 -1
  304. package/dist/setup/halt-mode.d.ts +14 -0
  305. package/dist/setup/halt-mode.js +17 -0
  306. package/dist/setup/halt-mode.js.map +1 -0
  307. package/dist/solver-nets/prediction-operator-ux.d.ts +1 -2
  308. package/dist/solver-nets/prediction-operator-ux.js +90 -47
  309. package/dist/solver-nets/prediction-operator-ux.js.map +1 -1
  310. package/dist/solver-nets/registry.d.ts +20 -1
  311. package/dist/solver-nets/registry.js +38 -25
  312. package/dist/solver-nets/registry.js.map +1 -1
  313. package/dist/solver-types/_swe-rebench-v2-pool-cache.d.ts +58 -0
  314. package/dist/solver-types/_swe-rebench-v2-pool-cache.js +87 -0
  315. package/dist/solver-types/_swe-rebench-v2-pool-cache.js.map +1 -0
  316. package/dist/solver-types/_swe-rebench-v2-pool.d.ts +9 -2
  317. package/dist/solver-types/_swe-rebench-v2-pool.js +15 -20
  318. package/dist/solver-types/_swe-rebench-v2-pool.js.map +1 -1
  319. package/dist/solver-types/_swe-rebench-v2-substrate.d.ts +1 -0
  320. package/dist/solver-types/_swe-rebench-v2-substrate.js +10 -0
  321. package/dist/solver-types/_swe-rebench-v2-substrate.js.map +1 -1
  322. package/dist/solver-types/_swe-rebench-v2-validated-pool.d.ts +94 -1
  323. package/dist/solver-types/_swe-rebench-v2-validated-pool.js +305 -39
  324. package/dist/solver-types/_swe-rebench-v2-validated-pool.js.map +1 -1
  325. package/dist/solver-types/swe-rebench-v2-auto.d.ts +22 -7
  326. package/dist/solver-types/swe-rebench-v2-auto.js +57 -20
  327. package/dist/solver-types/swe-rebench-v2-auto.js.map +1 -1
  328. package/dist/solver-types/swe-rebench-v2.d.ts +18 -2
  329. package/dist/solver-types/swe-rebench-v2.js +310 -94
  330. package/dist/solver-types/swe-rebench-v2.js.map +1 -1
  331. package/dist/solvernets/daemon-init.d.ts +10 -2
  332. package/dist/solvernets/daemon-init.js +22 -2
  333. package/dist/solvernets/daemon-init.js.map +1 -1
  334. package/dist/solvernets/launched-record-dispatcher.d.ts +4 -0
  335. package/dist/solvernets/launched-record-dispatcher.js +44 -7
  336. package/dist/solvernets/launched-record-dispatcher.js.map +1 -1
  337. package/dist/solvernets/store.d.ts +5 -0
  338. package/dist/solvernets/store.js +1 -0
  339. package/dist/solvernets/store.js.map +1 -1
  340. package/dist/spend/credential.d.ts +8 -0
  341. package/dist/spend/credential.js +30 -0
  342. package/dist/spend/credential.js.map +1 -0
  343. package/dist/spend/daemon-config.d.ts +13 -0
  344. package/dist/spend/daemon-config.js +24 -0
  345. package/dist/spend/daemon-config.js.map +1 -0
  346. package/dist/spend/pricing.d.ts +16 -0
  347. package/dist/spend/pricing.js +26 -0
  348. package/dist/spend/pricing.js.map +1 -0
  349. package/dist/spend/record.d.ts +13 -0
  350. package/dist/spend/record.js +30 -0
  351. package/dist/spend/record.js.map +1 -0
  352. package/dist/spend/usage.d.ts +27 -0
  353. package/dist/spend/usage.js +113 -0
  354. package/dist/spend/usage.js.map +1 -0
  355. package/dist/store/store.d.ts +61 -0
  356. package/dist/store/store.js +302 -7
  357. package/dist/store/store.js.map +1 -1
  358. package/dist/tasks/sources.d.ts +18 -1
  359. package/dist/tasks/sources.js +33 -5
  360. package/dist/tasks/sources.js.map +1 -1
  361. package/dist/trajectory/transcript-parsers/types.d.ts +8 -8
  362. package/dist/tx-retry.d.ts +166 -19
  363. package/dist/tx-retry.js +310 -32
  364. package/dist/tx-retry.js.map +1 -1
  365. package/dist/types/payloads/prediction-apy-v0.d.ts +5 -5
  366. package/dist/types/payloads/prediction-v0.d.ts +5 -5
  367. package/dist/types/task-document.d.ts +392 -0
  368. package/dist/types/task-document.js +10 -0
  369. package/dist/types/task-document.js.map +1 -1
  370. package/dist/types/task.d.ts +28 -0
  371. package/dist/util/extract-tx-hash.d.ts +14 -0
  372. package/dist/util/extract-tx-hash.js +19 -0
  373. package/dist/util/extract-tx-hash.js.map +1 -0
  374. package/dist/vendor/@jinn-network/sdk/dist/contracts.js +1 -1
  375. package/dist/vendor/@jinn-network/sdk/dist/solvernets/manifest-schema.d.ts +3 -0
  376. package/dist/vendor/@jinn-network/sdk/dist/solvernets/manifest-schema.js +1 -0
  377. package/package.json +36 -13
  378. package/plugins/swe-rebench-v2-diffmin/README.md +10 -9
  379. package/plugins/swe-rebench-v2-diffmin/jinn.plugin.json +1 -1
  380. package/plugins/swe-rebench-v2-diffmin/skills/diffmin/SKILL.md +15 -10
  381. package/plugins/swe-rebench-v2-diffmin/skills/test-map/SKILL.md +10 -12
  382. package/plugins/swe-rebench-v2-runtime/.claude-plugin/plugin.json +1 -1
  383. package/plugins/swe-rebench-v2-runtime/.codex-plugin/plugin.json +3 -3
  384. package/plugins/swe-rebench-v2-runtime/README.md +6 -6
  385. package/plugins/swe-rebench-v2-runtime/jinn.plugin.json +2 -3
  386. package/plugins/swe-rebench-v2-runtime/skills/task/SKILL.md +69 -0
  387. package/dist/dashboard/assets/index-DOlzFN8a.css +0 -32
  388. package/dist/dashboard/assets/index-NkZ7CTAT.js +0 -140
  389. package/plugins/swe-rebench-v2-runtime/skills/orient/SKILL.md +0 -29
  390. package/plugins/swe-rebench-v2-runtime/skills/plan/SKILL.md +0 -53
@@ -4,11 +4,23 @@ import { privateKeyToAccount } from 'viem/accounts';
4
4
  import { base, baseSepolia } from 'viem/chains';
5
5
  import { PermanentError, parseTask } from '../../types/index.js';
6
6
  import { createClients } from './safe.js';
7
+ /**
8
+ * Coalesce a string-or-array RPC input down to the head URL for display in
9
+ * error contexts (`formatRpcError` expects a single host). The adapter
10
+ * accepts the full fallback chain at the type level; this helper exists so
11
+ * the error-formatting call sites can keep their old signature.
12
+ */
13
+ function rpcUrlForDisplay(rpcUrl) {
14
+ return Array.isArray(rpcUrl) ? rpcUrl[0] : rpcUrl;
15
+ }
7
16
  import { buildResultPayload, uploadToIpfs, cidToDigestHex, fetchFromIpfs, fetchSignedTaskFromIpfs, fetchSignedEnvelopeFromIpfs, } from './ipfs.js';
8
17
  import { canonicalJson } from '../../harnesses/engine/canonical-json.js';
9
- import { SignedEnvelopeSchema } from '../../types/envelope.js';
18
+ import { normalizeEnvelopeRole, SignedEnvelopeSchema } from '../../types/envelope.js';
10
19
  import { submitTask, claimTask as claimTaskOnchain, claimEvaluation as claimEvaluationOnchain, claimDelivery, getMechDeliveryRate, getTimeoutBounds, decodeTaskCreatedLogs, decodeSolutionDeliveryClaimedLogs, decodeDeliverLogs, findLatestDeliveryDataHexForRequest, getMarketplaceRequestDeliveryMech, getTaskCidDigest, callDeliverToMarketplace, canClaimTask, canClaimEvaluation, } from './contracts.js';
20
+ import { isNonRecoverableInnerRevert } from './safe-revert.js';
21
+ import { verdictCodeFromValue } from './verdict-code.js';
11
22
  import { manifestDigestForCid } from './digest.js';
23
+ import { emitStructured } from '../../events/emitter.js';
12
24
  import { withRecoverableRetry } from '../../tx-retry.js';
13
25
  import { formatRpcError } from '../../rpc-error-context.js';
14
26
  import { SOLUTION_ENVELOPE_CID_CONTEXT_KEY, SOLUTION_TASK_CID_CONTEXT_KEY, RESTORATION_TASK_CID_CONTEXT_KEY, } from '../../harnesses/impls/evaluation-context.js';
@@ -16,6 +28,28 @@ import { signTaskV1 } from '../../tasks/signing.js';
16
28
  const ROUTER_REQUEST_CURSOR_CONFIG_KEY = 'mech_router_request_block_cursor_v1';
17
29
  const PENDING_EVALUATION_SOLUTIONS_CONFIG_KEY = 'mech_pending_evaluation_solutions_v1';
18
30
  const DEFAULT_MECH_DELIVER_BACKFILL_LOOKBACK_BLOCKS = 100000n;
31
+ /** Yield to the event loop every N evaluation opportunities so a large retry
32
+ * backlog can't starve the HTTP API mid-cycle. */
33
+ const EVALUATION_RETRY_YIELD_EVERY = 10;
34
+ /**
35
+ * Decide whether a `canClaimEvaluation` failure means the opportunity can NEVER
36
+ * become claimable (terminal, prune it) versus one that could still clear later
37
+ * (transient, keep retrying).
38
+ *
39
+ * Classification is done on the *structured* `revertName` decoded straight from
40
+ * the inner revert data — not by regex-unformatting the operator-facing `reason`
41
+ * string. The format→regex round-trip was fragile: an arg value containing a
42
+ * `(` corrupted the strip, and the `flattenErrorMessage` fallback produced
43
+ * arbitrary text the regex mangled, silently mis-classifying opportunities.
44
+ *
45
+ * A false-keep (re-checking a dead opportunity) only costs one more RPC; a
46
+ * false-prune (dropping a still-claimable opportunity) loses real work — so
47
+ * when in doubt we keep. Anything without a known non-recoverable revert name
48
+ * is treated as transient.
49
+ */
50
+ function isTerminalEvaluationReason(revertName) {
51
+ return isNonRecoverableInnerRevert(revertName);
52
+ }
19
53
  const DEFAULT_ROUTER_LOG_CHUNK_BLOCKS = 9999n;
20
54
  /**
21
55
  * Floor block for the on-chain TaskCreated backlog scan, per chain.
@@ -81,8 +115,18 @@ export class MechAdapter {
81
115
  deliveryBlockCursor = 0n;
82
116
  pendingEvaluations = new Map();
83
117
  observedTasks = new Map();
118
+ /**
119
+ * Read-through cache for `restorationAnnouncementForTaskId` — the restoration
120
+ * task body looked up *while building an evaluation opportunity*. Kept
121
+ * SEPARATE from `observedTasks` (the `watchForTasks` discovery dedup set) on
122
+ * purpose: writing the restoration body into `observedTasks` made the
123
+ * TaskCreated scan skip that taskId as a *restoration* opportunity just
124
+ * because the daemon had built an *evaluation* opportunity for someone
125
+ * else's attempt on it. That blocked the creator's own daemon from claiming
126
+ * its own attempt on a multi-attempt (`maxClaims > 1`) task it posted.
127
+ */
128
+ restorationBodyCache = new Map();
84
129
  requestKinds = new Map();
85
- claimedRestorationTaskIds = new Set();
86
130
  evaluationOpportunities = new Map();
87
131
  pendingEvaluationSolutions = new Map();
88
132
  // Original Tasks keyed by request ID (restoration and evaluation)
@@ -104,7 +148,7 @@ export class MechAdapter {
104
148
  formatRpcError(message, {
105
149
  operation: 'getBlockNumber',
106
150
  chain: this.config.chainId === 84532 ? 'base-sepolia' : 'base',
107
- rpcUrl: this.config.rpcUrl,
151
+ rpcUrl: rpcUrlForDisplay(this.config.rpcUrl),
108
152
  }));
109
153
  },
110
154
  });
@@ -236,6 +280,35 @@ export class MechAdapter {
236
280
  return;
237
281
  this.persistPendingEvaluationSolutions();
238
282
  }
283
+ clearPendingDeliveryRecoveryState(requestId) {
284
+ this.originalStates.delete(requestId);
285
+ this.pendingEvaluations.delete(requestId);
286
+ this.requestKinds.delete(requestId);
287
+ }
288
+ recoveryDeliveryExpirySeconds(requestId) {
289
+ const task = this.originalStates.get(requestId) ?? this.pendingEvaluations.get(requestId);
290
+ const claimPolicy = task?.claimPolicy ?? DEFAULT_MECH_CLAIM_POLICY;
291
+ const normalizeTsToSeconds = (value) => {
292
+ if (value == null)
293
+ return undefined;
294
+ return value > 10_000_000_000 ? Math.floor(value / 1000) : value;
295
+ };
296
+ const submissionDeadlineSeconds = normalizeTsToSeconds(claimPolicy.submissionDeadlineTs);
297
+ if (submissionDeadlineSeconds != null)
298
+ return submissionDeadlineSeconds;
299
+ const claimWindowEndSeconds = normalizeTsToSeconds(claimPolicy.claimWindowEndTs ?? task?.window?.endTs);
300
+ if (claimWindowEndSeconds == null)
301
+ return undefined;
302
+ return claimWindowEndSeconds + claimPolicy.claimLeaseTtlSeconds;
303
+ }
304
+ shouldSkipExpiredRecoveryDelivery(requestId, currentChainTimestampSeconds, recoveryExpirySeconds) {
305
+ if (currentChainTimestampSeconds <= recoveryExpirySeconds)
306
+ return false;
307
+ console.error(`[mech] skipping recovery delivery for ${requestId}: ` +
308
+ `submission deadline expired at ${new Date(recoveryExpirySeconds * 1000).toISOString()}`);
309
+ this.clearPendingDeliveryRecoveryState(requestId);
310
+ return true;
311
+ }
239
312
  async postTask(state) {
240
313
  const restorationState = {
241
314
  ...state,
@@ -264,18 +337,21 @@ export class MechAdapter {
264
337
  const manifestDigest = keccak256(toBytes(signedTask.solverNetManifestCid));
265
338
  const policy = this.contractPolicyForTask(restorationState);
266
339
  const taskSubmission = await submitTask(this.publicClient, this.walletClient, this.config.safeAddress, this.config.routerAddress, restorationDataHex, manifestDigest, policy, deliveryRate, deliveryRate, maxTimeout, this.config.evictionRecovery);
267
- const announcement = {
268
- taskId: taskSubmission.taskId,
269
- task: {
270
- ...restorationState,
271
- signedTask,
272
- context: { ...(restorationState.context ?? {}), [SOLUTION_TASK_CID_CONTEXT_KEY]: restorationTaskCid },
273
- },
274
- taskCid: restorationTaskCid,
275
- onchainCreationTx: taskSubmission.txHash,
276
- onchainCreationBlock: taskSubmission.blockNumber,
277
- };
278
- this.observedTasks.set(taskSubmission.taskId, announcement);
340
+ // Deliberately do NOT seed `observedTasks` with the task we just posted.
341
+ // `observedTasks` is the dedup set for `watchForTasks`: the on-chain
342
+ // TaskCreated scan skips any taskId already in it (so a task is announced
343
+ // to the engine-watcher at most once). Seeding it here marked the
344
+ // creator's own task as "already announced" before it was ever yielded —
345
+ // which permanently prevented the *creator's own daemon* from discovering,
346
+ // claiming, and solving a task it posted. On a multi-attempt task
347
+ // (`maxClaims > 1`) the creator running the solver role is legitimate
348
+ // (the protocol forbids only self-*evaluation*, and that on a per-attempt
349
+ // basis), and on testnet it is the intended single-operator dogfood path
350
+ // — post → claim → solve → grade → settle from one daemon. The dedup is
351
+ // still correct: it now keys only on tasks `watchForTasks` actually
352
+ // yielded. `restorationAnnouncementForTaskId` re-hydrates from chain/IPFS
353
+ // on a cache miss, so dropping the pre-seed costs at most one redundant
354
+ // fetch if the creator later claims its own task.
279
355
  return {
280
356
  taskId: taskSubmission.taskId,
281
357
  taskCid: restorationTaskCid,
@@ -348,7 +424,14 @@ export class MechAdapter {
348
424
  maxClaimsPerOperator: claimPolicy.maxClaimsPerOperator,
349
425
  policyHook: (claimPolicy.policyHook ?? zeroAddress),
350
426
  evaluationPolicy: {
351
- requiredVerdicts: 1,
427
+ // `requiredVerdicts` defaults to 1 but is overridable via the task's
428
+ // claim policy. A value > 1 opens additional verdict claim slots per
429
+ // attempt; combined with the per-evaluator cap below (1), it
430
+ // guarantees an honest evaluator can still claim and deliver a slot
431
+ // even when other evaluators have squatted some — the structural fix
432
+ // for a shared/adversarial testnet where a non-delivering claimer
433
+ // would otherwise permanently lock a single-slot attempt.
434
+ requiredVerdicts: claimPolicy.requiredVerdicts ?? 1,
352
435
  passThreshold: 1,
353
436
  evaluationDeadline: submissionDeadline + BigInt(claimPolicy.claimLeaseTtlSeconds),
354
437
  maxVerdictsPerEvaluator: 1,
@@ -381,7 +464,11 @@ export class MechAdapter {
381
464
  };
382
465
  }
383
466
  async restorationAnnouncementForTaskId(taskId) {
384
- const cached = this.observedTasks.get(taskId);
467
+ // Read-through `restorationBodyCache` — NOT `observedTasks`. This helper is
468
+ // an evaluation-path lookup of a task's restoration body; caching it into
469
+ // the `watchForTasks` discovery dedup set would suppress the creator's own
470
+ // restoration-claim discovery for the same taskId (see field comment).
471
+ const cached = this.restorationBodyCache.get(taskId) ?? this.observedTasks.get(taskId);
385
472
  if (cached)
386
473
  return cached;
387
474
  const taskCidDigest = await getTaskCidDigest(this.publicClient, this.config.routerAddress, taskId);
@@ -394,7 +481,7 @@ export class MechAdapter {
394
481
  task,
395
482
  taskCid,
396
483
  };
397
- this.observedTasks.set(taskId, announcement);
484
+ this.restorationBodyCache.set(taskId, announcement);
398
485
  return announcement;
399
486
  }
400
487
  async restorationAnnouncementFromDigest(params) {
@@ -440,8 +527,6 @@ export class MechAdapter {
440
527
  for (const candidate of candidates) {
441
528
  if (!this.isDiscoveryTaskAllowed(candidate.taskId))
442
529
  continue;
443
- if (this.claimedRestorationTaskIds.has(candidate.taskId))
444
- continue;
445
530
  // gh #300 ghost-task floor — same floor as the on-chain TaskCreated
446
531
  // backlog scan, applied to the DiscoveryAPI path too. Without this,
447
532
  // the Ponder indexer (or onchain floor's listClaimableTasks) returns
@@ -465,19 +550,40 @@ export class MechAdapter {
465
550
  continue;
466
551
  }
467
552
  try {
553
+ // Yield every hydrated candidate per cycle rather than returning after
554
+ // the first. The engine-watcher (daemon._runEngineWatcherLoop) is the
555
+ // single point of skip-state truth — when its in-flight admission gate
556
+ // fast-skips a candidate (~30s TTL), that skip state never flows back
557
+ // into the adapter's iteration cursor. Yielding only the first
558
+ // candidate per cycle meant a fast-skipped slot starved every
559
+ // subsequent candidate in the round-robin (`fc05f686`) ordering for
560
+ // the duration of the TTL. By driving the full candidate list per
561
+ // cycle we let the engine apply its gate to each one, preserving the
562
+ // round-robin fairness across joined SolverNets. See task 212 live
563
+ // verification in the fix's commit body.
468
564
  yield await this.restorationAnnouncementFromDigest({
469
565
  taskId: candidate.taskId,
470
566
  taskCidDigest: candidate.taskCidDigest,
471
567
  transactionHash: candidate.createdAtTx,
472
568
  blockNumber: candidate.createdAtBlock,
473
569
  });
474
- return;
475
570
  }
476
571
  catch (err) {
477
572
  console.error(`[mech] failed to hydrate subgraph task ${candidate.taskId}:`, err instanceof Error ? err.message : err);
478
573
  }
479
574
  }
480
575
  }
576
+ /**
577
+ * Look up the Deliver-event envelope CID for a pending evaluation solution.
578
+ *
579
+ * Returns `null` when the Deliver event is not present in the configured
580
+ * lookback window. This is a terminal signal for the caller — re-running the
581
+ * same lookup later is deterministically futile when `solution.blockNumber`
582
+ * is set (toBlock is fixed at the SolutionDeliveryClaimed block), and is
583
+ * monotonically less likely to find the event when toBlock follows chain head
584
+ * (the window slides forward, away from any older Deliver event). Callers
585
+ * should prune the pending solution on `null` rather than retry — see #553.
586
+ */
481
587
  async deliveryEnvelopeCidForSolution(solution) {
482
588
  const deliveryMech = await getMarketplaceRequestDeliveryMech(this.publicClient, this.config.mechMarketplaceAddress, solution.requestId);
483
589
  const toBlock = solution.blockNumber != null
@@ -488,8 +594,7 @@ export class MechAdapter {
488
594
  const fromBlock = toBlock > lookback ? toBlock - lookback : 0n;
489
595
  const deliveryDataHex = await findLatestDeliveryDataHexForRequest(this.publicClient, deliveryMech, solution.requestId, fromBlock, toBlock);
490
596
  if (!deliveryDataHex) {
491
- throw new Error(`No Deliver event data found for solution ${solution.requestId} on mech ${deliveryMech} ` +
492
- `between blocks ${fromBlock} and ${toBlock}`);
597
+ return null;
493
598
  }
494
599
  const digest = deliveryDataHex.startsWith('0x') ? deliveryDataHex.slice(2) : deliveryDataHex;
495
600
  return `f01551220${digest}`;
@@ -500,14 +605,34 @@ export class MechAdapter {
500
605
  this.forgetPendingEvaluationSolution(solution.requestId);
501
606
  return undefined;
502
607
  }
503
- const restoration = await this.restorationAnnouncementForTaskId(solution.taskId);
608
+ // Cheap claimability gate FIRST — before the restoration lookup + IPFS
609
+ // fetch. A backlog of terminal opportunities (finalized / evaluation
610
+ // deadline passed / max verdicts reached) must not pay the expensive
611
+ // restoration-announcement cost on every poll cycle. Terminal reasons are
612
+ // pruned from the working set so the loop never re-scans on-chain history;
613
+ // transient reasons are left in place to be retried next cycle.
504
614
  const claimable = await canClaimEvaluation(this.publicClient, this.config.safeAddress, this.config.routerAddress, solution.taskId, solution.attemptIndex, this.config.mechContractAddress);
505
615
  if (!claimable.ok) {
506
- console.log(`[mech] skipping evaluation opportunity ${solution.requestId} for task ${solution.taskId}/${solution.attemptIndex}: ${claimable.reason}`);
507
- this.forgetPendingEvaluationSolution(solution.requestId);
616
+ const terminal = isTerminalEvaluationReason(claimable.revertName);
617
+ console.log(`[mech] skipping evaluation opportunity ${solution.requestId} for task ${solution.taskId}/${solution.attemptIndex}: ${claimable.reason}` +
618
+ (terminal ? ' (terminal — pruned)' : ' (transient — will retry)'));
619
+ if (terminal) {
620
+ this.forgetPendingEvaluationSolution(solution.requestId);
621
+ }
508
622
  return undefined;
509
623
  }
624
+ const restoration = await this.restorationAnnouncementForTaskId(solution.taskId);
510
625
  const solutionEnvelopeCid = await this.deliveryEnvelopeCidForSolution(solution);
626
+ if (solutionEnvelopeCid == null) {
627
+ // #553: Deliver event is not within the configured lookback window. A
628
+ // retry with the same toBlock cannot reach an older event, so this is
629
+ // terminal — prune so the loop never re-pays the canClaimEvaluation +
630
+ // restoration lookup cost on a deterministically-failing opportunity.
631
+ console.log(`[mech] pruning evaluation opportunity ${solution.requestId} for task ${solution.taskId}/${solution.attemptIndex}: ` +
632
+ `no Deliver event found within configured lookback (terminal — pruned)`);
633
+ this.forgetPendingEvaluationSolution(solution.requestId);
634
+ return undefined;
635
+ }
511
636
  const resultPayload = await fetchFromIpfs(this.config.ipfsGatewayUrl, solutionEnvelopeCid);
512
637
  const resultData = resultPayload.data ?? JSON.stringify(resultPayload);
513
638
  const evaluationTask = this.buildEvaluationTask({
@@ -535,15 +660,21 @@ export class MechAdapter {
535
660
  return announcement;
536
661
  }
537
662
  async *retryPendingEvaluationSolutions() {
663
+ let processed = 0;
538
664
  for (const [requestId, solution] of Array.from(this.pendingEvaluationSolutions)) {
665
+ // Yield to the event loop periodically so a large backlog of pending
666
+ // evaluation solutions can't starve the HTTP API mid-cycle.
667
+ if (processed > 0 && processed % EVALUATION_RETRY_YIELD_EVERY === 0) {
668
+ await new Promise((resolve) => setImmediate(resolve));
669
+ }
670
+ processed++;
539
671
  try {
540
672
  const announcement = await this.evaluationAnnouncementForSolution(solution);
541
673
  if (announcement) {
542
674
  yield announcement;
543
675
  }
544
- else {
545
- this.forgetPendingEvaluationSolution(requestId);
546
- }
676
+ // No announcement does NOT mean "forget" — pruning is owned by
677
+ // evaluationAnnouncementForSolution, which only removes terminal cases.
547
678
  }
548
679
  catch (err) {
549
680
  console.error(`[mech] evaluation opportunity retry failed for ${requestId}:`, err);
@@ -576,7 +707,7 @@ export class MechAdapter {
576
707
  for (const { taskId, taskCidDigest, manifestDigest, transactionHash, blockNumber } of createdTasks) {
577
708
  if (!this.isDiscoveryTaskAllowed(taskId))
578
709
  continue;
579
- if (this.claimedRestorationTaskIds.has(taskId) || this.observedTasks.has(taskId))
710
+ if (this.observedTasks.has(taskId))
580
711
  continue;
581
712
  if (joinedManifestDigests.size > 0 && !joinedManifestDigests.has(manifestDigest.toLowerCase()))
582
713
  continue;
@@ -605,7 +736,7 @@ export class MechAdapter {
605
736
  console.error('[mech] Error polling for tasks:', formatRpcError(err, {
606
737
  operation: 'pollTaskCreated',
607
738
  chain: this.config.chainId === 84532 ? 'base-sepolia' : 'base',
608
- rpcUrl: this.config.rpcUrl,
739
+ rpcUrl: rpcUrlForDisplay(this.config.rpcUrl),
609
740
  contract: this.config.routerAddress,
610
741
  fromBlock: this.requestBlockCursor + 1n,
611
742
  }));
@@ -644,7 +775,6 @@ export class MechAdapter {
644
775
  }
645
776
  const claimed = await claimTaskOnchain(this.publicClient, this.walletClient, this.config.safeAddress, this.config.routerAddress, taskId, this.config.mechContractAddress, this.config.evictionRecovery);
646
777
  const task = announcement.task;
647
- this.claimedRestorationTaskIds.add(claimed.taskId);
648
778
  this.pendingEvaluations.set(claimed.requestId, task);
649
779
  this.originalStates.set(claimed.requestId, { ...task, role: task.role ?? 'restoration' });
650
780
  this.requestKinds.set(claimed.requestId, 'solution');
@@ -676,9 +806,13 @@ export class MechAdapter {
676
806
  async submitVerdictDelivery(requestId, verdictDigest, verdictCode) {
677
807
  await claimDelivery(this.publicClient, this.walletClient, this.config.safeAddress, this.config.routerAddress, requestId, { variant: 'v3', kind: 'verdict', evidenceHash: verdictDigest, verdictCode }, this.config.evictionRecovery);
678
808
  }
679
- async evidenceHashForDelivery(requestId, deliveryDataHex) {
809
+ async deliveryClaimForDelivery(requestId, deliveryDataHex) {
810
+ const fallbackKind = this.requestKinds.get(requestId) ?? 'solution';
680
811
  if (this.config.routerClaimDeliveryVariant !== 'v2' && this.config.routerClaimDeliveryVariant !== 'v3') {
681
- return undefined;
812
+ return {
813
+ evidenceHash: undefined,
814
+ kind: fallbackKind,
815
+ };
682
816
  }
683
817
  const deliveryDigest = deliveryDataHex.startsWith('0x')
684
818
  ? deliveryDataHex.slice(2)
@@ -686,11 +820,6 @@ export class MechAdapter {
686
820
  const envelopeCid = `f01551220${deliveryDigest}`;
687
821
  const rawEnvelope = await fetchSignedEnvelopeFromIpfs(this.config.ipfsGatewayUrl, envelopeCid);
688
822
  const parsed = SignedEnvelopeSchema.parse(rawEnvelope);
689
- // Strip signature to recompute the hash over the unsigned body.
690
- //
691
- // Important: compute over the fetched wire object, not over the parsed
692
- // schema result. The schema normalizes some nested objects and may strip
693
- // extension metadata that was present when the envelope was signed.
694
823
  const rawSigned = rawEnvelope;
695
824
  const { signature: _rawSignature, ...unsignedBody } = rawSigned;
696
825
  const signature = parsed.signature;
@@ -699,22 +828,36 @@ export class MechAdapter {
699
828
  if (recomputed !== signature.hash) {
700
829
  throw new Error(`recomputed hash ${recomputed} !== envelope.signature.hash ${signature.hash}`);
701
830
  }
702
- return recomputed;
831
+ const role = normalizeEnvelopeRole(parsed.role);
832
+ if (role === 'capture') {
833
+ throw new Error(`unsupported delivery envelope role=capture for requestId ${requestId}`);
834
+ }
835
+ const kind = role === 'verdict' ? 'verdict' : 'solution';
836
+ const payload = rawSigned['payload'];
837
+ const rawVerdict = payload != null && typeof payload === 'object'
838
+ ? payload['verdict']
839
+ : undefined;
840
+ return {
841
+ evidenceHash: recomputed,
842
+ kind,
843
+ verdictCode: kind === 'verdict' ? verdictCodeFromValue(rawVerdict) : undefined,
844
+ };
703
845
  }
704
846
  async ensureDeliveryClaimed(requestId, deliveryDataHex) {
705
- let evidenceHash;
847
+ let claimOptions;
706
848
  try {
707
- evidenceHash = await this.evidenceHashForDelivery(requestId, deliveryDataHex);
849
+ claimOptions = await this.deliveryClaimForDelivery(requestId, deliveryDataHex);
708
850
  }
709
851
  catch (err) {
710
- console.error(`[mech] evidenceHash derivation failed for ${requestId} — skipping claim, will retry on next loop:`, err);
852
+ console.error(`[mech] delivery claim metadata derivation failed for ${requestId} — skipping claim, will retry on next loop:`, err);
711
853
  return 'retry';
712
854
  }
713
855
  try {
714
856
  await claimDelivery(this.publicClient, this.walletClient, this.config.safeAddress, this.config.routerAddress, requestId, {
715
857
  variant: this.config.routerClaimDeliveryVariant,
716
- kind: this.requestKinds.get(requestId) ?? 'solution',
717
- evidenceHash,
858
+ kind: claimOptions.kind,
859
+ evidenceHash: claimOptions.evidenceHash,
860
+ verdictCode: claimOptions.verdictCode,
718
861
  }, this.config.evictionRecovery);
719
862
  return 'claimed';
720
863
  }
@@ -728,22 +871,66 @@ export class MechAdapter {
728
871
  return 'already-claimed';
729
872
  }
730
873
  console.error(`[mech] claimDelivery failed for ${requestId}:`, err);
874
+ // Paired SSE signal for the operator-app `claim_failed` notification
875
+ // (OPERATOR-APP-SPEC §2.10). The early-return branches above
876
+ // (`skipped` / `already-claimed`) are not failures and intentionally do not emit.
877
+ emitStructured({
878
+ kind: 'intent',
879
+ message: 'Delivery claim failed',
880
+ requestId,
881
+ errorCode: 'claim_failed',
882
+ details: {
883
+ kind: claimOptions.kind,
884
+ source: 'mech.claimDelivery',
885
+ error: message,
886
+ },
887
+ });
731
888
  return 'retry';
732
889
  }
733
890
  }
891
+ /**
892
+ * Paginate `getLogs` over `[deliveryBlockCursor+1, currentBlock]` chunked by
893
+ * `DEFAULT_ROUTER_LOG_CHUNK_BLOCKS` to honor RPC provider block-range limits
894
+ * (Tenderly base-sepolia caps at 100k; sepolia.base.org ~1k). Advances +
895
+ * persists `deliveryBlockCursor` per chunk so a mid-scan RPC failure on a
896
+ * later chunk does not strand the cursor at the pre-poll value (#552).
897
+ *
898
+ * Yields each chunk's decoded Deliver entries so the consumer can process
899
+ * them with the live "current block" context (needed for the recovery-
900
+ * delivery timestamp cache).
901
+ */
902
+ async *scanDeliveryLogChunks(currentBlock) {
903
+ while (currentBlock > this.deliveryBlockCursor) {
904
+ const chunkStart = this.deliveryBlockCursor + 1n;
905
+ const chunkEnd = chunkStart + DEFAULT_ROUTER_LOG_CHUNK_BLOCKS > currentBlock
906
+ ? currentBlock
907
+ : chunkStart + DEFAULT_ROUTER_LOG_CHUNK_BLOCKS;
908
+ const logs = await this.publicClient.getLogs({
909
+ address: this.config.mechContractAddress,
910
+ fromBlock: chunkStart,
911
+ toBlock: chunkEnd,
912
+ });
913
+ // Advance + persist BEFORE yielding so partial progress is durable even
914
+ // if a downstream throw escapes back through the for-await consumer.
915
+ this.deliveryBlockCursor = chunkEnd;
916
+ if (this.store) {
917
+ this.store.setLastProcessedBlock(this.deliveryBlockCursor);
918
+ }
919
+ yield decodeDeliverLogs(logs);
920
+ }
921
+ }
734
922
  async *watchForDeliveries() {
735
923
  while (!this.stopped) {
736
924
  try {
737
925
  const currentBlock = await this.publicClient.getBlockNumber();
738
- if (currentBlock > this.deliveryBlockCursor) {
739
- const logs = await this.publicClient.getLogs({
740
- address: this.config.mechContractAddress,
741
- fromBlock: this.deliveryBlockCursor + 1n,
742
- toBlock: currentBlock,
743
- });
744
- this.deliveryBlockCursor = currentBlock;
745
- const decoded = decodeDeliverLogs(logs);
746
- for (const { requestId, deliveryDataHex, mechAddress } of decoded) {
926
+ // Caches scoped to the whole poll iteration: the "current block"
927
+ // reference does not change across chunks.
928
+ const blockTimestampSecondsByNumber = new Map();
929
+ let currentBlockTimestampSeconds;
930
+ for await (const decoded of this.scanDeliveryLogChunks(currentBlock)) {
931
+ if (this.stopped)
932
+ break;
933
+ for (const { requestId, deliveryDataHex, mechAddress, blockNumber } of decoded) {
747
934
  // Two concerns, independent:
748
935
  // (a) Did this Safe DELIVER this? → claim it (counter credit goes to msg.sender)
749
936
  // The Deliver event's mechAddress is mechServiceMultisig (the Safe that owns
@@ -753,6 +940,30 @@ export class MechAdapter {
753
940
  const iCreatedRestoration = this.pendingEvaluations.has(requestId);
754
941
  if (!iDelivered && !iCreatedRestoration)
755
942
  continue;
943
+ if (iCreatedRestoration) {
944
+ const recoveryExpirySeconds = this.recoveryDeliveryExpirySeconds(requestId);
945
+ if (recoveryExpirySeconds != null) {
946
+ let deliveryTimestampSeconds;
947
+ if (blockNumber != null) {
948
+ deliveryTimestampSeconds = blockTimestampSecondsByNumber.get(blockNumber);
949
+ if (deliveryTimestampSeconds == null) {
950
+ const deliveryBlockData = await this.publicClient.getBlock({ blockNumber });
951
+ deliveryTimestampSeconds = Number(deliveryBlockData.timestamp);
952
+ blockTimestampSecondsByNumber.set(blockNumber, deliveryTimestampSeconds);
953
+ }
954
+ }
955
+ else {
956
+ if (currentBlockTimestampSeconds == null) {
957
+ const currentBlockData = await this.publicClient.getBlock({ blockNumber: currentBlock });
958
+ currentBlockTimestampSeconds = Number(currentBlockData.timestamp);
959
+ }
960
+ deliveryTimestampSeconds = currentBlockTimestampSeconds;
961
+ }
962
+ if (this.shouldSkipExpiredRecoveryDelivery(requestId, deliveryTimestampSeconds, recoveryExpirySeconds)) {
963
+ continue;
964
+ }
965
+ }
966
+ }
756
967
  // (a) Deliverer-side claim path: if this Safe delivered the request,
757
968
  // claim it first so router counters credit the deliverer.
758
969
  let deliveryClaimStatus;
@@ -788,9 +999,7 @@ export class MechAdapter {
788
999
  deliveryMechAddress: mechAddress,
789
1000
  };
790
1001
  // Clean up after yielding
791
- this.originalStates.delete(requestId);
792
- this.pendingEvaluations.delete(requestId);
793
- this.requestKinds.delete(requestId);
1002
+ this.clearPendingDeliveryRecoveryState(requestId);
794
1003
  }
795
1004
  catch (err) {
796
1005
  console.error(`[mech] Failed to parse delivery ${requestId}:`, err);
@@ -802,15 +1011,13 @@ export class MechAdapter {
802
1011
  console.error('[mech] Error polling for deliveries:', formatRpcError(err, {
803
1012
  operation: 'pollDeliveries',
804
1013
  chain: this.config.chainId === 84532 ? 'base-sepolia' : 'base',
805
- rpcUrl: this.config.rpcUrl,
1014
+ rpcUrl: rpcUrlForDisplay(this.config.rpcUrl),
806
1015
  contract: this.config.mechContractAddress,
807
1016
  fromBlock: this.deliveryBlockCursor + 1n,
808
1017
  }));
809
1018
  }
810
- // Persist block cursor for crash recovery
811
- if (this.store && this.deliveryBlockCursor > 0n) {
812
- this.store.setLastProcessedBlock(this.deliveryBlockCursor);
813
- }
1019
+ // Cursor persistence is per-chunk inside the loop above (#552). A poll
1020
+ // that did no chunked work has no progress to persist.
814
1021
  await new Promise(r => setTimeout(r, this.config.pollIntervalMs));
815
1022
  }
816
1023
  }