@jinn-network/client 0.1.5 → 0.1.6-canary.0b4ff7f9

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 (326) hide show
  1. package/CHANGELOG.md +98 -0
  2. package/dist/adapters/mech/adapter.js +7 -7
  3. package/dist/adapters/mech/adapter.js.map +1 -1
  4. package/dist/adapters/mech/ipfs-pinfile.d.ts +22 -0
  5. package/dist/adapters/mech/ipfs-pinfile.js +54 -0
  6. package/dist/adapters/mech/ipfs-pinfile.js.map +1 -0
  7. package/dist/adapters/mech/ipfs.d.ts +1 -0
  8. package/dist/adapters/mech/ipfs.js +24 -1
  9. package/dist/adapters/mech/ipfs.js.map +1 -1
  10. package/dist/api/bootstrap-endpoint.js +2 -0
  11. package/dist/api/bootstrap-endpoint.js.map +1 -1
  12. package/dist/api/discovery-endpoint.d.ts +18 -0
  13. package/dist/api/discovery-endpoint.js +65 -0
  14. package/dist/api/discovery-endpoint.js.map +1 -0
  15. package/dist/api/fleet-build.d.ts +7 -0
  16. package/dist/api/fleet-build.js +6 -1
  17. package/dist/api/fleet-build.js.map +1 -1
  18. package/dist/api/harness-readiness-endpoint.d.ts +13 -0
  19. package/dist/api/harness-readiness-endpoint.js +15 -0
  20. package/dist/api/harness-readiness-endpoint.js.map +1 -0
  21. package/dist/api/hermes-doctor-endpoint.d.ts +26 -0
  22. package/dist/api/hermes-doctor-endpoint.js +29 -0
  23. package/dist/api/hermes-doctor-endpoint.js.map +1 -0
  24. package/dist/api/server.d.ts +21 -0
  25. package/dist/api/server.js +22 -0
  26. package/dist/api/server.js.map +1 -1
  27. package/dist/build-info.json +4 -4
  28. package/dist/build-meta.json +1 -1
  29. package/dist/cli/commands/create.d.ts +5 -3
  30. package/dist/cli/commands/create.js +101 -36
  31. package/dist/cli/commands/create.js.map +1 -1
  32. package/dist/cli/commands/solver-nets.d.ts +19 -0
  33. package/dist/cli/commands/solver-nets.js +140 -2
  34. package/dist/cli/commands/solver-nets.js.map +1 -1
  35. package/dist/cli/commands/solver-plugins-publish.d.ts +31 -0
  36. package/dist/cli/commands/solver-plugins-publish.js +169 -0
  37. package/dist/cli/commands/solver-plugins-publish.js.map +1 -0
  38. package/dist/cli/commands/solver-plugins-revoke.d.ts +15 -0
  39. package/dist/cli/commands/solver-plugins-revoke.js +91 -0
  40. package/dist/cli/commands/solver-plugins-revoke.js.map +1 -0
  41. package/dist/cli/commands/solver-plugins.d.ts +50 -6
  42. package/dist/cli/commands/solver-plugins.js +205 -68
  43. package/dist/cli/commands/solver-plugins.js.map +1 -1
  44. package/dist/config.d.ts +27 -0
  45. package/dist/config.js +24 -0
  46. package/dist/config.js.map +1 -1
  47. package/dist/conformance/checks/hash-signature.js +6 -2
  48. package/dist/conformance/checks/hash-signature.js.map +1 -1
  49. package/dist/conformance/checks/payload.js +4 -2
  50. package/dist/conformance/checks/payload.js.map +1 -1
  51. package/dist/conformance/checks/verdict.d.ts +10 -10
  52. package/dist/conformance/checks/verdict.js +16 -15
  53. package/dist/conformance/checks/verdict.js.map +1 -1
  54. package/dist/conformance/harness.d.ts +1 -1
  55. package/dist/conformance/harness.js +16 -9
  56. package/dist/conformance/harness.js.map +1 -1
  57. package/dist/conformance/types.d.ts +10 -3
  58. package/dist/conformance/types.js.map +1 -1
  59. package/dist/corpus/acquire.d.ts +1 -3
  60. package/dist/corpus/acquire.js.map +1 -1
  61. package/dist/corpus/envelope-projection.d.ts +1 -1
  62. package/dist/corpus/envelope-projection.js +14 -7
  63. package/dist/corpus/envelope-projection.js.map +1 -1
  64. package/dist/corpus/index.d.ts +2 -1
  65. package/dist/corpus/index.js.map +1 -1
  66. package/dist/corpus/prediction-brier-scoreboard-report.js +1 -1
  67. package/dist/corpus/prediction-brier-scoreboard-report.js.map +1 -1
  68. package/dist/corpus/prediction-brier-scoreboard.js +3 -1
  69. package/dist/corpus/prediction-brier-scoreboard.js.map +1 -1
  70. package/dist/corpus/types.d.ts +2 -2
  71. package/dist/daemon/daemon.d.ts +17 -1
  72. package/dist/daemon/daemon.js +15 -0
  73. package/dist/daemon/daemon.js.map +1 -1
  74. package/dist/daemon/freeze-fence.js +6 -3
  75. package/dist/daemon/freeze-fence.js.map +1 -1
  76. package/dist/daemon/readiness-gate.d.ts +30 -0
  77. package/dist/daemon/readiness-gate.js +31 -0
  78. package/dist/daemon/readiness-gate.js.map +1 -0
  79. package/dist/dashboard/assets/{index-D_NMfDfV.css → index-B4sTrvQD.css} +1 -1
  80. package/dist/dashboard/assets/index-C5j0ZJWS.js +140 -0
  81. package/dist/dashboard/index.html +2 -2
  82. package/dist/discovery/http.js +121 -0
  83. package/dist/discovery/http.js.map +1 -1
  84. package/dist/discovery/onchain.js +11 -0
  85. package/dist/discovery/onchain.js.map +1 -1
  86. package/dist/discovery/types.d.ts +112 -0
  87. package/dist/discovery/types.js.map +1 -1
  88. package/dist/discovery/with-fallback.js +9 -0
  89. package/dist/discovery/with-fallback.js.map +1 -1
  90. package/dist/earning/agent-wallet-binding.d.ts +20 -1
  91. package/dist/earning/agent-wallet-binding.js +54 -16
  92. package/dist/earning/agent-wallet-binding.js.map +1 -1
  93. package/dist/earning/bootstrap.d.ts +55 -0
  94. package/dist/earning/bootstrap.js +376 -20
  95. package/dist/earning/bootstrap.js.map +1 -1
  96. package/dist/earning/store.js +48 -1
  97. package/dist/earning/store.js.map +1 -1
  98. package/dist/earning/types.d.ts +30 -0
  99. package/dist/earning/types.js +37 -0
  100. package/dist/earning/types.js.map +1 -1
  101. package/dist/erc8004/abis.d.ts +64 -0
  102. package/dist/erc8004/abis.js +48 -0
  103. package/dist/erc8004/abis.js.map +1 -1
  104. package/dist/erc8004/plugin-registry.d.ts +102 -0
  105. package/dist/erc8004/plugin-registry.js +165 -0
  106. package/dist/erc8004/plugin-registry.js.map +1 -0
  107. package/dist/harnesses/engine/engine.js +15 -3
  108. package/dist/harnesses/engine/engine.js.map +1 -1
  109. package/dist/harnesses/engine/envelope-assembly.d.ts +2 -2
  110. package/dist/harnesses/engine/envelope-assembly.js +4 -2
  111. package/dist/harnesses/engine/envelope-assembly.js.map +1 -1
  112. package/dist/harnesses/freeze.d.ts +4 -1
  113. package/dist/harnesses/freeze.js +12 -2
  114. package/dist/harnesses/freeze.js.map +1 -1
  115. package/dist/harnesses/impls/claude-mcp-prediction/index.d.ts +4 -1
  116. package/dist/harnesses/impls/claude-mcp-prediction/index.js +7 -2
  117. package/dist/harnesses/impls/claude-mcp-prediction/index.js.map +1 -1
  118. package/dist/harnesses/impls/claude-mcp-prediction-apy/index.d.ts +4 -1
  119. package/dist/harnesses/impls/claude-mcp-prediction-apy/index.js +7 -2
  120. package/dist/harnesses/impls/claude-mcp-prediction-apy/index.js.map +1 -1
  121. package/dist/harnesses/impls/evaluation-context.d.ts +15 -4
  122. package/dist/harnesses/impls/evaluation-context.js +24 -8
  123. package/dist/harnesses/impls/evaluation-context.js.map +1 -1
  124. package/dist/harnesses/impls/hermes-agent/adapter.d.ts +34 -0
  125. package/dist/harnesses/impls/hermes-agent/adapter.js +184 -0
  126. package/dist/harnesses/impls/hermes-agent/adapter.js.map +1 -0
  127. package/dist/harnesses/impls/hermes-agent/bootstrap.d.ts +18 -0
  128. package/dist/harnesses/impls/hermes-agent/bootstrap.js +231 -0
  129. package/dist/harnesses/impls/hermes-agent/bootstrap.js.map +1 -0
  130. package/dist/harnesses/impls/hermes-agent/config-builder.d.ts +49 -0
  131. package/dist/harnesses/impls/hermes-agent/config-builder.js +104 -0
  132. package/dist/harnesses/impls/hermes-agent/config-builder.js.map +1 -0
  133. package/dist/harnesses/impls/hermes-agent/harness.d.ts +30 -0
  134. package/dist/harnesses/impls/hermes-agent/harness.js +52 -0
  135. package/dist/harnesses/impls/hermes-agent/harness.js.map +1 -0
  136. package/dist/harnesses/impls/hermes-agent/index.d.ts +5 -0
  137. package/dist/harnesses/impls/hermes-agent/index.js +7 -0
  138. package/dist/harnesses/impls/hermes-agent/index.js.map +1 -0
  139. package/dist/harnesses/impls/hermes-agent/prompt.d.ts +15 -0
  140. package/dist/harnesses/impls/hermes-agent/prompt.js +37 -0
  141. package/dist/harnesses/impls/hermes-agent/prompt.js.map +1 -0
  142. package/dist/harnesses/impls/index.d.ts +6 -0
  143. package/dist/harnesses/impls/index.js +17 -4
  144. package/dist/harnesses/impls/index.js.map +1 -1
  145. package/dist/harnesses/impls/learner/adapters/claude-code.js.map +1 -0
  146. package/dist/harnesses/impls/{claude-code-learner → learner}/adapters/codex-code.js +13 -34
  147. package/dist/harnesses/impls/learner/adapters/codex-code.js.map +1 -0
  148. package/dist/harnesses/impls/learner/adapters/codex-workspace.js.map +1 -0
  149. package/dist/harnesses/impls/{claude-code-learner → learner}/harness.d.ts +9 -3
  150. package/dist/harnesses/impls/{claude-code-learner → learner}/harness.js +24 -1
  151. package/dist/harnesses/impls/learner/harness.js.map +1 -0
  152. package/dist/harnesses/impls/{claude-code-learner → learner}/harvest.js +15 -3
  153. package/dist/harnesses/impls/learner/harvest.js.map +1 -0
  154. package/dist/harnesses/impls/{claude-code-learner → learner}/index.d.ts +5 -5
  155. package/dist/harnesses/impls/{claude-code-learner → learner}/index.js +4 -4
  156. package/dist/harnesses/impls/learner/index.js.map +1 -0
  157. package/dist/harnesses/impls/{claude-code-learner → learner}/plugin-path.d.ts +4 -4
  158. package/dist/harnesses/impls/{claude-code-learner → learner}/plugin-path.js +7 -7
  159. package/dist/harnesses/impls/learner/plugin-path.js.map +1 -0
  160. package/dist/harnesses/impls/{claude-code-learner → learner}/restoration-patch.js +3 -1
  161. package/dist/harnesses/impls/learner/restoration-patch.js.map +1 -0
  162. package/dist/harnesses/impls/learner/test-utils/fake-plugin-outputs.js.map +1 -0
  163. package/dist/harnesses/impls/learner/test-utils/noop-adapter.js.map +1 -0
  164. package/dist/harnesses/impls/{claude-code-learner → learner}/types.d.ts +12 -2
  165. package/dist/harnesses/impls/learner/types.js.map +1 -0
  166. package/dist/harnesses/impls/portfolio-v0-evaluator/index.js +13 -12
  167. package/dist/harnesses/impls/portfolio-v0-evaluator/index.js.map +1 -1
  168. package/dist/harnesses/impls/prediction-apy-v0-evaluator/index.js +7 -7
  169. package/dist/harnesses/impls/prediction-apy-v0-evaluator/index.js.map +1 -1
  170. package/dist/harnesses/impls/prediction-apy-v0-evaluator/parse-submission.d.ts +3 -3
  171. package/dist/harnesses/impls/prediction-apy-v0-evaluator/parse-submission.js +7 -6
  172. package/dist/harnesses/impls/prediction-apy-v0-evaluator/parse-submission.js.map +1 -1
  173. package/dist/harnesses/impls/prediction-v0-evaluator/checks/integrity.js +1 -1
  174. package/dist/harnesses/impls/prediction-v0-evaluator/checks/integrity.js.map +1 -1
  175. package/dist/harnesses/impls/prediction-v0-evaluator/index.js +11 -10
  176. package/dist/harnesses/impls/prediction-v0-evaluator/index.js.map +1 -1
  177. package/dist/harnesses/impls/prediction-v1-evaluator/index.js +11 -10
  178. package/dist/harnesses/impls/prediction-v1-evaluator/index.js.map +1 -1
  179. package/dist/harnesses/impls/swe-rebench-v2-evaluator/eval-runner.d.ts +1 -0
  180. package/dist/harnesses/impls/swe-rebench-v2-evaluator/eval-runner.js +10 -2
  181. package/dist/harnesses/impls/swe-rebench-v2-evaluator/eval-runner.js.map +1 -1
  182. package/dist/harnesses/impls/swe-rebench-v2-evaluator/harness.d.ts +24 -5
  183. package/dist/harnesses/impls/swe-rebench-v2-evaluator/harness.js +104 -4
  184. package/dist/harnesses/impls/swe-rebench-v2-evaluator/harness.js.map +1 -1
  185. package/dist/harnesses/impls/swe-rebench-v2-evaluator/hf-fetcher.d.ts +9 -0
  186. package/dist/harnesses/impls/swe-rebench-v2-evaluator/hf-fetcher.js +25 -1
  187. package/dist/harnesses/impls/swe-rebench-v2-evaluator/hf-fetcher.js.map +1 -1
  188. package/dist/harnesses/names.d.ts +1 -0
  189. package/dist/harnesses/names.js +3 -0
  190. package/dist/harnesses/names.js.map +1 -1
  191. package/dist/harnesses/readiness-registry.d.ts +48 -0
  192. package/dist/harnesses/readiness-registry.js +136 -0
  193. package/dist/harnesses/readiness-registry.js.map +1 -0
  194. package/dist/harnesses/types.d.ts +7 -0
  195. package/dist/main.d.ts +14 -0
  196. package/dist/main.js +70 -35
  197. package/dist/main.js.map +1 -1
  198. package/dist/mcp/server.js +14 -13
  199. package/dist/mcp/server.js.map +1 -1
  200. package/dist/preflight/claude-auth.d.ts +18 -0
  201. package/dist/preflight/claude-auth.js +38 -0
  202. package/dist/preflight/claude-auth.js.map +1 -1
  203. package/dist/scripts/donation-consumption-acceptance.js +1 -1
  204. package/dist/scripts/donation-consumption-acceptance.js.map +1 -1
  205. package/dist/scripts/swe-rebench-v2-known-bad.json +12 -0
  206. package/dist/scripts/swe-rebench-v2-seed-pool.json +26 -0
  207. package/dist/solver-types/_swe-rebench-v2-substrate.d.ts +52 -0
  208. package/dist/solver-types/_swe-rebench-v2-substrate.js +76 -0
  209. package/dist/solver-types/_swe-rebench-v2-substrate.js.map +1 -0
  210. package/dist/solver-types/_swe-rebench-v2-validated-pool.d.ts +38 -12
  211. package/dist/solver-types/_swe-rebench-v2-validated-pool.js +136 -27
  212. package/dist/solver-types/_swe-rebench-v2-validated-pool.js.map +1 -1
  213. package/dist/solver-types/swe-rebench-v2-auto.d.ts +6 -0
  214. package/dist/solver-types/swe-rebench-v2-auto.js.map +1 -1
  215. package/dist/solver-types/swe-rebench-v2.d.ts +1 -0
  216. package/dist/solver-types/swe-rebench-v2.js +19 -6
  217. package/dist/solver-types/swe-rebench-v2.js.map +1 -1
  218. package/dist/store/store.js +12 -4
  219. package/dist/store/store.js.map +1 -1
  220. package/dist/templates/plugins/runtime-plugin/.mcp.json.tmpl +8 -0
  221. package/dist/templates/plugins/runtime-plugin/README.md.tmpl +30 -0
  222. package/dist/templates/plugins/runtime-plugin/gitignore.tmpl +3 -0
  223. package/dist/templates/plugins/runtime-plugin/jinn.plugin.json.tmpl +21 -0
  224. package/dist/templates/plugins/runtime-plugin/mcp/server.mjs.tmpl +33 -0
  225. package/dist/templates/plugins/runtime-plugin/package.json.tmpl +15 -0
  226. package/dist/templates/plugins/runtime-plugin/test/plugin.test.ts.tmpl +35 -0
  227. package/dist/templates/plugins/runtime-plugin/tsconfig.json.tmpl +11 -0
  228. package/dist/templates/plugins/solver-type-plugin/README.md.tmpl +35 -0
  229. package/dist/templates/plugins/solver-type-plugin/gitignore.tmpl +3 -0
  230. package/dist/templates/plugins/solver-type-plugin/jinn.plugin.json.tmpl +11 -0
  231. package/dist/templates/plugins/solver-type-plugin/package.json.tmpl +15 -0
  232. package/dist/templates/plugins/solver-type-plugin/skills/example/SKILL.md.tmpl +10 -0
  233. package/dist/templates/plugins/solver-type-plugin/test/plugin.test.ts.tmpl +25 -0
  234. package/dist/templates/plugins/solver-type-plugin/tsconfig.json.tmpl +11 -0
  235. package/dist/types/envelope.d.ts +28 -21
  236. package/dist/types/envelope.js +8 -3
  237. package/dist/types/envelope.js.map +1 -1
  238. package/dist/types/payloads/index.d.ts +2 -2
  239. package/dist/types/payloads/index.js +13 -12
  240. package/dist/types/payloads/index.js.map +1 -1
  241. package/dist/types/payloads/portfolio-v0.d.ts +60 -10
  242. package/dist/types/payloads/portfolio-v0.js +16 -6
  243. package/dist/types/payloads/portfolio-v0.js.map +1 -1
  244. package/dist/types/payloads/prediction-apy-v0.d.ts +52 -10
  245. package/dist/types/payloads/prediction-apy-v0.js +16 -6
  246. package/dist/types/payloads/prediction-apy-v0.js.map +1 -1
  247. package/dist/types/payloads/prediction-v0.d.ts +49 -10
  248. package/dist/types/payloads/prediction-v0.js +16 -6
  249. package/dist/types/payloads/prediction-v0.js.map +1 -1
  250. package/dist/vendor/@jinn-network/sdk/dist/payloads/prediction-v1.d.ts +45 -6
  251. package/dist/vendor/@jinn-network/sdk/dist/payloads/prediction-v1.js +16 -6
  252. package/dist/x402/handler.js +51 -20
  253. package/dist/x402/handler.js.map +1 -1
  254. package/package.json +8 -3
  255. package/plugins/swe-rebench-v2-diffmin/.claude-plugin/plugin.json +5 -0
  256. package/plugins/swe-rebench-v2-diffmin/.mcp.json +8 -0
  257. package/plugins/swe-rebench-v2-diffmin/README.md +69 -0
  258. package/plugins/swe-rebench-v2-diffmin/jinn.plugin.json +12 -0
  259. package/plugins/swe-rebench-v2-diffmin/mcp/diff-stats-server.mjs +72 -0
  260. package/plugins/swe-rebench-v2-diffmin/mcp/diff-stats.mjs +48 -0
  261. package/plugins/swe-rebench-v2-diffmin/package.json +19 -0
  262. package/plugins/swe-rebench-v2-diffmin/skills/diffmin/SKILL.md +116 -0
  263. package/plugins/swe-rebench-v2-diffmin/skills/test-map/SKILL.md +126 -0
  264. package/plugins/swe-rebench-v2-diffmin/test/diff-stats.test.ts +62 -0
  265. package/plugins/swe-rebench-v2-diffmin/test/manifest.test.ts +53 -0
  266. package/plugins/swe-rebench-v2-diffmin/tsconfig.json +12 -0
  267. package/plugins/swe-rebench-v2-runtime/README.md +13 -0
  268. package/plugins/swe-rebench-v2-runtime/skills/orient/SKILL.md +7 -3
  269. package/plugins/swe-rebench-v2-runtime/skills/plan/SKILL.md +6 -17
  270. package/templates/plugins/runtime-plugin/.mcp.json.tmpl +8 -0
  271. package/templates/plugins/runtime-plugin/README.md.tmpl +30 -0
  272. package/templates/plugins/runtime-plugin/gitignore.tmpl +3 -0
  273. package/templates/plugins/runtime-plugin/jinn.plugin.json.tmpl +21 -0
  274. package/templates/plugins/runtime-plugin/mcp/server.mjs.tmpl +33 -0
  275. package/templates/plugins/runtime-plugin/package.json.tmpl +15 -0
  276. package/templates/plugins/runtime-plugin/test/plugin.test.ts.tmpl +35 -0
  277. package/templates/plugins/runtime-plugin/tsconfig.json.tmpl +11 -0
  278. package/templates/plugins/solver-type-plugin/README.md.tmpl +35 -0
  279. package/templates/plugins/solver-type-plugin/gitignore.tmpl +3 -0
  280. package/templates/plugins/solver-type-plugin/jinn.plugin.json.tmpl +11 -0
  281. package/templates/plugins/solver-type-plugin/package.json.tmpl +15 -0
  282. package/templates/plugins/solver-type-plugin/skills/example/SKILL.md.tmpl +10 -0
  283. package/templates/plugins/solver-type-plugin/test/plugin.test.ts.tmpl +25 -0
  284. package/templates/plugins/solver-type-plugin/tsconfig.json.tmpl +11 -0
  285. package/dist/dashboard/assets/index-BjtltOGc.js +0 -76
  286. package/dist/harnesses/impls/claude-code-learner/adapters/claude-code.js.map +0 -1
  287. package/dist/harnesses/impls/claude-code-learner/adapters/codex-code.js.map +0 -1
  288. package/dist/harnesses/impls/claude-code-learner/adapters/codex-workspace.js.map +0 -1
  289. package/dist/harnesses/impls/claude-code-learner/harness.js.map +0 -1
  290. package/dist/harnesses/impls/claude-code-learner/harvest.js.map +0 -1
  291. package/dist/harnesses/impls/claude-code-learner/index.js.map +0 -1
  292. package/dist/harnesses/impls/claude-code-learner/plugin-path.js.map +0 -1
  293. package/dist/harnesses/impls/claude-code-learner/restoration-patch.js.map +0 -1
  294. package/dist/harnesses/impls/claude-code-learner/test-utils/fake-plugin-outputs.js.map +0 -1
  295. package/dist/harnesses/impls/claude-code-learner/test-utils/noop-adapter.js.map +0 -1
  296. package/dist/harnesses/impls/claude-code-learner/types.js.map +0 -1
  297. package/dist/preflight/claude-required.d.ts +0 -8
  298. package/dist/preflight/claude-required.js +0 -17
  299. package/dist/preflight/claude-required.js.map +0 -1
  300. /package/dist/harnesses/impls/{claude-code-learner → learner}/adapters/claude-code.d.ts +0 -0
  301. /package/dist/harnesses/impls/{claude-code-learner → learner}/adapters/claude-code.js +0 -0
  302. /package/dist/harnesses/impls/{claude-code-learner → learner}/adapters/codex-code.d.ts +0 -0
  303. /package/dist/harnesses/impls/{claude-code-learner → learner}/adapters/codex-workspace.d.ts +0 -0
  304. /package/dist/harnesses/impls/{claude-code-learner → learner}/adapters/codex-workspace.js +0 -0
  305. /package/dist/harnesses/impls/{claude-code-learner → learner}/harvest.d.ts +0 -0
  306. /package/dist/harnesses/impls/{claude-code-learner → learner}/restoration-patch.d.ts +0 -0
  307. /package/dist/harnesses/impls/{claude-code-learner → learner}/test-utils/fake-plugin-outputs.d.ts +0 -0
  308. /package/dist/harnesses/impls/{claude-code-learner → learner}/test-utils/fake-plugin-outputs.js +0 -0
  309. /package/dist/harnesses/impls/{claude-code-learner → learner}/test-utils/noop-adapter.d.ts +0 -0
  310. /package/dist/harnesses/impls/{claude-code-learner → learner}/test-utils/noop-adapter.js +0 -0
  311. /package/dist/harnesses/impls/{claude-code-learner → learner}/types.js +0 -0
  312. /package/plugins/{claude-code-learner → learner}/.claude-plugin/plugin.json +0 -0
  313. /package/plugins/{claude-code-learner → learner}/.codex-plugin/plugin.json +0 -0
  314. /package/plugins/{claude-code-learner → learner}/AGENTS.md +0 -0
  315. /package/plugins/{claude-code-learner → learner}/CLAUDE.md +0 -0
  316. /package/plugins/{claude-code-learner → learner}/README.md +0 -0
  317. /package/plugins/{claude-code-learner → learner}/hooks/hooks.json +0 -0
  318. /package/plugins/{claude-code-learner → learner}/hooks/session-start +0 -0
  319. /package/plugins/{claude-code-learner → learner}/skills/learn/SKILL.md +0 -0
  320. /package/plugins/{claude-code-learner → learner}/skills/learn/analyst-prompt.md +0 -0
  321. /package/plugins/{claude-code-learner → learner}/skills/learn/consolidator-prompt.md +0 -0
  322. /package/plugins/{claude-code-learner → learner}/skills/learn/explorer-prompt.md +0 -0
  323. /package/plugins/{claude-code-learner → learner}/skills/learn/planner-prompt.md +0 -0
  324. /package/plugins/{claude-code-learner → learner}/skills/learn/promoter-prompt.md +0 -0
  325. /package/plugins/{claude-code-learner → learner}/skills/learn/step-worker-prompt.md +0 -0
  326. /package/plugins/{claude-code-learner → learner}/skills/learn/strategist-prompt.md +0 -0
@@ -45,6 +45,16 @@ export interface FleetBootstrapperOptions {
45
45
  * testnet funding an explicit operator action.
46
46
  */
47
47
  autoTestnetFaucet?: boolean;
48
+ /**
49
+ * Max in-process attempts for the ERC-8004 Safe-binding step (jinn-mono-h74p).
50
+ * Defaults to 3. Tests pass small values to keep retry budgets predictable.
51
+ */
52
+ safeBindingMaxAttempts?: number;
53
+ /**
54
+ * Delay between Safe-binding retries (jinn-mono-h74p). Defaults to 3000 ms
55
+ * (~1.5 Base Sepolia blocks). Tests pass 0 to skip the sleep entirely.
56
+ */
57
+ safeBindingRetryDelayMs?: number;
48
58
  }
49
59
  export declare class FleetBootstrapper {
50
60
  private readonly store;
@@ -60,6 +70,8 @@ export declare class FleetBootstrapper {
60
70
  private readonly faucetLoopTimeoutMs;
61
71
  private readonly now;
62
72
  private readonly autoTestnetFaucet;
73
+ private readonly safeBindingMaxAttempts;
74
+ private readonly safeBindingRetryDelayMs;
63
75
  constructor(options?: FleetBootstrapperOptions);
64
76
  getStatus(): Promise<FleetState>;
65
77
  /**
@@ -83,6 +95,43 @@ export declare class FleetBootstrapper {
83
95
  * IdentityCard's "binding pending" chip on Overview.
84
96
  */
85
97
  retryAgentBindingFor(serviceIndex: number, password: string): Promise<FleetState>;
98
+ /**
99
+ * Stage 1 — Identity (universal). Walks: wallet → predict Safe (from
100
+ * HD-index-1 agent EOA) → ETH funding gate → deploy Safe → mint agentId
101
+ * + setAgentWallet via ERC-1271. Idempotent and re-entrant. Does NOT
102
+ * touch service rows or staking — those belong to Stage 2.
103
+ *
104
+ * Fleet-level fields written:
105
+ * - fleet_safe_address (after predict)
106
+ * - fleet_agent_id, fleet_identity_registry, fleet_stage='stage1'
107
+ * (after mint + bind)
108
+ *
109
+ * Funding gate: requires ETH on the master EOA only (no OLAS). On testnet,
110
+ * the existing CDP faucet loop drains as usual when `autoTestnetFaucet`
111
+ * is enabled.
112
+ *
113
+ * See docs/superpowers/specs/2026-05-13-plug-in-builder-entry-point-design.md §5.1.
114
+ */
115
+ ensureStage1(password: string): Promise<FleetBootstrapResult>;
116
+ /**
117
+ * Stage 1 + Stage 2 — full operator bootstrap. Calls `ensureStage1`
118
+ * first; on success, walks Stage 2 per service. Builder-only users who
119
+ * have completed Stage 1 and call this method later begin Stage 2 from
120
+ * `awaiting_stake` for the first service row (created lazily here).
121
+ *
122
+ * Two-Safe topology in standard mode: `fleet_safe_address !==
123
+ * services[0].safe_address` because Stage 2's `distributor.stake()`
124
+ * creates its own Safe. In self-bond mode the two converge (both
125
+ * derived from HD-index-1).
126
+ *
127
+ * See docs/superpowers/specs/2026-05-13-plug-in-builder-entry-point-design.md §5.1.
128
+ */
129
+ ensureStage1And2(password: string): Promise<FleetBootstrapResult>;
130
+ /**
131
+ * Back-compat alias. Existing call sites in `client/src/cli/commands/bootstrap.ts`
132
+ * and `client/src/cli/commands/fleet-scale.ts` continue to call `bootstrap()`;
133
+ * forwarding to `ensureStage1And2` preserves their semantics without churn.
134
+ */
86
135
  bootstrap(password: string): Promise<FleetBootstrapResult>;
87
136
  /**
88
137
  * If the master is only slightly above the minimum, warn about gas runway (heuristic days).
@@ -90,6 +139,12 @@ export declare class FleetBootstrapper {
90
139
  private warnMasterEthRunway;
91
140
  private ensureMasterWallet;
92
141
  private loadExistingMnemonic;
142
+ /** Deterministic Safe predict from the HD-index-1 agent EOA. */
143
+ private stepFleetSafePredict;
144
+ /** Deploy the predicted fleet Safe. Funds the agent EOA from master if needed. */
145
+ private stepFleetSafeDeploy;
146
+ /** Mint the fleet agentId + bind Safe via setAgentWallet (ERC-1271). */
147
+ private stepFleetIdentityRegister;
93
148
  private bootstrapService;
94
149
  /**
95
150
  * Compare persisted per-service state to registry/staking/Safe bytecode and patch store
@@ -15,7 +15,7 @@ import { formatBootstrapOperatorMessage, isJinnDebug, } from '../operator-errors
15
15
  import { reconcileServiceAgainstChain, } from './reconcile.js';
16
16
  import { previousSafeBeingAbandoned, sweepOrphanedServiceFunds, } from './orphan-sweep.js';
17
17
  import { DEFAULT_FAUCET_LOOP_TIMEOUT_MS, computeFaucetDripCap, requestTestnetFunding, } from './faucet.js';
18
- import { flattenErrorMessage, viemSendTransactionWithRetry, waitForTransactionReceiptWithRetry, } from '../tx-retry.js';
18
+ import { flattenErrorMessage, sleep, viemSendTransactionWithRetry, waitForTransactionReceiptWithRetry, } from '../tx-retry.js';
19
19
  import { isUnauthorizedAccountError } from '../errors/unauthorized-account.js';
20
20
  import { createJinnPublicClient, createJinnWalletClient } from './viem-clients.js';
21
21
  import { isTransientEthReadError } from '../chain-read-errors.js';
@@ -29,6 +29,28 @@ const STANDARD_MASTER_BOOTSTRAP_MULTIPLIER = 2n;
29
29
  const DEFAULT_MASTER_ETH_DAILY_WEI = 1000000000000000n;
30
30
  /** Warn when ETH above the minimum would last fewer than this many days at the daily estimate. */
31
31
  const MASTER_ETH_RUNWAY_WARN_DAYS = 7n;
32
+ /**
33
+ * Safe → ERC-8004 agent NFT binding retry (jinn-mono-h74p).
34
+ *
35
+ * Empirical observation against fresh Base Sepolia 1/1 Safes: the first
36
+ * `IdentityRegistry.setAgentWallet` attempt reverts with a generic
37
+ * "Execution reverted for an unknown reason" — but the same Safe + same
38
+ * agentId + a freshly-signed message a few seconds later succeeds. The
39
+ * race window is likely freshly-deployed-Safe state lag on the public RPC
40
+ * (the simulator can't read the Safe's storage yet in the same block /
41
+ * eventual-consistency between sibling RPC nodes). A short bounded retry
42
+ * makes the operator-visible behaviour deterministic instead of relying on
43
+ * the "daemon exits → operator restarts → resume at safe_binding_pending"
44
+ * accidental safety net (which goes away when jinn-mono-vh74.2 removes the
45
+ * Claude-auth post-bootstrap exit gate).
46
+ *
47
+ * Defaults: 3 attempts × 3 s delay = at most ~6 s of in-process retry budget
48
+ * before falling through to the existing `safe_binding_pending` persisted
49
+ * state. Real (non-transient) failures still surface — just with a slightly
50
+ * higher latency tax for the diagnostic.
51
+ */
52
+ const DEFAULT_SAFE_BINDING_MAX_ATTEMPTS = 3;
53
+ const DEFAULT_SAFE_BINDING_RETRY_DELAY_MS = 3_000;
32
54
  export class FleetBootstrapper {
33
55
  store;
34
56
  config;
@@ -43,6 +65,8 @@ export class FleetBootstrapper {
43
65
  faucetLoopTimeoutMs;
44
66
  now;
45
67
  autoTestnetFaucet;
68
+ safeBindingMaxAttempts;
69
+ safeBindingRetryDelayMs;
46
70
  constructor(options = {}) {
47
71
  this.store = new FleetStateStore(options.earningDir);
48
72
  this.chain = options.chain ?? 'base';
@@ -55,6 +79,10 @@ export class FleetBootstrapper {
55
79
  this.now = options.now ?? Date.now;
56
80
  this.autoTestnetFaucet =
57
81
  options.autoTestnetFaucet ?? this.env['JINN_DISABLE_TESTNET_FAUCET'] !== '1';
82
+ this.safeBindingMaxAttempts =
83
+ options.safeBindingMaxAttempts ?? DEFAULT_SAFE_BINDING_MAX_ATTEMPTS;
84
+ this.safeBindingRetryDelayMs =
85
+ options.safeBindingRetryDelayMs ?? DEFAULT_SAFE_BINDING_RETRY_DELAY_MS;
58
86
  const dailyOpt = options.masterEthDailyEstimateWei;
59
87
  this.masterEthDailyEstimateWei =
60
88
  dailyOpt !== undefined
@@ -112,16 +140,145 @@ export class FleetBootstrapper {
112
140
  const mnemonic = await this.loadExistingMnemonic(state, password);
113
141
  return this.stepRegisterAgent(state, mnemonic, serviceIndex);
114
142
  }
115
- async bootstrap(password) {
116
- // Handle legacy keystore migration
143
+ /**
144
+ * Stage 1 Identity (universal). Walks: wallet → predict Safe (from
145
+ * HD-index-1 agent EOA) → ETH funding gate → deploy Safe → mint agentId
146
+ * + setAgentWallet via ERC-1271. Idempotent and re-entrant. Does NOT
147
+ * touch service rows or staking — those belong to Stage 2.
148
+ *
149
+ * Fleet-level fields written:
150
+ * - fleet_safe_address (after predict)
151
+ * - fleet_agent_id, fleet_identity_registry, fleet_stage='stage1'
152
+ * (after mint + bind)
153
+ *
154
+ * Funding gate: requires ETH on the master EOA only (no OLAS). On testnet,
155
+ * the existing CDP faucet loop drains as usual when `autoTestnetFaucet`
156
+ * is enabled.
157
+ *
158
+ * See docs/superpowers/specs/2026-05-13-plug-in-builder-entry-point-design.md §5.1.
159
+ */
160
+ async ensureStage1(password) {
161
+ // Legacy keystore migration (same as bootstrap()).
117
162
  if (!this.store.hasMnemonicKeystore() && this.store.hasLegacyKeystore()) {
118
163
  await this.store.migrateLegacyFiles();
119
164
  }
120
165
  let state = await this.store.load(this.chain);
166
+ // Short-circuit if Stage 1 is already complete (or beyond).
167
+ if (state.fleet_stage === 'stage1' || state.fleet_stage === 'stage1_and_2') {
168
+ // Even when stage marker says complete, fleet identity may be empty for
169
+ // pre-j07 operators (`stage1_and_2` is set by the migration for
170
+ // services-complete-but-no-agent_id operators). In that case we leave
171
+ // Stage 1 alone — the legacy backfill in main.ts handles those rows
172
+ // and a future ensureStage1 call after backfill will promote.
173
+ return {
174
+ ok: true,
175
+ fleet_state: state,
176
+ message: state.fleet_agent_id !== null
177
+ ? `Stage 1 already complete (fleet_agent_id=${state.fleet_agent_id}, fleet_safe=${state.fleet_safe_address}).`
178
+ : 'Stage 1 marker present but fleet identity is empty (legacy operator). Skipping.',
179
+ };
180
+ }
121
181
  try {
122
- // Phase 1: Master wallet setup
123
182
  state = await this.ensureMasterWallet(state, password);
124
- // Phase 1b: Check master funding
183
+ // Stage 1 funding gate — ETH only (no OLAS). Self-bond Stage 1 needs:
184
+ // master ETH for the agent-funding transfer + agent ETH for Safe deploy
185
+ // + Safe deploy gas + ERC-8004 register + setAgentWallet (two agent EOA
186
+ // txs through the IdentityRegistry contract). 0.005 ETH is the
187
+ // configured `minEoaGasEth` floor; bump by 2x for safety.
188
+ const requiredMasterEth = this.config.minEoaGasEth * STANDARD_MASTER_BOOTSTRAP_MULTIPLIER;
189
+ const masterAddress = state.master_address;
190
+ const masterBalance = await this.publicClient.getBalance({
191
+ address: masterAddress,
192
+ });
193
+ if (masterBalance < requiredMasterEth) {
194
+ const shortfall = requiredMasterEth - masterBalance;
195
+ return {
196
+ ok: false,
197
+ fleet_state: state,
198
+ message: `Your master wallet needs more ETH (currently ${formatEther(masterBalance)} ETH, need ${formatEther(shortfall)} ETH more) to complete Stage 1. Please send ETH to: ${masterAddress}`,
199
+ funding: {
200
+ master_address: masterAddress,
201
+ eth_required: shortfall.toString(),
202
+ eth_balance: masterBalance.toString(),
203
+ },
204
+ };
205
+ }
206
+ const mnemonic = await this.loadExistingMnemonic(state, password);
207
+ // Step 1: predict fleet Safe from HD-index-1 agent EOA.
208
+ if (!state.fleet_safe_address) {
209
+ state = await this.stepFleetSafePredict(state, mnemonic);
210
+ }
211
+ // Step 2: deploy fleet Safe if bytecode absent.
212
+ const safeCode = await this.publicClient.getCode({
213
+ address: getAddress(state.fleet_safe_address),
214
+ });
215
+ if (safeCode === undefined || safeCode === '0x') {
216
+ state = await this.stepFleetSafeDeploy(state, mnemonic);
217
+ }
218
+ // Step 3: mint agentId + bind Safe via setAgentWallet.
219
+ if (!state.fleet_agent_id) {
220
+ state = await this.stepFleetIdentityRegister(state, mnemonic);
221
+ }
222
+ else if (state.fleet_stage !== 'stage1' && state.fleet_stage !== 'stage1_and_2') {
223
+ // Identity was minted but stage marker is stale; advance it.
224
+ state = await this.store.patchFleet({ fleet_stage: 'stage1' });
225
+ }
226
+ return {
227
+ ok: true,
228
+ fleet_state: state,
229
+ message: `Stage 1 complete. fleet_agent_id=${state.fleet_agent_id}, fleet_safe=${state.fleet_safe_address}.`,
230
+ };
231
+ }
232
+ catch (error) {
233
+ const { summary, hint, rawMessage } = formatBootstrapOperatorMessage(error);
234
+ const userMessage = hint !== undefined ? `${summary}\nHint: ${hint}` : summary;
235
+ if (this.debug) {
236
+ console.error(`[fleet-bootstrap] ensureStage1 failed:`, error);
237
+ }
238
+ else {
239
+ console.error(`[fleet-bootstrap] ${summary}`);
240
+ if (hint !== undefined)
241
+ console.error(`Hint: ${hint}`);
242
+ if (rawMessage && rawMessage !== summary) {
243
+ console.error(`[fleet-bootstrap] raw: ${rawMessage.split('\n')[0]}`);
244
+ }
245
+ }
246
+ return {
247
+ ok: false,
248
+ fleet_state: state,
249
+ message: userMessage,
250
+ rawErrorMessage: rawMessage,
251
+ };
252
+ }
253
+ }
254
+ /**
255
+ * Stage 1 + Stage 2 — full operator bootstrap. Calls `ensureStage1`
256
+ * first; on success, walks Stage 2 per service. Builder-only users who
257
+ * have completed Stage 1 and call this method later begin Stage 2 from
258
+ * `awaiting_stake` for the first service row (created lazily here).
259
+ *
260
+ * Two-Safe topology in standard mode: `fleet_safe_address !==
261
+ * services[0].safe_address` because Stage 2's `distributor.stake()`
262
+ * creates its own Safe. In self-bond mode the two converge (both
263
+ * derived from HD-index-1).
264
+ *
265
+ * See docs/superpowers/specs/2026-05-13-plug-in-builder-entry-point-design.md §5.1.
266
+ */
267
+ async ensureStage1And2(password) {
268
+ // Stage 1 first — establishes fleet identity. Short-circuits if already done.
269
+ const stage1Result = await this.ensureStage1(password);
270
+ if (!stage1Result.ok) {
271
+ return stage1Result;
272
+ }
273
+ // Original bootstrap body — copied verbatim from the previous bootstrap()
274
+ // method, with two changes:
275
+ // (a) the legacy-keystore migration and master-wallet-ensure are no-ops
276
+ // because ensureStage1 already ran them.
277
+ // (b) at the end, if any service reached `complete`/`safe_binding_pending`
278
+ // we advance `fleet_stage` to `'stage1_and_2'`.
279
+ let state = stage1Result.fleet_state;
280
+ try {
281
+ // Phase 1b: Check master funding for the full operator path.
125
282
  const masterAddress = state.master_address;
126
283
  let masterBalance = await this.publicClient.getBalance({ address: masterAddress });
127
284
  // Self-bond mode needs much more ETH than standard mode because the master
@@ -291,6 +448,11 @@ export class FleetBootstrapper {
291
448
  const nextIndex = nextFleetServiceIndex(state.services);
292
449
  state = await this.bootstrapService(state, mnemonic, nextIndex);
293
450
  }
451
+ // Advance fleet_stage to 'stage1_and_2' if any service is operational.
452
+ const anyOperationalAfter = state.services.some(s => isOperationalServiceStep(s.step));
453
+ if (anyOperationalAfter && state.fleet_stage !== 'stage1_and_2') {
454
+ state = await this.store.patchFleet({ fleet_stage: 'stage1_and_2' });
455
+ }
294
456
  return {
295
457
  ok: true,
296
458
  fleet_state: state,
@@ -322,6 +484,14 @@ export class FleetBootstrapper {
322
484
  };
323
485
  }
324
486
  }
487
+ /**
488
+ * Back-compat alias. Existing call sites in `client/src/cli/commands/bootstrap.ts`
489
+ * and `client/src/cli/commands/fleet-scale.ts` continue to call `bootstrap()`;
490
+ * forwarding to `ensureStage1And2` preserves their semantics without churn.
491
+ */
492
+ async bootstrap(password) {
493
+ return this.ensureStage1And2(password);
494
+ }
325
495
  /**
326
496
  * If the master is only slightly above the minimum, warn about gas runway (heuristic days).
327
497
  */
@@ -382,6 +552,128 @@ export class FleetBootstrapper {
382
552
  return freshMnemonic;
383
553
  }
384
554
  }
555
+ // ── Stage 1: fleet-level identity steps (nghf) ────────────────────────
556
+ /** Deterministic Safe predict from the HD-index-1 agent EOA. */
557
+ async stepFleetSafePredict(state, mnemonic) {
558
+ const agentAddress = deriveAgentAddress(mnemonic, 1);
559
+ const agentKey = walletPrivateKeyAtIndex(mnemonic, 1);
560
+ console.error(`[fleet-bootstrap] Stage 1: predicting fleet Safe (owner=${agentAddress})`);
561
+ const { address } = await initPredictedSafe({
562
+ rpcUrl: this.config.rpcUrl,
563
+ signerKey: agentKey,
564
+ owners: [agentAddress],
565
+ threshold: 1,
566
+ });
567
+ void state;
568
+ return this.store.patchFleet({ fleet_safe_address: getAddress(address) });
569
+ }
570
+ /** Deploy the predicted fleet Safe. Funds the agent EOA from master if needed. */
571
+ async stepFleetSafeDeploy(state, mnemonic) {
572
+ const agentAddress = deriveAgentAddress(mnemonic, 1);
573
+ const agentKey = walletPrivateKeyAtIndex(mnemonic, 1);
574
+ const agentSigner = deriveAgentSigner(mnemonic, 1);
575
+ const fleetSafe = state.fleet_safe_address;
576
+ // Fund agent EOA so it can pay for Safe deploy + setAgentWallet gas.
577
+ // 0.01 ETH covers Safe deploy (~250k gas) + register (~80k) + setAgentWallet
578
+ // (~200k) at testnet gas prices comfortably.
579
+ const STAGE1_AGENT_ETH = 10000000000000000n; // 0.01 ETH
580
+ const masterAccount = deriveMasterSigner(mnemonic);
581
+ const masterWallet = createJinnWalletClient(this.config.rpcUrl, this.chain, masterAccount);
582
+ const agentBalance = await this.publicClient.getBalance({
583
+ address: getAddress(agentAddress),
584
+ });
585
+ if (agentBalance < STAGE1_AGENT_ETH) {
586
+ const fundAmount = STAGE1_AGENT_ETH - agentBalance;
587
+ console.error(`[fleet-bootstrap] Stage 1: funding fleet agent EOA with ${fundAmount} wei from master`);
588
+ const fundHash = await viemSendTransactionWithRetry(masterWallet, this.publicClient, {
589
+ account: masterAccount,
590
+ to: addr(agentAddress),
591
+ value: fundAmount,
592
+ });
593
+ await waitForTransactionReceiptWithRetry(this.publicClient, fundHash);
594
+ }
595
+ console.error(`[fleet-bootstrap] Stage 1: deploying fleet Safe at ${fleetSafe}`);
596
+ const { safe } = await initPredictedSafe({
597
+ rpcUrl: this.config.rpcUrl,
598
+ signerKey: agentKey,
599
+ owners: [agentAddress],
600
+ threshold: 1,
601
+ });
602
+ const deployTx = await safe.createSafeDeploymentTransaction();
603
+ const agentWallet = createJinnWalletClient(this.config.rpcUrl, this.chain, agentSigner);
604
+ const deployHash = await viemSendTransactionWithRetry(agentWallet, this.publicClient, {
605
+ account: agentSigner,
606
+ to: deployTx.to,
607
+ value: BigInt(deployTx.value),
608
+ data: deployTx.data,
609
+ });
610
+ const receipt = await waitForTransactionReceiptWithRetry(this.publicClient, deployHash);
611
+ if (receipt.status !== 'success') {
612
+ throw new Error(`Fleet Safe deployment tx failed: ${deployHash}`);
613
+ }
614
+ const deployedCode = await this.publicClient.getCode({
615
+ address: getAddress(fleetSafe),
616
+ });
617
+ if (deployedCode === undefined || deployedCode === '0x') {
618
+ throw new Error(`Fleet Safe deployment succeeded but no code at ${fleetSafe}`);
619
+ }
620
+ console.error(`[fleet-bootstrap] Stage 1: fleet Safe deployed (tx=${deployHash})`);
621
+ return this.store.load(this.chain);
622
+ }
623
+ /** Mint the fleet agentId + bind Safe via setAgentWallet (ERC-1271). */
624
+ async stepFleetIdentityRegister(state, mnemonic) {
625
+ const identityRegistry = this.config.identityRegistry ?? IDENTITY_REGISTRY_ADDRESSES[this.config.chainId];
626
+ if (!identityRegistry) {
627
+ throw new Error(`IdentityRegistry address not configured for chainId=${this.config.chainId}.`);
628
+ }
629
+ const fleetSafe = state.fleet_safe_address;
630
+ const agentSigner = deriveAgentSigner(mnemonic, 1);
631
+ const agentWallet = createJinnWalletClient(this.config.rpcUrl, this.chain, agentSigner);
632
+ // Mint agentId — empty agent URI for v0 (matches stepRegisterAgent §6.1 in spec).
633
+ const registerData = encodeFunctionData({
634
+ abi: IDENTITY_REGISTRY_ABI,
635
+ functionName: 'register',
636
+ args: [''],
637
+ });
638
+ console.error(`[fleet-bootstrap] Stage 1: minting fleet agentId ` +
639
+ `(IdentityRegistry=${identityRegistry}, agentEOA=${agentSigner.address})`);
640
+ const mintTxHash = await viemSendTransactionWithRetry(agentWallet, this.publicClient, {
641
+ account: agentSigner,
642
+ to: addr(identityRegistry),
643
+ data: registerData,
644
+ });
645
+ const mintReceipt = await waitForTransactionReceiptWithRetry(this.publicClient, mintTxHash);
646
+ if (mintReceipt.status !== 'success') {
647
+ throw new Error(`Fleet IdentityRegistry.register() failed: ${mintTxHash}`);
648
+ }
649
+ const fleetAgentId = this.parseAgentIdFromReceipt(mintReceipt, identityRegistry);
650
+ if (fleetAgentId === null) {
651
+ throw new Error(`Fleet IdentityRegistry.register() succeeded but Registered event missing (tx=${mintTxHash})`);
652
+ }
653
+ // Persist agentId IMMEDIATELY so a crash between mint and bind doesn't lose it.
654
+ await this.store.patchFleet({
655
+ fleet_agent_id: fleetAgentId,
656
+ fleet_identity_registry: getAddress(identityRegistry),
657
+ });
658
+ // Bind the Safe via setAgentWallet (ERC-1271).
659
+ console.error(`[fleet-bootstrap] Stage 1: binding fleet Safe ${fleetSafe} to agentId=${fleetAgentId}`);
660
+ const bindResult = await bindAgentWalletToSafe({
661
+ identityRegistryAddress: addr(identityRegistry),
662
+ agentId: BigInt(fleetAgentId),
663
+ safeAddress: addr(fleetSafe),
664
+ agentEoaAccount: agentSigner,
665
+ agentEoaWalletClient: agentWallet,
666
+ publicClient: this.publicClient,
667
+ chainId: this.config.chainId,
668
+ });
669
+ if (!bindResult.ok) {
670
+ const bindErr = bindResult.error;
671
+ throw new Error(`Fleet setAgentWallet failed: ${bindErr.shortMessage}` +
672
+ (bindErr.revertReason ? ` (revert: ${bindErr.revertReason})` : ''));
673
+ }
674
+ console.error(`[fleet-bootstrap] Stage 1: setAgentWallet succeeded (tx=${bindResult.txHash})`);
675
+ return this.store.patchFleet({ fleet_stage: 'stage1' });
676
+ }
385
677
  // ── Phase 2: Per-service bootstrap ───────────────────────────────────
386
678
  async bootstrapService(state, mnemonic, index) {
387
679
  const agentAddress = deriveAgentAddress(mnemonic, index);
@@ -837,6 +1129,7 @@ export class FleetBootstrapper {
837
1129
  let svc = (await this.store.load(this.chain)).services.find(s => s.index === index);
838
1130
  if (!svc)
839
1131
  throw new Error(`Service ${index} not found in state`);
1132
+ const fleetSnapshot = await this.store.load(this.chain);
840
1133
  const identityRegistry = this.config.identityRegistry
841
1134
  ?? IDENTITY_REGISTRY_ADDRESSES[this.config.chainId];
842
1135
  if (!identityRegistry) {
@@ -845,7 +1138,7 @@ export class FleetBootstrapper {
845
1138
  }
846
1139
  const agentSigner = deriveAgentSigner(mnemonic, index);
847
1140
  const agentWallet = createJinnWalletClient(this.config.rpcUrl, this.chain, agentSigner);
848
- // ── Sub-step A: mint NFT (skip if agent_id is already set). ─────────
1141
+ // ── Sub-step A: mint NFT (skip if agent_id is already set OR fleet identity exists).
849
1142
  let agentId;
850
1143
  if (svc.agent_id) {
851
1144
  console.error(`[fleet-bootstrap] Service ${index}: ERC-8004 agent already registered ` +
@@ -856,6 +1149,22 @@ export class FleetBootstrapper {
856
1149
  step: svc.step === 'safe_binding_pending' ? 'safe_binding_pending' : 'agent_registered',
857
1150
  });
858
1151
  }
1152
+ else if (fleetSnapshot.fleet_agent_id) {
1153
+ // nghf: reuse the fleet-level agentId minted by ensureStage1 instead of
1154
+ // minting a second one. This collapses the "one agentId per user"
1155
+ // invariant in spec §5.1 for the standard-mode two-Safe topology.
1156
+ console.error(`[fleet-bootstrap] Service ${index}: reusing fleet agentId=${fleetSnapshot.fleet_agent_id} ` +
1157
+ `(no second mint needed).`);
1158
+ agentId = fleetSnapshot.fleet_agent_id;
1159
+ svc = await this.firstServiceUpdate(index, {
1160
+ agent_id: fleetSnapshot.fleet_agent_id,
1161
+ agent_uri: '',
1162
+ identity_registry_address: fleetSnapshot.fleet_identity_registry ?? getAddress(identityRegistry),
1163
+ agent_registered_tx: null,
1164
+ step: 'agent_registered',
1165
+ error: null,
1166
+ });
1167
+ }
859
1168
  else {
860
1169
  // v0: empty agentURI. The richer agent card (per §6 of the spec) is
861
1170
  // future work — operators may later call `setAgentURI`.
@@ -924,32 +1233,79 @@ export class FleetBootstrapper {
924
1233
  step: 'safe_binding_pending',
925
1234
  error: null,
926
1235
  });
927
- try {
928
- const result = await bindAgentWalletToSafe({
929
- identityRegistryAddress: addr(identityRegistry),
930
- agentId: BigInt(agentId),
931
- safeAddress: addr(safeAddress),
932
- agentEoaAccount: agentSigner,
933
- agentEoaWalletClient: agentWallet,
934
- publicClient: this.publicClient,
935
- chainId: this.config.chainId,
936
- });
1236
+ // Combined h74p (retry-on-transient-throw) + hjex.4 (Result-typed
1237
+ // structured errors) policy:
1238
+ // - bindAgentWalletToSafe now returns a BindAgentWalletOutcome
1239
+ // (ok=true | ok=false with structured SafeBindingError).
1240
+ // - A returned Result.ok=false is a deterministic contract revert —
1241
+ // don't retry; record the structured diagnostic.
1242
+ // - A *thrown* exception is the freshly-deployed-Safe RPC race
1243
+ // window h74p targets — retry up to safeBindingMaxAttempts with a
1244
+ // small delay; if every attempt throws we fall through to a plain
1245
+ // reason log (no structured fields available).
1246
+ const maxAttempts = Math.max(1, this.safeBindingMaxAttempts);
1247
+ let bindResult;
1248
+ let lastBindError;
1249
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
1250
+ try {
1251
+ bindResult = await bindAgentWalletToSafe({
1252
+ identityRegistryAddress: addr(identityRegistry),
1253
+ agentId: BigInt(agentId),
1254
+ safeAddress: addr(safeAddress),
1255
+ agentEoaAccount: agentSigner,
1256
+ agentEoaWalletClient: agentWallet,
1257
+ publicClient: this.publicClient,
1258
+ chainId: this.config.chainId,
1259
+ });
1260
+ break;
1261
+ }
1262
+ catch (err) {
1263
+ lastBindError = err;
1264
+ if (attempt < maxAttempts) {
1265
+ const reason = err instanceof Error ? err.message : String(err);
1266
+ console.error(`[fleet-bootstrap] Service ${index}: setAgentWallet attempt ` +
1267
+ `${attempt}/${maxAttempts} failed (${reason}); retrying in ` +
1268
+ `${this.safeBindingRetryDelayMs}ms...`);
1269
+ if (this.safeBindingRetryDelayMs > 0) {
1270
+ await sleep(this.safeBindingRetryDelayMs);
1271
+ }
1272
+ }
1273
+ }
1274
+ }
1275
+ if (bindResult?.ok === true) {
937
1276
  console.error(`[fleet-bootstrap] Service ${index}: setAgentWallet succeeded ` +
938
- `(tx=${result.txHash}, safe=${safeAddress}).`);
1277
+ `(tx=${bindResult.txHash}, safe=${safeAddress}).`);
939
1278
  svc = await this.firstServiceUpdate(index, {
940
1279
  safe_bound_to_agent: true,
941
1280
  step: 'complete',
942
1281
  error: null,
1282
+ error_revert_reason: null,
1283
+ error_short_message: null,
943
1284
  });
944
1285
  }
945
- catch (err) {
946
- const reason = err instanceof Error ? err.message : String(err);
1286
+ else if (bindResult && !bindResult.ok) {
1287
+ const bindErr = bindResult.error;
947
1288
  console.error(`[fleet-bootstrap] Service ${index}: setAgentWallet failed; continuing with ` +
948
- `safe_bound_to_agent=false (${reason}).`);
1289
+ `safe_bound_to_agent=false (${bindErr.shortMessage}` +
1290
+ `${bindErr.revertReason ? `, revert: ${bindErr.revertReason}` : ''}).`);
1291
+ svc = await this.firstServiceUpdate(index, {
1292
+ safe_bound_to_agent: false,
1293
+ step: 'safe_binding_pending',
1294
+ error: `safe_binding_failed: ${bindErr.shortMessage}`,
1295
+ error_revert_reason: bindErr.revertReason,
1296
+ error_short_message: bindErr.shortMessage,
1297
+ });
1298
+ }
1299
+ else {
1300
+ const reason = lastBindError instanceof Error ? lastBindError.message : String(lastBindError);
1301
+ console.error(`[fleet-bootstrap] Service ${index}: setAgentWallet failed after ` +
1302
+ `${maxAttempts} attempts; continuing with safe_bound_to_agent=false (${reason}).`);
949
1303
  svc = await this.firstServiceUpdate(index, {
950
1304
  safe_bound_to_agent: false,
951
1305
  step: 'safe_binding_pending',
952
1306
  error: `safe_binding_failed: ${reason}`,
1307
+ error_revert_reason: null,
1308
+ error_short_message: null,
953
1309
  });
954
1310
  }
955
1311
  }