@jinn-network/client 0.1.5 → 0.1.6-canary.118cd4d0

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 (343) 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 +14 -1
  11. package/dist/api/bootstrap-endpoint.js.map +1 -1
  12. package/dist/api/discovery-endpoint.d.ts +31 -0
  13. package/dist/api/discovery-endpoint.js +78 -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/gather-status.js +20 -3
  19. package/dist/api/gather-status.js.map +1 -1
  20. package/dist/api/harness-readiness-endpoint.d.ts +25 -0
  21. package/dist/api/harness-readiness-endpoint.js +24 -0
  22. package/dist/api/harness-readiness-endpoint.js.map +1 -0
  23. package/dist/api/hermes-doctor-endpoint.d.ts +26 -0
  24. package/dist/api/hermes-doctor-endpoint.js +29 -0
  25. package/dist/api/hermes-doctor-endpoint.js.map +1 -0
  26. package/dist/api/server.d.ts +43 -0
  27. package/dist/api/server.js +39 -0
  28. package/dist/api/server.js.map +1 -1
  29. package/dist/api/setup-endpoints.d.ts +5 -0
  30. package/dist/api/setup-endpoints.js +24 -5
  31. package/dist/api/setup-endpoints.js.map +1 -1
  32. package/dist/build-info.json +4 -4
  33. package/dist/build-meta.json +1 -1
  34. package/dist/cli/commands/auth.js +3 -1
  35. package/dist/cli/commands/auth.js.map +1 -1
  36. package/dist/cli/commands/create.d.ts +5 -3
  37. package/dist/cli/commands/create.js +101 -36
  38. package/dist/cli/commands/create.js.map +1 -1
  39. package/dist/cli/commands/solver-nets.d.ts +19 -0
  40. package/dist/cli/commands/solver-nets.js +140 -2
  41. package/dist/cli/commands/solver-nets.js.map +1 -1
  42. package/dist/cli/commands/solver-plugins-publish.d.ts +31 -0
  43. package/dist/cli/commands/solver-plugins-publish.js +169 -0
  44. package/dist/cli/commands/solver-plugins-publish.js.map +1 -0
  45. package/dist/cli/commands/solver-plugins-revoke.d.ts +15 -0
  46. package/dist/cli/commands/solver-plugins-revoke.js +91 -0
  47. package/dist/cli/commands/solver-plugins-revoke.js.map +1 -0
  48. package/dist/cli/commands/solver-plugins.d.ts +50 -6
  49. package/dist/cli/commands/solver-plugins.js +205 -68
  50. package/dist/cli/commands/solver-plugins.js.map +1 -1
  51. package/dist/config.d.ts +27 -0
  52. package/dist/config.js +30 -2
  53. package/dist/config.js.map +1 -1
  54. package/dist/conformance/checks/hash-signature.js +6 -2
  55. package/dist/conformance/checks/hash-signature.js.map +1 -1
  56. package/dist/conformance/checks/payload.js +4 -2
  57. package/dist/conformance/checks/payload.js.map +1 -1
  58. package/dist/conformance/checks/verdict.d.ts +10 -10
  59. package/dist/conformance/checks/verdict.js +16 -15
  60. package/dist/conformance/checks/verdict.js.map +1 -1
  61. package/dist/conformance/harness.d.ts +1 -1
  62. package/dist/conformance/harness.js +16 -9
  63. package/dist/conformance/harness.js.map +1 -1
  64. package/dist/conformance/types.d.ts +10 -3
  65. package/dist/conformance/types.js.map +1 -1
  66. package/dist/corpus/acquire.d.ts +1 -3
  67. package/dist/corpus/acquire.js.map +1 -1
  68. package/dist/corpus/envelope-projection.d.ts +1 -1
  69. package/dist/corpus/envelope-projection.js +14 -7
  70. package/dist/corpus/envelope-projection.js.map +1 -1
  71. package/dist/corpus/index.d.ts +2 -1
  72. package/dist/corpus/index.js.map +1 -1
  73. package/dist/corpus/prediction-brier-scoreboard-report.js +1 -1
  74. package/dist/corpus/prediction-brier-scoreboard-report.js.map +1 -1
  75. package/dist/corpus/prediction-brier-scoreboard.js +3 -1
  76. package/dist/corpus/prediction-brier-scoreboard.js.map +1 -1
  77. package/dist/corpus/types.d.ts +2 -2
  78. package/dist/daemon/daemon.d.ts +17 -1
  79. package/dist/daemon/daemon.js +15 -0
  80. package/dist/daemon/daemon.js.map +1 -1
  81. package/dist/daemon/freeze-fence.js +6 -3
  82. package/dist/daemon/freeze-fence.js.map +1 -1
  83. package/dist/daemon/readiness-gate.d.ts +30 -0
  84. package/dist/daemon/readiness-gate.js +31 -0
  85. package/dist/daemon/readiness-gate.js.map +1 -0
  86. package/dist/dashboard/assets/{index-D_NMfDfV.css → index-DOlzFN8a.css} +1 -1
  87. package/dist/dashboard/assets/index-NkZ7CTAT.js +140 -0
  88. package/dist/dashboard/index.html +2 -2
  89. package/dist/discovery/http.js +121 -0
  90. package/dist/discovery/http.js.map +1 -1
  91. package/dist/discovery/onchain.js +11 -0
  92. package/dist/discovery/onchain.js.map +1 -1
  93. package/dist/discovery/types.d.ts +112 -0
  94. package/dist/discovery/types.js.map +1 -1
  95. package/dist/discovery/with-fallback.js +9 -0
  96. package/dist/discovery/with-fallback.js.map +1 -1
  97. package/dist/earning/agent-wallet-binding.d.ts +20 -1
  98. package/dist/earning/agent-wallet-binding.js +54 -16
  99. package/dist/earning/agent-wallet-binding.js.map +1 -1
  100. package/dist/earning/bootstrap.d.ts +119 -0
  101. package/dist/earning/bootstrap.js +482 -16
  102. package/dist/earning/bootstrap.js.map +1 -1
  103. package/dist/earning/contracts.js +9 -1
  104. package/dist/earning/contracts.js.map +1 -1
  105. package/dist/earning/funding-plan.js +15 -2
  106. package/dist/earning/funding-plan.js.map +1 -1
  107. package/dist/earning/store.js +48 -1
  108. package/dist/earning/store.js.map +1 -1
  109. package/dist/earning/types.d.ts +30 -0
  110. package/dist/earning/types.js +37 -0
  111. package/dist/earning/types.js.map +1 -1
  112. package/dist/erc8004/abis.d.ts +64 -0
  113. package/dist/erc8004/abis.js +48 -0
  114. package/dist/erc8004/abis.js.map +1 -1
  115. package/dist/erc8004/plugin-registry.d.ts +102 -0
  116. package/dist/erc8004/plugin-registry.js +165 -0
  117. package/dist/erc8004/plugin-registry.js.map +1 -0
  118. package/dist/events/types.d.ts +2 -2
  119. package/dist/harnesses/engine/engine.js +15 -3
  120. package/dist/harnesses/engine/engine.js.map +1 -1
  121. package/dist/harnesses/engine/envelope-assembly.d.ts +2 -2
  122. package/dist/harnesses/engine/envelope-assembly.js +4 -2
  123. package/dist/harnesses/engine/envelope-assembly.js.map +1 -1
  124. package/dist/harnesses/freeze.d.ts +4 -1
  125. package/dist/harnesses/freeze.js +12 -2
  126. package/dist/harnesses/freeze.js.map +1 -1
  127. package/dist/harnesses/impls/claude-mcp-prediction/index.d.ts +4 -1
  128. package/dist/harnesses/impls/claude-mcp-prediction/index.js +7 -2
  129. package/dist/harnesses/impls/claude-mcp-prediction/index.js.map +1 -1
  130. package/dist/harnesses/impls/claude-mcp-prediction-apy/index.d.ts +4 -1
  131. package/dist/harnesses/impls/claude-mcp-prediction-apy/index.js +7 -2
  132. package/dist/harnesses/impls/claude-mcp-prediction-apy/index.js.map +1 -1
  133. package/dist/harnesses/impls/evaluation-context.d.ts +15 -4
  134. package/dist/harnesses/impls/evaluation-context.js +24 -8
  135. package/dist/harnesses/impls/evaluation-context.js.map +1 -1
  136. package/dist/harnesses/impls/hermes-agent/adapter.d.ts +34 -0
  137. package/dist/harnesses/impls/hermes-agent/adapter.js +205 -0
  138. package/dist/harnesses/impls/hermes-agent/adapter.js.map +1 -0
  139. package/dist/harnesses/impls/hermes-agent/bootstrap.d.ts +18 -0
  140. package/dist/harnesses/impls/hermes-agent/bootstrap.js +231 -0
  141. package/dist/harnesses/impls/hermes-agent/bootstrap.js.map +1 -0
  142. package/dist/harnesses/impls/hermes-agent/config-builder.d.ts +49 -0
  143. package/dist/harnesses/impls/hermes-agent/config-builder.js +104 -0
  144. package/dist/harnesses/impls/hermes-agent/config-builder.js.map +1 -0
  145. package/dist/harnesses/impls/hermes-agent/harness.d.ts +30 -0
  146. package/dist/harnesses/impls/hermes-agent/harness.js +52 -0
  147. package/dist/harnesses/impls/hermes-agent/harness.js.map +1 -0
  148. package/dist/harnesses/impls/hermes-agent/index.d.ts +5 -0
  149. package/dist/harnesses/impls/hermes-agent/index.js +7 -0
  150. package/dist/harnesses/impls/hermes-agent/index.js.map +1 -0
  151. package/dist/harnesses/impls/hermes-agent/prompt.d.ts +15 -0
  152. package/dist/harnesses/impls/hermes-agent/prompt.js +37 -0
  153. package/dist/harnesses/impls/hermes-agent/prompt.js.map +1 -0
  154. package/dist/harnesses/impls/index.d.ts +6 -0
  155. package/dist/harnesses/impls/index.js +17 -4
  156. package/dist/harnesses/impls/index.js.map +1 -1
  157. package/dist/harnesses/impls/learner/adapters/claude-code.js.map +1 -0
  158. package/dist/harnesses/impls/{claude-code-learner → learner}/adapters/codex-code.js +13 -34
  159. package/dist/harnesses/impls/learner/adapters/codex-code.js.map +1 -0
  160. package/dist/harnesses/impls/learner/adapters/codex-workspace.js.map +1 -0
  161. package/dist/harnesses/impls/{claude-code-learner → learner}/harness.d.ts +9 -3
  162. package/dist/harnesses/impls/{claude-code-learner → learner}/harness.js +24 -1
  163. package/dist/harnesses/impls/learner/harness.js.map +1 -0
  164. package/dist/harnesses/impls/{claude-code-learner → learner}/harvest.js +15 -3
  165. package/dist/harnesses/impls/learner/harvest.js.map +1 -0
  166. package/dist/harnesses/impls/{claude-code-learner → learner}/index.d.ts +5 -5
  167. package/dist/harnesses/impls/{claude-code-learner → learner}/index.js +4 -4
  168. package/dist/harnesses/impls/learner/index.js.map +1 -0
  169. package/dist/harnesses/impls/{claude-code-learner → learner}/plugin-path.d.ts +4 -4
  170. package/dist/harnesses/impls/{claude-code-learner → learner}/plugin-path.js +7 -7
  171. package/dist/harnesses/impls/learner/plugin-path.js.map +1 -0
  172. package/dist/harnesses/impls/{claude-code-learner → learner}/restoration-patch.js +3 -1
  173. package/dist/harnesses/impls/learner/restoration-patch.js.map +1 -0
  174. package/dist/harnesses/impls/learner/test-utils/fake-plugin-outputs.js.map +1 -0
  175. package/dist/harnesses/impls/learner/test-utils/noop-adapter.js.map +1 -0
  176. package/dist/harnesses/impls/{claude-code-learner → learner}/types.d.ts +12 -2
  177. package/dist/harnesses/impls/learner/types.js.map +1 -0
  178. package/dist/harnesses/impls/portfolio-v0-evaluator/index.js +13 -12
  179. package/dist/harnesses/impls/portfolio-v0-evaluator/index.js.map +1 -1
  180. package/dist/harnesses/impls/prediction-apy-v0-evaluator/index.js +7 -7
  181. package/dist/harnesses/impls/prediction-apy-v0-evaluator/index.js.map +1 -1
  182. package/dist/harnesses/impls/prediction-apy-v0-evaluator/parse-submission.d.ts +3 -3
  183. package/dist/harnesses/impls/prediction-apy-v0-evaluator/parse-submission.js +7 -6
  184. package/dist/harnesses/impls/prediction-apy-v0-evaluator/parse-submission.js.map +1 -1
  185. package/dist/harnesses/impls/prediction-v0-evaluator/checks/integrity.js +1 -1
  186. package/dist/harnesses/impls/prediction-v0-evaluator/checks/integrity.js.map +1 -1
  187. package/dist/harnesses/impls/prediction-v0-evaluator/index.js +11 -10
  188. package/dist/harnesses/impls/prediction-v0-evaluator/index.js.map +1 -1
  189. package/dist/harnesses/impls/prediction-v1-evaluator/index.js +11 -10
  190. package/dist/harnesses/impls/prediction-v1-evaluator/index.js.map +1 -1
  191. package/dist/harnesses/impls/swe-rebench-v2-evaluator/eval-runner.d.ts +1 -0
  192. package/dist/harnesses/impls/swe-rebench-v2-evaluator/eval-runner.js +10 -2
  193. package/dist/harnesses/impls/swe-rebench-v2-evaluator/eval-runner.js.map +1 -1
  194. package/dist/harnesses/impls/swe-rebench-v2-evaluator/harness.d.ts +24 -5
  195. package/dist/harnesses/impls/swe-rebench-v2-evaluator/harness.js +104 -4
  196. package/dist/harnesses/impls/swe-rebench-v2-evaluator/harness.js.map +1 -1
  197. package/dist/harnesses/impls/swe-rebench-v2-evaluator/hf-fetcher.d.ts +9 -0
  198. package/dist/harnesses/impls/swe-rebench-v2-evaluator/hf-fetcher.js +25 -1
  199. package/dist/harnesses/impls/swe-rebench-v2-evaluator/hf-fetcher.js.map +1 -1
  200. package/dist/harnesses/names.d.ts +1 -0
  201. package/dist/harnesses/names.js +3 -0
  202. package/dist/harnesses/names.js.map +1 -1
  203. package/dist/harnesses/readiness-registry.d.ts +48 -0
  204. package/dist/harnesses/readiness-registry.js +136 -0
  205. package/dist/harnesses/readiness-registry.js.map +1 -0
  206. package/dist/harnesses/types.d.ts +7 -0
  207. package/dist/main.d.ts +14 -0
  208. package/dist/main.js +112 -37
  209. package/dist/main.js.map +1 -1
  210. package/dist/mcp/server.js +14 -13
  211. package/dist/mcp/server.js.map +1 -1
  212. package/dist/operator-errors.js +13 -1
  213. package/dist/operator-errors.js.map +1 -1
  214. package/dist/preflight/claude-auth.d.ts +18 -0
  215. package/dist/preflight/claude-auth.js +38 -0
  216. package/dist/preflight/claude-auth.js.map +1 -1
  217. package/dist/scripts/donation-consumption-acceptance.js +1 -1
  218. package/dist/scripts/donation-consumption-acceptance.js.map +1 -1
  219. package/dist/scripts/swe-rebench-v2-known-bad.json +12 -0
  220. package/dist/scripts/swe-rebench-v2-seed-pool.json +26 -0
  221. package/dist/solver-types/_swe-rebench-v2-substrate.d.ts +52 -0
  222. package/dist/solver-types/_swe-rebench-v2-substrate.js +76 -0
  223. package/dist/solver-types/_swe-rebench-v2-substrate.js.map +1 -0
  224. package/dist/solver-types/_swe-rebench-v2-validated-pool.d.ts +38 -12
  225. package/dist/solver-types/_swe-rebench-v2-validated-pool.js +136 -27
  226. package/dist/solver-types/_swe-rebench-v2-validated-pool.js.map +1 -1
  227. package/dist/solver-types/swe-rebench-v2-auto.d.ts +6 -0
  228. package/dist/solver-types/swe-rebench-v2-auto.js.map +1 -1
  229. package/dist/solver-types/swe-rebench-v2.d.ts +1 -0
  230. package/dist/solver-types/swe-rebench-v2.js +19 -6
  231. package/dist/solver-types/swe-rebench-v2.js.map +1 -1
  232. package/dist/store/store.js +12 -4
  233. package/dist/store/store.js.map +1 -1
  234. package/dist/templates/plugins/runtime-plugin/.mcp.json.tmpl +8 -0
  235. package/dist/templates/plugins/runtime-plugin/README.md.tmpl +30 -0
  236. package/dist/templates/plugins/runtime-plugin/gitignore.tmpl +3 -0
  237. package/dist/templates/plugins/runtime-plugin/jinn.plugin.json.tmpl +21 -0
  238. package/dist/templates/plugins/runtime-plugin/mcp/server.mjs.tmpl +33 -0
  239. package/dist/templates/plugins/runtime-plugin/package.json.tmpl +15 -0
  240. package/dist/templates/plugins/runtime-plugin/test/plugin.test.ts.tmpl +35 -0
  241. package/dist/templates/plugins/runtime-plugin/tsconfig.json.tmpl +11 -0
  242. package/dist/templates/plugins/solver-type-plugin/README.md.tmpl +35 -0
  243. package/dist/templates/plugins/solver-type-plugin/gitignore.tmpl +3 -0
  244. package/dist/templates/plugins/solver-type-plugin/jinn.plugin.json.tmpl +11 -0
  245. package/dist/templates/plugins/solver-type-plugin/package.json.tmpl +15 -0
  246. package/dist/templates/plugins/solver-type-plugin/skills/example/SKILL.md.tmpl +10 -0
  247. package/dist/templates/plugins/solver-type-plugin/test/plugin.test.ts.tmpl +25 -0
  248. package/dist/templates/plugins/solver-type-plugin/tsconfig.json.tmpl +11 -0
  249. package/dist/tx-retry.d.ts +13 -0
  250. package/dist/tx-retry.js +22 -0
  251. package/dist/tx-retry.js.map +1 -1
  252. package/dist/types/envelope.d.ts +28 -21
  253. package/dist/types/envelope.js +8 -3
  254. package/dist/types/envelope.js.map +1 -1
  255. package/dist/types/payloads/index.d.ts +2 -2
  256. package/dist/types/payloads/index.js +13 -12
  257. package/dist/types/payloads/index.js.map +1 -1
  258. package/dist/types/payloads/portfolio-v0.d.ts +60 -10
  259. package/dist/types/payloads/portfolio-v0.js +16 -6
  260. package/dist/types/payloads/portfolio-v0.js.map +1 -1
  261. package/dist/types/payloads/prediction-apy-v0.d.ts +52 -10
  262. package/dist/types/payloads/prediction-apy-v0.js +16 -6
  263. package/dist/types/payloads/prediction-apy-v0.js.map +1 -1
  264. package/dist/types/payloads/prediction-v0.d.ts +49 -10
  265. package/dist/types/payloads/prediction-v0.js +16 -6
  266. package/dist/types/payloads/prediction-v0.js.map +1 -1
  267. package/dist/vendor/@jinn-network/sdk/dist/payloads/prediction-v1.d.ts +45 -6
  268. package/dist/vendor/@jinn-network/sdk/dist/payloads/prediction-v1.js +16 -6
  269. package/dist/x402/handler.js +51 -20
  270. package/dist/x402/handler.js.map +1 -1
  271. package/package.json +11 -3
  272. package/plugins/swe-rebench-v2-diffmin/.claude-plugin/plugin.json +5 -0
  273. package/plugins/swe-rebench-v2-diffmin/.mcp.json +8 -0
  274. package/plugins/swe-rebench-v2-diffmin/README.md +69 -0
  275. package/plugins/swe-rebench-v2-diffmin/jinn.plugin.json +12 -0
  276. package/plugins/swe-rebench-v2-diffmin/mcp/diff-stats-server.mjs +72 -0
  277. package/plugins/swe-rebench-v2-diffmin/mcp/diff-stats.mjs +48 -0
  278. package/plugins/swe-rebench-v2-diffmin/package.json +19 -0
  279. package/plugins/swe-rebench-v2-diffmin/skills/diffmin/SKILL.md +116 -0
  280. package/plugins/swe-rebench-v2-diffmin/skills/test-map/SKILL.md +126 -0
  281. package/plugins/swe-rebench-v2-diffmin/test/diff-stats.test.ts +62 -0
  282. package/plugins/swe-rebench-v2-diffmin/test/manifest.test.ts +53 -0
  283. package/plugins/swe-rebench-v2-diffmin/tsconfig.json +12 -0
  284. package/plugins/swe-rebench-v2-runtime/README.md +13 -0
  285. package/plugins/swe-rebench-v2-runtime/skills/orient/SKILL.md +7 -3
  286. package/plugins/swe-rebench-v2-runtime/skills/plan/SKILL.md +6 -17
  287. package/templates/plugins/runtime-plugin/.mcp.json.tmpl +8 -0
  288. package/templates/plugins/runtime-plugin/README.md.tmpl +30 -0
  289. package/templates/plugins/runtime-plugin/gitignore.tmpl +3 -0
  290. package/templates/plugins/runtime-plugin/jinn.plugin.json.tmpl +21 -0
  291. package/templates/plugins/runtime-plugin/mcp/server.mjs.tmpl +33 -0
  292. package/templates/plugins/runtime-plugin/package.json.tmpl +15 -0
  293. package/templates/plugins/runtime-plugin/test/plugin.test.ts.tmpl +35 -0
  294. package/templates/plugins/runtime-plugin/tsconfig.json.tmpl +11 -0
  295. package/templates/plugins/solver-type-plugin/README.md.tmpl +35 -0
  296. package/templates/plugins/solver-type-plugin/gitignore.tmpl +3 -0
  297. package/templates/plugins/solver-type-plugin/jinn.plugin.json.tmpl +11 -0
  298. package/templates/plugins/solver-type-plugin/package.json.tmpl +15 -0
  299. package/templates/plugins/solver-type-plugin/skills/example/SKILL.md.tmpl +10 -0
  300. package/templates/plugins/solver-type-plugin/test/plugin.test.ts.tmpl +25 -0
  301. package/templates/plugins/solver-type-plugin/tsconfig.json.tmpl +11 -0
  302. package/dist/dashboard/assets/index-BjtltOGc.js +0 -76
  303. package/dist/harnesses/impls/claude-code-learner/adapters/claude-code.js.map +0 -1
  304. package/dist/harnesses/impls/claude-code-learner/adapters/codex-code.js.map +0 -1
  305. package/dist/harnesses/impls/claude-code-learner/adapters/codex-workspace.js.map +0 -1
  306. package/dist/harnesses/impls/claude-code-learner/harness.js.map +0 -1
  307. package/dist/harnesses/impls/claude-code-learner/harvest.js.map +0 -1
  308. package/dist/harnesses/impls/claude-code-learner/index.js.map +0 -1
  309. package/dist/harnesses/impls/claude-code-learner/plugin-path.js.map +0 -1
  310. package/dist/harnesses/impls/claude-code-learner/restoration-patch.js.map +0 -1
  311. package/dist/harnesses/impls/claude-code-learner/test-utils/fake-plugin-outputs.js.map +0 -1
  312. package/dist/harnesses/impls/claude-code-learner/test-utils/noop-adapter.js.map +0 -1
  313. package/dist/harnesses/impls/claude-code-learner/types.js.map +0 -1
  314. package/dist/preflight/claude-required.d.ts +0 -8
  315. package/dist/preflight/claude-required.js +0 -17
  316. package/dist/preflight/claude-required.js.map +0 -1
  317. /package/dist/harnesses/impls/{claude-code-learner → learner}/adapters/claude-code.d.ts +0 -0
  318. /package/dist/harnesses/impls/{claude-code-learner → learner}/adapters/claude-code.js +0 -0
  319. /package/dist/harnesses/impls/{claude-code-learner → learner}/adapters/codex-code.d.ts +0 -0
  320. /package/dist/harnesses/impls/{claude-code-learner → learner}/adapters/codex-workspace.d.ts +0 -0
  321. /package/dist/harnesses/impls/{claude-code-learner → learner}/adapters/codex-workspace.js +0 -0
  322. /package/dist/harnesses/impls/{claude-code-learner → learner}/harvest.d.ts +0 -0
  323. /package/dist/harnesses/impls/{claude-code-learner → learner}/restoration-patch.d.ts +0 -0
  324. /package/dist/harnesses/impls/{claude-code-learner → learner}/test-utils/fake-plugin-outputs.d.ts +0 -0
  325. /package/dist/harnesses/impls/{claude-code-learner → learner}/test-utils/fake-plugin-outputs.js +0 -0
  326. /package/dist/harnesses/impls/{claude-code-learner → learner}/test-utils/noop-adapter.d.ts +0 -0
  327. /package/dist/harnesses/impls/{claude-code-learner → learner}/test-utils/noop-adapter.js +0 -0
  328. /package/dist/harnesses/impls/{claude-code-learner → learner}/types.js +0 -0
  329. /package/plugins/{claude-code-learner → learner}/.claude-plugin/plugin.json +0 -0
  330. /package/plugins/{claude-code-learner → learner}/.codex-plugin/plugin.json +0 -0
  331. /package/plugins/{claude-code-learner → learner}/AGENTS.md +0 -0
  332. /package/plugins/{claude-code-learner → learner}/CLAUDE.md +0 -0
  333. /package/plugins/{claude-code-learner → learner}/README.md +0 -0
  334. /package/plugins/{claude-code-learner → learner}/hooks/hooks.json +0 -0
  335. /package/plugins/{claude-code-learner → learner}/hooks/session-start +0 -0
  336. /package/plugins/{claude-code-learner → learner}/skills/learn/SKILL.md +0 -0
  337. /package/plugins/{claude-code-learner → learner}/skills/learn/analyst-prompt.md +0 -0
  338. /package/plugins/{claude-code-learner → learner}/skills/learn/consolidator-prompt.md +0 -0
  339. /package/plugins/{claude-code-learner → learner}/skills/learn/explorer-prompt.md +0 -0
  340. /package/plugins/{claude-code-learner → learner}/skills/learn/planner-prompt.md +0 -0
  341. /package/plugins/{claude-code-learner → learner}/skills/learn/promoter-prompt.md +0 -0
  342. /package/plugins/{claude-code-learner → learner}/skills/learn/step-worker-prompt.md +0 -0
  343. /package/plugins/{claude-code-learner → learner}/skills/learn/strategist-prompt.md +0 -0
@@ -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, waitForContractCode, 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';
@@ -25,10 +25,71 @@ import { detectDeprecatedTestnetSetup, migrateDeprecatedTestnetSetup, } from './
25
25
  const addr = (value) => getAddress(value);
26
26
  const SAFE_TOKEN_BOOTSTRAP_MULTIPLIER = 2n;
27
27
  const STANDARD_MASTER_BOOTSTRAP_MULTIPLIER = 2n;
28
+ /** Master ETH required to FINISH the whole bootstrap from a fresh start (not
29
+ * just to enter Stage 1). Centralized so the daemon's ensureStage1 gate,
30
+ * the read-side funding-plan, gather-status, and the panel faucet target
31
+ * all agree on a single "one-shot fund the operator" number.
32
+ *
33
+ * Components for a 1-service standard-mode bootstrap:
34
+ * - STAGE1_AGENT_ETH (0.010 ETH): master → HD-1 fleet-agent transfer.
35
+ * HD-1 pays for its own Safe deploy + register + setAgentWallet out
36
+ * of this; leftover covers service 1's Stage 2 work (mech deploy +
37
+ * rebind). May get a conditional minEoaGasEth top-up from master if
38
+ * Stage 1's gas eats too much of the original transfer.
39
+ * - minEoaGasEth × STANDARD_MASTER_BOOTSTRAP_MULTIPLIER (0.010 ETH):
40
+ * master gas budget across both stages. Real spend (~0.0025 ETH at
41
+ * typical 6 gwei Base Sepolia) leaves room for ~4× gas-spike margin
42
+ * plus the conditional HD-1 top-up.
43
+ * - minEoaGasEth × (targetServices - 1): per-extra-service top-up for
44
+ * services 2..N. Service 1 piggybacks on HD-1's Stage 1 funding.
45
+ *
46
+ * Total for N=1: 0.010 + 0.010 = 0.020 ETH.
47
+ * Total for N=2: 0.025 ETH.
48
+ * Total for N=3: 0.030 ETH.
49
+ *
50
+ * This number works ONLY when Stage 2's internal gate is `minEoaGasEth ×
51
+ * 1n` (0.005 ETH) — not the historic `× 2n`. After Stage 1 transfers 0.010
52
+ * out, master sits at ~0.0099 ETH (0.020 minus transfer minus Stage 1
53
+ * funding-tx gas). The 0.005 gate clears that with margin; the 0.010 gate
54
+ * did not. See the Stage 2 gate at ensureStage1And2 line ~484.
55
+ *
56
+ * Operator may see a "low runway" warning after bootstrap — that's
57
+ * intentional. The operator-facing 0.020 ETH covers bootstrap completion,
58
+ * not multi-week post-bootstrap runway. Top-up is a separate concern.
59
+ */
60
+ export const STAGE1_AGENT_ETH = 10000000000000000n; // 0.01 ETH (moved out of stepFleetSafeDeploy)
61
+ export function stage1MinMasterEth(config, targetServices = 1) {
62
+ const extraServiceTransfers = config.minEoaGasEth * BigInt(Math.max(0, targetServices - 1));
63
+ return (STAGE1_AGENT_ETH +
64
+ config.minEoaGasEth * STANDARD_MASTER_BOOTSTRAP_MULTIPLIER +
65
+ extraServiceTransfers);
66
+ }
28
67
  /** Conservative default: ~0.001 ETH/day master gas if not configured. */
29
68
  const DEFAULT_MASTER_ETH_DAILY_WEI = 1000000000000000n;
30
69
  /** Warn when ETH above the minimum would last fewer than this many days at the daily estimate. */
31
70
  const MASTER_ETH_RUNWAY_WARN_DAYS = 7n;
71
+ /**
72
+ * Safe → ERC-8004 agent NFT binding retry (jinn-mono-h74p).
73
+ *
74
+ * Empirical observation against fresh Base Sepolia 1/1 Safes: the first
75
+ * `IdentityRegistry.setAgentWallet` attempt reverts with a generic
76
+ * "Execution reverted for an unknown reason" — but the same Safe + same
77
+ * agentId + a freshly-signed message a few seconds later succeeds. The
78
+ * race window is likely freshly-deployed-Safe state lag on the public RPC
79
+ * (the simulator can't read the Safe's storage yet in the same block /
80
+ * eventual-consistency between sibling RPC nodes). A short bounded retry
81
+ * makes the operator-visible behaviour deterministic instead of relying on
82
+ * the "daemon exits → operator restarts → resume at safe_binding_pending"
83
+ * accidental safety net (which goes away when jinn-mono-vh74.2 removes the
84
+ * Claude-auth post-bootstrap exit gate).
85
+ *
86
+ * Defaults: 3 attempts × 3 s delay = at most ~6 s of in-process retry budget
87
+ * before falling through to the existing `safe_binding_pending` persisted
88
+ * state. Real (non-transient) failures still surface — just with a slightly
89
+ * higher latency tax for the diagnostic.
90
+ */
91
+ const DEFAULT_SAFE_BINDING_MAX_ATTEMPTS = 3;
92
+ const DEFAULT_SAFE_BINDING_RETRY_DELAY_MS = 3_000;
32
93
  export class FleetBootstrapper {
33
94
  store;
34
95
  config;
@@ -43,6 +104,8 @@ export class FleetBootstrapper {
43
104
  faucetLoopTimeoutMs;
44
105
  now;
45
106
  autoTestnetFaucet;
107
+ safeBindingMaxAttempts;
108
+ safeBindingRetryDelayMs;
46
109
  constructor(options = {}) {
47
110
  this.store = new FleetStateStore(options.earningDir);
48
111
  this.chain = options.chain ?? 'base';
@@ -55,6 +118,10 @@ export class FleetBootstrapper {
55
118
  this.now = options.now ?? Date.now;
56
119
  this.autoTestnetFaucet =
57
120
  options.autoTestnetFaucet ?? this.env['JINN_DISABLE_TESTNET_FAUCET'] !== '1';
121
+ this.safeBindingMaxAttempts =
122
+ options.safeBindingMaxAttempts ?? DEFAULT_SAFE_BINDING_MAX_ATTEMPTS;
123
+ this.safeBindingRetryDelayMs =
124
+ options.safeBindingRetryDelayMs ?? DEFAULT_SAFE_BINDING_RETRY_DELAY_MS;
58
125
  const dailyOpt = options.masterEthDailyEstimateWei;
59
126
  this.masterEthDailyEstimateWei =
60
127
  dailyOpt !== undefined
@@ -77,6 +144,71 @@ export class FleetBootstrapper {
77
144
  async getStatus() {
78
145
  return this.store.load(this.chain);
79
146
  }
147
+ /**
148
+ * Run `bindAgentWalletToSafe` with the freshly-deployed-Safe race retry
149
+ * (jinn-mono-h74p, corrected in jinn-mono-k1ng).
150
+ *
151
+ * The race: against a fresh 1/1 Safe on Base Sepolia, the first
152
+ * setAgentWallet attempt reverts with "Execution reverted for an unknown
153
+ * reason"; the same Safe + same agentId a few seconds later succeeds.
154
+ *
155
+ * The h74p version of the retry only wrapped the call in a try/catch.
156
+ * In production, `bindAgentWalletToSafe` doesn't throw on revert — it
157
+ * returns a `{ ok: false, error }` outcome — so the catch never fired
158
+ * and the retry was dead code. The per-service path "worked" anyway
159
+ * because it persists `safe_binding_pending` and the next bootstrap
160
+ * resumes the bind. Stage 1 had no equivalent safety net, so a single
161
+ * `ok: false` halted bootstrap (the 2026-05-18 canary failure).
162
+ *
163
+ * This wrapper:
164
+ * - Retries on returned `ok: false` (the way the race actually
165
+ * manifests in production).
166
+ * - Also retries on thrown exceptions (defense-in-depth in case viem
167
+ * error handling changes).
168
+ * - Returns the final outcome; callers decide whether to throw, mark
169
+ * pending, or proceed.
170
+ *
171
+ * Single attempt budget: `safeBindingMaxAttempts` × `safeBindingRetryDelayMs`
172
+ * (defaults: 3 × 3 s = ~9 s).
173
+ */
174
+ async bindAgentWalletWithRetry(args, label) {
175
+ const maxAttempts = Math.max(1, this.safeBindingMaxAttempts);
176
+ let lastResult;
177
+ let lastThrowError;
178
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
179
+ try {
180
+ lastResult = await bindAgentWalletToSafe(args);
181
+ if (lastResult.ok)
182
+ return lastResult;
183
+ if (attempt < maxAttempts) {
184
+ console.error(`[fleet-bootstrap] ${label}: setAgentWallet attempt ` +
185
+ `${attempt}/${maxAttempts} returned ok=false (${lastResult.error.shortMessage}); ` +
186
+ `retrying in ${this.safeBindingRetryDelayMs}ms...`);
187
+ if (this.safeBindingRetryDelayMs > 0) {
188
+ await sleep(this.safeBindingRetryDelayMs);
189
+ }
190
+ }
191
+ }
192
+ catch (err) {
193
+ lastThrowError = err;
194
+ if (attempt < maxAttempts) {
195
+ const reason = err instanceof Error ? err.message : String(err);
196
+ console.error(`[fleet-bootstrap] ${label}: setAgentWallet attempt ` +
197
+ `${attempt}/${maxAttempts} threw (${reason}); retrying in ` +
198
+ `${this.safeBindingRetryDelayMs}ms...`);
199
+ if (this.safeBindingRetryDelayMs > 0) {
200
+ await sleep(this.safeBindingRetryDelayMs);
201
+ }
202
+ }
203
+ }
204
+ }
205
+ if (lastResult)
206
+ return lastResult; // final ok:false propagated to caller
207
+ // Only thrown all the way through — no successful response or returned outcome.
208
+ throw lastThrowError instanceof Error
209
+ ? lastThrowError
210
+ : new Error(String(lastThrowError));
211
+ }
80
212
  /**
81
213
  * Conservative daily master gas (wei): max(DEFAULT, rough tx count from poll interval × cost).
82
214
  */
@@ -112,16 +244,149 @@ export class FleetBootstrapper {
112
244
  const mnemonic = await this.loadExistingMnemonic(state, password);
113
245
  return this.stepRegisterAgent(state, mnemonic, serviceIndex);
114
246
  }
115
- async bootstrap(password) {
116
- // Handle legacy keystore migration
247
+ /**
248
+ * Stage 1 Identity (universal). Walks: wallet → predict Safe (from
249
+ * HD-index-1 agent EOA) → ETH funding gate → deploy Safe → mint agentId
250
+ * + setAgentWallet via ERC-1271. Idempotent and re-entrant. Does NOT
251
+ * touch service rows or staking — those belong to Stage 2.
252
+ *
253
+ * Fleet-level fields written:
254
+ * - fleet_safe_address (after predict)
255
+ * - fleet_agent_id, fleet_identity_registry, fleet_stage='stage1'
256
+ * (after mint + bind)
257
+ *
258
+ * Funding gate: requires ETH on the master EOA only (no OLAS). On testnet,
259
+ * the existing CDP faucet loop drains as usual when `autoTestnetFaucet`
260
+ * is enabled.
261
+ *
262
+ * See docs/superpowers/specs/2026-05-13-plug-in-builder-entry-point-design.md §5.1.
263
+ */
264
+ async ensureStage1(password) {
265
+ // Legacy keystore migration (same as bootstrap()).
117
266
  if (!this.store.hasMnemonicKeystore() && this.store.hasLegacyKeystore()) {
118
267
  await this.store.migrateLegacyFiles();
119
268
  }
120
269
  let state = await this.store.load(this.chain);
270
+ // Short-circuit if Stage 1 is already complete (or beyond).
271
+ if (state.fleet_stage === 'stage1' || state.fleet_stage === 'stage1_and_2') {
272
+ // Even when stage marker says complete, fleet identity may be empty for
273
+ // pre-j07 operators (`stage1_and_2` is set by the migration for
274
+ // services-complete-but-no-agent_id operators). In that case we leave
275
+ // Stage 1 alone — the legacy backfill in main.ts handles those rows
276
+ // and a future ensureStage1 call after backfill will promote.
277
+ return {
278
+ ok: true,
279
+ fleet_state: state,
280
+ message: state.fleet_agent_id !== null
281
+ ? `Stage 1 already complete (fleet_agent_id=${state.fleet_agent_id}, fleet_safe=${state.fleet_safe_address}).`
282
+ : 'Stage 1 marker present but fleet identity is empty (legacy operator). Skipping.',
283
+ };
284
+ }
121
285
  try {
122
- // Phase 1: Master wallet setup
123
286
  state = await this.ensureMasterWallet(state, password);
124
- // Phase 1b: Check master funding
287
+ // Stage 1 funding gate — ETH only (no OLAS). Stage 1 needs
288
+ // STAGE1_AGENT_ETH (0.01) for the master → agent transfer plus
289
+ // minEoaGasEth (0.005) reserved for the master's own gas to send that
290
+ // transfer. The agent EOA then pays for Safe deploy + ERC-8004 register
291
+ // + setAgentWallet out of the funds it just received.
292
+ // See jinn-mono-u34i: pre-fix this gate was 2×minEoaGasEth (= 0.01 ETH),
293
+ // which equaled the transfer amount and left no gas headroom, so a
294
+ // master holding the gate's minimum would fail eth_estimateGas with
295
+ // "gas required exceeds allowance (0)".
296
+ const requiredMasterEth = stage1MinMasterEth(this.config, this.targetServices);
297
+ const masterAddress = state.master_address;
298
+ const masterBalance = await this.publicClient.getBalance({
299
+ address: masterAddress,
300
+ });
301
+ if (masterBalance < requiredMasterEth) {
302
+ const shortfall = requiredMasterEth - masterBalance;
303
+ return {
304
+ ok: false,
305
+ fleet_state: state,
306
+ 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}`,
307
+ funding: {
308
+ master_address: masterAddress,
309
+ eth_required: shortfall.toString(),
310
+ eth_balance: masterBalance.toString(),
311
+ },
312
+ };
313
+ }
314
+ const mnemonic = await this.loadExistingMnemonic(state, password);
315
+ // Step 1: predict fleet Safe from HD-index-1 agent EOA.
316
+ if (!state.fleet_safe_address) {
317
+ state = await this.stepFleetSafePredict(state, mnemonic);
318
+ }
319
+ // Step 2: deploy fleet Safe if bytecode absent.
320
+ const safeCode = await this.publicClient.getCode({
321
+ address: getAddress(state.fleet_safe_address),
322
+ });
323
+ if (safeCode === undefined || safeCode === '0x') {
324
+ state = await this.stepFleetSafeDeploy(state, mnemonic);
325
+ }
326
+ // Step 3: mint agentId + bind Safe via setAgentWallet.
327
+ if (!state.fleet_agent_id) {
328
+ state = await this.stepFleetIdentityRegister(state, mnemonic);
329
+ }
330
+ else if (state.fleet_stage !== 'stage1' && state.fleet_stage !== 'stage1_and_2') {
331
+ // Identity was minted but stage marker is stale; advance it.
332
+ state = await this.store.patchFleet({ fleet_stage: 'stage1' });
333
+ }
334
+ return {
335
+ ok: true,
336
+ fleet_state: state,
337
+ message: `Stage 1 complete. fleet_agent_id=${state.fleet_agent_id}, fleet_safe=${state.fleet_safe_address}.`,
338
+ };
339
+ }
340
+ catch (error) {
341
+ const { summary, hint, rawMessage } = formatBootstrapOperatorMessage(error);
342
+ const userMessage = hint !== undefined ? `${summary}\nHint: ${hint}` : summary;
343
+ if (this.debug) {
344
+ console.error(`[fleet-bootstrap] ensureStage1 failed:`, error);
345
+ }
346
+ else {
347
+ console.error(`[fleet-bootstrap] ${summary}`);
348
+ if (hint !== undefined)
349
+ console.error(`Hint: ${hint}`);
350
+ if (rawMessage && rawMessage !== summary) {
351
+ console.error(`[fleet-bootstrap] raw: ${rawMessage.split('\n')[0]}`);
352
+ }
353
+ }
354
+ return {
355
+ ok: false,
356
+ fleet_state: state,
357
+ message: userMessage,
358
+ rawErrorMessage: rawMessage,
359
+ };
360
+ }
361
+ }
362
+ /**
363
+ * Stage 1 + Stage 2 — full operator bootstrap. Calls `ensureStage1`
364
+ * first; on success, walks Stage 2 per service. Builder-only users who
365
+ * have completed Stage 1 and call this method later begin Stage 2 from
366
+ * `awaiting_stake` for the first service row (created lazily here).
367
+ *
368
+ * Two-Safe topology in standard mode: `fleet_safe_address !==
369
+ * services[0].safe_address` because Stage 2's `distributor.stake()`
370
+ * creates its own Safe. In self-bond mode the two converge (both
371
+ * derived from HD-index-1).
372
+ *
373
+ * See docs/superpowers/specs/2026-05-13-plug-in-builder-entry-point-design.md §5.1.
374
+ */
375
+ async ensureStage1And2(password) {
376
+ // Stage 1 first — establishes fleet identity. Short-circuits if already done.
377
+ const stage1Result = await this.ensureStage1(password);
378
+ if (!stage1Result.ok) {
379
+ return stage1Result;
380
+ }
381
+ // Original bootstrap body — copied verbatim from the previous bootstrap()
382
+ // method, with two changes:
383
+ // (a) the legacy-keystore migration and master-wallet-ensure are no-ops
384
+ // because ensureStage1 already ran them.
385
+ // (b) at the end, if any service reached `complete`/`safe_binding_pending`
386
+ // we advance `fleet_stage` to `'stage1_and_2'`.
387
+ let state = stage1Result.fleet_state;
388
+ try {
389
+ // Phase 1b: Check master funding for the full operator path.
125
390
  const masterAddress = state.master_address;
126
391
  let masterBalance = await this.publicClient.getBalance({ address: masterAddress });
127
392
  // Self-bond mode needs much more ETH than standard mode because the master
@@ -159,7 +424,17 @@ export class FleetBootstrapper {
159
424
  const requiredMasterEth = this.stakingMode === 'standard'
160
425
  ? (standardFleetAlreadyComplete
161
426
  ? 0n
162
- : this.config.minEoaGasEth * (standardFleetHasInProgressServices ? 1n : STANDARD_MASTER_BOOTSTRAP_MULTIPLIER))
427
+ // Stage 2 master gas budget covers distributor.stake() (~0.003
428
+ // ETH at typical 6 gwei Base Sepolia) plus per-extra-service
429
+ // top-up transfers. Previously this was `× 2` for fresh fleets,
430
+ // which double-counted a service-1 transfer that doesn't actually
431
+ // fire (HD-1 carries Stage 1 leftover, gets a conditional top-up
432
+ // only if needed). See jinn-mono-u34i: the `× 2` figure also
433
+ // exceeded the post-Stage-1 master balance at the operator-facing
434
+ // 0.020 ETH budget by ~127k gwei of Stage 1 gas burn, causing a
435
+ // second funding prompt.
436
+ : this.config.minEoaGasEth +
437
+ this.config.minEoaGasEth * BigInt(Math.max(0, this.targetServices - 1)))
163
438
  : SELF_BOND_ETH_PER_SERVICE * BigInt(this.targetServices);
164
439
  const autoFaucetEnabled = this.autoTestnetFaucet;
165
440
  // Re-sum system ETH (master + agent/safe balances for self-bond mode).
@@ -291,6 +566,11 @@ export class FleetBootstrapper {
291
566
  const nextIndex = nextFleetServiceIndex(state.services);
292
567
  state = await this.bootstrapService(state, mnemonic, nextIndex);
293
568
  }
569
+ // Advance fleet_stage to 'stage1_and_2' if any service is operational.
570
+ const anyOperationalAfter = state.services.some(s => isOperationalServiceStep(s.step));
571
+ if (anyOperationalAfter && state.fleet_stage !== 'stage1_and_2') {
572
+ state = await this.store.patchFleet({ fleet_stage: 'stage1_and_2' });
573
+ }
294
574
  return {
295
575
  ok: true,
296
576
  fleet_state: state,
@@ -322,6 +602,14 @@ export class FleetBootstrapper {
322
602
  };
323
603
  }
324
604
  }
605
+ /**
606
+ * Back-compat alias. Existing call sites in `client/src/cli/commands/bootstrap.ts`
607
+ * and `client/src/cli/commands/fleet-scale.ts` continue to call `bootstrap()`;
608
+ * forwarding to `ensureStage1And2` preserves their semantics without churn.
609
+ */
610
+ async bootstrap(password) {
611
+ return this.ensureStage1And2(password);
612
+ }
325
613
  /**
326
614
  * If the master is only slightly above the minimum, warn about gas runway (heuristic days).
327
615
  */
@@ -382,6 +670,133 @@ export class FleetBootstrapper {
382
670
  return freshMnemonic;
383
671
  }
384
672
  }
673
+ // ── Stage 1: fleet-level identity steps (nghf) ────────────────────────
674
+ /** Deterministic Safe predict from the HD-index-1 agent EOA. */
675
+ async stepFleetSafePredict(state, mnemonic) {
676
+ const agentAddress = deriveAgentAddress(mnemonic, 1);
677
+ const agentKey = walletPrivateKeyAtIndex(mnemonic, 1);
678
+ console.error(`[fleet-bootstrap] Stage 1: predicting fleet Safe (owner=${agentAddress})`);
679
+ const { address } = await initPredictedSafe({
680
+ rpcUrl: this.config.rpcUrl,
681
+ signerKey: agentKey,
682
+ owners: [agentAddress],
683
+ threshold: 1,
684
+ });
685
+ void state;
686
+ return this.store.patchFleet({ fleet_safe_address: getAddress(address) });
687
+ }
688
+ /** Deploy the predicted fleet Safe. Funds the agent EOA from master if needed. */
689
+ async stepFleetSafeDeploy(state, mnemonic) {
690
+ const agentAddress = deriveAgentAddress(mnemonic, 1);
691
+ const agentKey = walletPrivateKeyAtIndex(mnemonic, 1);
692
+ const agentSigner = deriveAgentSigner(mnemonic, 1);
693
+ const fleetSafe = state.fleet_safe_address;
694
+ // Fund agent EOA so it can pay for Safe deploy + setAgentWallet gas.
695
+ // 0.01 ETH covers Safe deploy (~250k gas) + register (~80k) + setAgentWallet
696
+ // (~200k) at testnet gas prices comfortably. STAGE1_AGENT_ETH is the
697
+ // module-level constant used both here and in `stage1MinMasterEth` so the
698
+ // gate and the transfer agree (jinn-mono-u34i).
699
+ const masterAccount = deriveMasterSigner(mnemonic);
700
+ const masterWallet = createJinnWalletClient(this.config.rpcUrl, this.chain, masterAccount);
701
+ const agentBalance = await this.publicClient.getBalance({
702
+ address: getAddress(agentAddress),
703
+ });
704
+ if (agentBalance < STAGE1_AGENT_ETH) {
705
+ const fundAmount = STAGE1_AGENT_ETH - agentBalance;
706
+ console.error(`[fleet-bootstrap] Stage 1: funding fleet agent EOA with ${fundAmount} wei from master`);
707
+ const fundHash = await viemSendTransactionWithRetry(masterWallet, this.publicClient, {
708
+ account: masterAccount,
709
+ to: addr(agentAddress),
710
+ value: fundAmount,
711
+ });
712
+ await waitForTransactionReceiptWithRetry(this.publicClient, fundHash);
713
+ }
714
+ console.error(`[fleet-bootstrap] Stage 1: deploying fleet Safe at ${fleetSafe}`);
715
+ const { safe } = await initPredictedSafe({
716
+ rpcUrl: this.config.rpcUrl,
717
+ signerKey: agentKey,
718
+ owners: [agentAddress],
719
+ threshold: 1,
720
+ });
721
+ const deployTx = await safe.createSafeDeploymentTransaction();
722
+ const agentWallet = createJinnWalletClient(this.config.rpcUrl, this.chain, agentSigner);
723
+ const deployHash = await viemSendTransactionWithRetry(agentWallet, this.publicClient, {
724
+ account: agentSigner,
725
+ to: deployTx.to,
726
+ value: BigInt(deployTx.value),
727
+ data: deployTx.data,
728
+ });
729
+ const receipt = await waitForTransactionReceiptWithRetry(this.publicClient, deployHash);
730
+ if (receipt.status !== 'success') {
731
+ throw new Error(`Fleet Safe deployment tx failed: ${deployHash}`);
732
+ }
733
+ try {
734
+ await waitForContractCode(this.publicClient, getAddress(fleetSafe));
735
+ }
736
+ catch {
737
+ throw new Error(`Fleet Safe deployment succeeded but no code at ${fleetSafe}`);
738
+ }
739
+ console.error(`[fleet-bootstrap] Stage 1: fleet Safe deployed (tx=${deployHash})`);
740
+ return this.store.load(this.chain);
741
+ }
742
+ /** Mint the fleet agentId + bind Safe via setAgentWallet (ERC-1271). */
743
+ async stepFleetIdentityRegister(state, mnemonic) {
744
+ const identityRegistry = this.config.identityRegistry ?? IDENTITY_REGISTRY_ADDRESSES[this.config.chainId];
745
+ if (!identityRegistry) {
746
+ throw new Error(`IdentityRegistry address not configured for chainId=${this.config.chainId}.`);
747
+ }
748
+ const fleetSafe = state.fleet_safe_address;
749
+ const agentSigner = deriveAgentSigner(mnemonic, 1);
750
+ const agentWallet = createJinnWalletClient(this.config.rpcUrl, this.chain, agentSigner);
751
+ // Mint agentId — empty agent URI for v0 (matches stepRegisterAgent §6.1 in spec).
752
+ const registerData = encodeFunctionData({
753
+ abi: IDENTITY_REGISTRY_ABI,
754
+ functionName: 'register',
755
+ args: [''],
756
+ });
757
+ console.error(`[fleet-bootstrap] Stage 1: minting fleet agentId ` +
758
+ `(IdentityRegistry=${identityRegistry}, agentEOA=${agentSigner.address})`);
759
+ const mintTxHash = await viemSendTransactionWithRetry(agentWallet, this.publicClient, {
760
+ account: agentSigner,
761
+ to: addr(identityRegistry),
762
+ data: registerData,
763
+ });
764
+ const mintReceipt = await waitForTransactionReceiptWithRetry(this.publicClient, mintTxHash);
765
+ if (mintReceipt.status !== 'success') {
766
+ throw new Error(`Fleet IdentityRegistry.register() failed: ${mintTxHash}`);
767
+ }
768
+ const fleetAgentId = this.parseAgentIdFromReceipt(mintReceipt, identityRegistry);
769
+ if (fleetAgentId === null) {
770
+ throw new Error(`Fleet IdentityRegistry.register() succeeded but Registered event missing (tx=${mintTxHash})`);
771
+ }
772
+ // Persist agentId IMMEDIATELY so a crash between mint and bind doesn't lose it.
773
+ await this.store.patchFleet({
774
+ fleet_agent_id: fleetAgentId,
775
+ fleet_identity_registry: getAddress(identityRegistry),
776
+ });
777
+ // Bind the Safe via setAgentWallet (ERC-1271).
778
+ // Wrapped in the freshly-deployed-Safe retry (jinn-mono-k1ng). The
779
+ // pre-k1ng single-attempt version halted bootstrap when the documented
780
+ // race fired on the first attempt — exactly the 2026-05-18 canary's
781
+ // second-time-around failure mode.
782
+ console.error(`[fleet-bootstrap] Stage 1: binding fleet Safe ${fleetSafe} to agentId=${fleetAgentId}`);
783
+ const bindResult = await this.bindAgentWalletWithRetry({
784
+ identityRegistryAddress: addr(identityRegistry),
785
+ agentId: BigInt(fleetAgentId),
786
+ safeAddress: addr(fleetSafe),
787
+ agentEoaAccount: agentSigner,
788
+ agentEoaWalletClient: agentWallet,
789
+ publicClient: this.publicClient,
790
+ chainId: this.config.chainId,
791
+ }, 'Stage 1');
792
+ if (!bindResult.ok) {
793
+ const bindErr = bindResult.error;
794
+ throw new Error(`Fleet setAgentWallet failed after ${this.safeBindingMaxAttempts} attempts: ${bindErr.shortMessage}` +
795
+ (bindErr.revertReason ? ` (revert: ${bindErr.revertReason})` : ''));
796
+ }
797
+ console.error(`[fleet-bootstrap] Stage 1: setAgentWallet succeeded (tx=${bindResult.txHash})`);
798
+ return this.store.patchFleet({ fleet_stage: 'stage1' });
799
+ }
385
800
  // ── Phase 2: Per-service bootstrap ───────────────────────────────────
386
801
  async bootstrapService(state, mnemonic, index) {
387
802
  const agentAddress = deriveAgentAddress(mnemonic, index);
@@ -837,6 +1252,7 @@ export class FleetBootstrapper {
837
1252
  let svc = (await this.store.load(this.chain)).services.find(s => s.index === index);
838
1253
  if (!svc)
839
1254
  throw new Error(`Service ${index} not found in state`);
1255
+ const fleetSnapshot = await this.store.load(this.chain);
840
1256
  const identityRegistry = this.config.identityRegistry
841
1257
  ?? IDENTITY_REGISTRY_ADDRESSES[this.config.chainId];
842
1258
  if (!identityRegistry) {
@@ -845,7 +1261,7 @@ export class FleetBootstrapper {
845
1261
  }
846
1262
  const agentSigner = deriveAgentSigner(mnemonic, index);
847
1263
  const agentWallet = createJinnWalletClient(this.config.rpcUrl, this.chain, agentSigner);
848
- // ── Sub-step A: mint NFT (skip if agent_id is already set). ─────────
1264
+ // ── Sub-step A: mint NFT (skip if agent_id is already set OR fleet identity exists).
849
1265
  let agentId;
850
1266
  if (svc.agent_id) {
851
1267
  console.error(`[fleet-bootstrap] Service ${index}: ERC-8004 agent already registered ` +
@@ -856,6 +1272,22 @@ export class FleetBootstrapper {
856
1272
  step: svc.step === 'safe_binding_pending' ? 'safe_binding_pending' : 'agent_registered',
857
1273
  });
858
1274
  }
1275
+ else if (fleetSnapshot.fleet_agent_id) {
1276
+ // nghf: reuse the fleet-level agentId minted by ensureStage1 instead of
1277
+ // minting a second one. This collapses the "one agentId per user"
1278
+ // invariant in spec §5.1 for the standard-mode two-Safe topology.
1279
+ console.error(`[fleet-bootstrap] Service ${index}: reusing fleet agentId=${fleetSnapshot.fleet_agent_id} ` +
1280
+ `(no second mint needed).`);
1281
+ agentId = fleetSnapshot.fleet_agent_id;
1282
+ svc = await this.firstServiceUpdate(index, {
1283
+ agent_id: fleetSnapshot.fleet_agent_id,
1284
+ agent_uri: '',
1285
+ identity_registry_address: fleetSnapshot.fleet_identity_registry ?? getAddress(identityRegistry),
1286
+ agent_registered_tx: null,
1287
+ step: 'agent_registered',
1288
+ error: null,
1289
+ });
1290
+ }
859
1291
  else {
860
1292
  // v0: empty agentURI. The richer agent card (per §6 of the spec) is
861
1293
  // future work — operators may later call `setAgentURI`.
@@ -924,8 +1356,18 @@ export class FleetBootstrapper {
924
1356
  step: 'safe_binding_pending',
925
1357
  error: null,
926
1358
  });
1359
+ // Unified retry policy (jinn-mono-k1ng — supersedes h74p's throw-only
1360
+ // retry): retry on `ok: false` and on thrown exceptions. The h74p
1361
+ // version only caught throws, but `bindAgentWalletToSafe` returns
1362
+ // `ok: false` for the documented freshly-deployed-Safe revert race —
1363
+ // so the retry was dead code under real RPC. Per-service "worked"
1364
+ // anyway because the next bootstrap resumes from `safe_binding_pending`;
1365
+ // k1ng makes the in-process retry actually do its job so we don't
1366
+ // depend on the operator restarting the daemon.
1367
+ let bindResult;
1368
+ let lastBindError;
927
1369
  try {
928
- const result = await bindAgentWalletToSafe({
1370
+ bindResult = await this.bindAgentWalletWithRetry({
929
1371
  identityRegistryAddress: addr(identityRegistry),
930
1372
  agentId: BigInt(agentId),
931
1373
  safeAddress: addr(safeAddress),
@@ -933,23 +1375,45 @@ export class FleetBootstrapper {
933
1375
  agentEoaWalletClient: agentWallet,
934
1376
  publicClient: this.publicClient,
935
1377
  chainId: this.config.chainId,
936
- });
1378
+ }, `Service ${index}`);
1379
+ }
1380
+ catch (err) {
1381
+ lastBindError = err;
1382
+ }
1383
+ if (bindResult?.ok === true) {
937
1384
  console.error(`[fleet-bootstrap] Service ${index}: setAgentWallet succeeded ` +
938
- `(tx=${result.txHash}, safe=${safeAddress}).`);
1385
+ `(tx=${bindResult.txHash}, safe=${safeAddress}).`);
939
1386
  svc = await this.firstServiceUpdate(index, {
940
1387
  safe_bound_to_agent: true,
941
1388
  step: 'complete',
942
1389
  error: null,
1390
+ error_revert_reason: null,
1391
+ error_short_message: null,
943
1392
  });
944
1393
  }
945
- catch (err) {
946
- const reason = err instanceof Error ? err.message : String(err);
947
- console.error(`[fleet-bootstrap] Service ${index}: setAgentWallet failed; continuing with ` +
948
- `safe_bound_to_agent=false (${reason}).`);
1394
+ else if (bindResult && !bindResult.ok) {
1395
+ const bindErr = bindResult.error;
1396
+ console.error(`[fleet-bootstrap] Service ${index}: setAgentWallet failed after retries; ` +
1397
+ `continuing with safe_bound_to_agent=false (${bindErr.shortMessage}` +
1398
+ `${bindErr.revertReason ? `, revert: ${bindErr.revertReason}` : ''}).`);
1399
+ svc = await this.firstServiceUpdate(index, {
1400
+ safe_bound_to_agent: false,
1401
+ step: 'safe_binding_pending',
1402
+ error: `safe_binding_failed: ${bindErr.shortMessage}`,
1403
+ error_revert_reason: bindErr.revertReason,
1404
+ error_short_message: bindErr.shortMessage,
1405
+ });
1406
+ }
1407
+ else {
1408
+ const reason = lastBindError instanceof Error ? lastBindError.message : String(lastBindError);
1409
+ console.error(`[fleet-bootstrap] Service ${index}: setAgentWallet threw on every attempt; ` +
1410
+ `continuing with safe_bound_to_agent=false (${reason}).`);
949
1411
  svc = await this.firstServiceUpdate(index, {
950
1412
  safe_bound_to_agent: false,
951
1413
  step: 'safe_binding_pending',
952
1414
  error: `safe_binding_failed: ${reason}`,
1415
+ error_revert_reason: null,
1416
+ error_short_message: null,
953
1417
  });
954
1418
  }
955
1419
  }
@@ -1066,8 +1530,10 @@ export class FleetBootstrapper {
1066
1530
  if (receipt.status !== 'success') {
1067
1531
  throw new Error(`Safe deployment tx failed for service ${index}: ${deployHash}`);
1068
1532
  }
1069
- const deployedCode = await this.publicClient.getCode({ address: getAddress(safeAddress) });
1070
- if (deployedCode === undefined || deployedCode === '0x') {
1533
+ try {
1534
+ await waitForContractCode(this.publicClient, getAddress(safeAddress));
1535
+ }
1536
+ catch {
1071
1537
  throw new Error(`Safe deployment succeeded but no code at ${safeAddress}`);
1072
1538
  }
1073
1539
  console.error(`[fleet-bootstrap] Service ${index}: Safe deployed (tx: ${deployHash})`);