@jinn-network/client 0.1.7 → 0.1.8

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 (319) hide show
  1. package/README.md +67 -1
  2. package/dist/adapters/mech/adapter.d.ts +19 -1
  3. package/dist/adapters/mech/adapter.js +130 -14
  4. package/dist/adapters/mech/adapter.js.map +1 -1
  5. package/dist/adapters/mech/contracts.d.ts +22 -1
  6. package/dist/adapters/mech/contracts.js +34 -24
  7. package/dist/adapters/mech/contracts.js.map +1 -1
  8. package/dist/adapters/mech/safe.d.ts +1 -1
  9. package/dist/adapters/mech/safe.js +5 -3
  10. package/dist/adapters/mech/safe.js.map +1 -1
  11. package/dist/adapters/mech/types.d.ts +6 -1
  12. package/dist/adapters/mech/types.js.map +1 -1
  13. package/dist/agent/operator-claude.js +8 -0
  14. package/dist/agent/operator-claude.js.map +1 -1
  15. package/dist/api/activity-events-endpoint.d.ts +14 -0
  16. package/dist/api/activity-events-endpoint.js +59 -0
  17. package/dist/api/activity-events-endpoint.js.map +1 -0
  18. package/dist/api/bootstrap-endpoint.d.ts +1 -2
  19. package/dist/api/bootstrap-endpoint.js +42 -24
  20. package/dist/api/bootstrap-endpoint.js.map +1 -1
  21. package/dist/api/codex-doctor-endpoint.d.ts +22 -5
  22. package/dist/api/codex-doctor-endpoint.js +136 -17
  23. package/dist/api/codex-doctor-endpoint.js.map +1 -1
  24. package/dist/api/debug-report-endpoint.d.ts +27 -0
  25. package/dist/api/debug-report-endpoint.js +157 -0
  26. package/dist/api/debug-report-endpoint.js.map +1 -0
  27. package/dist/api/gather-status.d.ts +33 -0
  28. package/dist/api/gather-status.js +211 -26
  29. package/dist/api/gather-status.js.map +1 -1
  30. package/dist/api/hermes-doctor-endpoint.d.ts +15 -7
  31. package/dist/api/hermes-doctor-endpoint.js +56 -19
  32. package/dist/api/hermes-doctor-endpoint.js.map +1 -1
  33. package/dist/api/launcher-status.d.ts +4 -2
  34. package/dist/api/launcher-status.js +11 -10
  35. package/dist/api/launcher-status.js.map +1 -1
  36. package/dist/api/launcher-tasks.d.ts +1 -1
  37. package/dist/api/launcher-tasks.js +12 -8
  38. package/dist/api/launcher-tasks.js.map +1 -1
  39. package/dist/api/operator-artifacts-endpoint.js +73 -6
  40. package/dist/api/operator-artifacts-endpoint.js.map +1 -1
  41. package/dist/api/portfolio-v0-build.d.ts +7 -1
  42. package/dist/api/portfolio-v0-build.js +6 -2
  43. package/dist/api/portfolio-v0-build.js.map +1 -1
  44. package/dist/api/prediction-v1-build.d.ts +6 -0
  45. package/dist/api/prediction-v1-build.js +3 -1
  46. package/dist/api/prediction-v1-build.js.map +1 -1
  47. package/dist/api/server.d.ts +17 -0
  48. package/dist/api/server.js +40 -1
  49. package/dist/api/server.js.map +1 -1
  50. package/dist/api/setup-endpoints.d.ts +0 -9
  51. package/dist/api/setup-endpoints.js +11 -153
  52. package/dist/api/setup-endpoints.js.map +1 -1
  53. package/dist/api/solvernets-endpoints.js +30 -63
  54. package/dist/api/solvernets-endpoints.js.map +1 -1
  55. package/dist/api/status-build.d.ts +115 -2
  56. package/dist/api/status-build.js +47 -11
  57. package/dist/api/status-build.js.map +1 -1
  58. package/dist/api/status-harness-rollup.d.ts +35 -0
  59. package/dist/api/status-harness-rollup.js +45 -0
  60. package/dist/api/status-harness-rollup.js.map +1 -0
  61. package/dist/api/task-runs-build.d.ts +8 -0
  62. package/dist/api/task-runs-build.js +5 -1
  63. package/dist/api/task-runs-build.js.map +1 -1
  64. package/dist/build-info.json +4 -4
  65. package/dist/build-meta.json +1 -1
  66. package/dist/captures/live-publisher.js +24 -4
  67. package/dist/captures/live-publisher.js.map +1 -1
  68. package/dist/captures/publish.d.ts +1 -1
  69. package/dist/chain-read-errors.d.ts +12 -0
  70. package/dist/chain-read-errors.js +26 -1
  71. package/dist/chain-read-errors.js.map +1 -1
  72. package/dist/cli/commands/codedigest-revert-check.d.ts +33 -0
  73. package/dist/cli/commands/codedigest-revert-check.js +249 -0
  74. package/dist/cli/commands/codedigest-revert-check.js.map +1 -0
  75. package/dist/cli/commands/solver-nets.d.ts +1 -0
  76. package/dist/cli/commands/solver-nets.js +177 -22
  77. package/dist/cli/commands/solver-nets.js.map +1 -1
  78. package/dist/cli/commands/solver-plugins-block.d.ts +33 -0
  79. package/dist/cli/commands/solver-plugins-block.js +118 -0
  80. package/dist/cli/commands/solver-plugins-block.js.map +1 -0
  81. package/dist/cli/commands/solver-plugins-feedback.d.ts +72 -0
  82. package/dist/cli/commands/solver-plugins-feedback.js +262 -0
  83. package/dist/cli/commands/solver-plugins-feedback.js.map +1 -0
  84. package/dist/cli/commands/solver-plugins-read.d.ts +54 -0
  85. package/dist/cli/commands/solver-plugins-read.js +259 -0
  86. package/dist/cli/commands/solver-plugins-read.js.map +1 -0
  87. package/dist/cli/commands/solver-plugins.d.ts +35 -0
  88. package/dist/cli/commands/solver-plugins.js +399 -2
  89. package/dist/cli/commands/solver-plugins.js.map +1 -1
  90. package/dist/cli/commands/tasks.js +15 -2
  91. package/dist/cli/commands/tasks.js.map +1 -1
  92. package/dist/cli/index.js +2 -0
  93. package/dist/cli/index.js.map +1 -1
  94. package/dist/cli/task-native-readiness.d.ts +7 -0
  95. package/dist/cli/task-native-readiness.js +7 -5
  96. package/dist/cli/task-native-readiness.js.map +1 -1
  97. package/dist/config.d.ts +183 -232
  98. package/dist/config.js +232 -107
  99. package/dist/config.js.map +1 -1
  100. package/dist/daemon/ai-units-gate.d.ts +54 -0
  101. package/dist/daemon/ai-units-gate.js +82 -0
  102. package/dist/daemon/ai-units-gate.js.map +1 -0
  103. package/dist/daemon/creator.js +13 -0
  104. package/dist/daemon/creator.js.map +1 -1
  105. package/dist/daemon/daemon.d.ts +10 -0
  106. package/dist/daemon/daemon.js +203 -30
  107. package/dist/daemon/daemon.js.map +1 -1
  108. package/dist/daemon/gate-logger.d.ts +9 -0
  109. package/dist/daemon/gate-logger.js +2 -0
  110. package/dist/daemon/gate-logger.js.map +1 -0
  111. package/dist/daemon/jinn-claim-loop.js +22 -4
  112. package/dist/daemon/jinn-claim-loop.js.map +1 -1
  113. package/dist/daemon/readiness-gate.d.ts +1 -4
  114. package/dist/daemon/readiness-gate.js.map +1 -1
  115. package/dist/daemon/spend-cap-gate.d.ts +40 -0
  116. package/dist/daemon/spend-cap-gate.js +46 -0
  117. package/dist/daemon/spend-cap-gate.js.map +1 -0
  118. package/dist/dashboard/assets/index-CzKxvMcU.css +32 -0
  119. package/dist/dashboard/assets/index-yVemxHot.js +351 -0
  120. package/dist/dashboard/index.html +2 -2
  121. package/dist/discovery/http.js +328 -1
  122. package/dist/discovery/http.js.map +1 -1
  123. package/dist/discovery/onchain.js +42 -4
  124. package/dist/discovery/onchain.js.map +1 -1
  125. package/dist/discovery/types.d.ts +129 -0
  126. package/dist/discovery/types.js.map +1 -1
  127. package/dist/discovery/with-fallback.js +27 -0
  128. package/dist/discovery/with-fallback.js.map +1 -1
  129. package/dist/earning/bootstrap.d.ts +8 -3
  130. package/dist/earning/bootstrap.js +36 -13
  131. package/dist/earning/bootstrap.js.map +1 -1
  132. package/dist/earning/safe-adapter.js +23 -11
  133. package/dist/earning/safe-adapter.js.map +1 -1
  134. package/dist/earning/types.d.ts +6 -6
  135. package/dist/earning/viem-clients.d.ts +11 -4
  136. package/dist/earning/viem-clients.js +14 -5
  137. package/dist/earning/viem-clients.js.map +1 -1
  138. package/dist/erc8004/identity.d.ts +19 -3
  139. package/dist/erc8004/identity.js +38 -11
  140. package/dist/erc8004/identity.js.map +1 -1
  141. package/dist/erc8004/index.d.ts +1 -1
  142. package/dist/erc8004/index.js.map +1 -1
  143. package/dist/events/types.d.ts +2 -2
  144. package/dist/harnesses/cost-estimates.d.ts +10 -31
  145. package/dist/harnesses/cost-estimates.js +11 -43
  146. package/dist/harnesses/cost-estimates.js.map +1 -1
  147. package/dist/harnesses/engine/engine.d.ts +28 -4
  148. package/dist/harnesses/engine/engine.js +103 -17
  149. package/dist/harnesses/engine/engine.js.map +1 -1
  150. package/dist/harnesses/engine/persistence.d.ts +21 -4
  151. package/dist/harnesses/engine/persistence.js +43 -6
  152. package/dist/harnesses/engine/persistence.js.map +1 -1
  153. package/dist/harnesses/engine/state.d.ts +9 -0
  154. package/dist/harnesses/engine/state.js +23 -10
  155. package/dist/harnesses/engine/state.js.map +1 -1
  156. package/dist/harnesses/impls/hermes-agent/bootstrap.js +4 -2
  157. package/dist/harnesses/impls/hermes-agent/bootstrap.js.map +1 -1
  158. package/dist/harnesses/impls/hermes-agent/config-builder.d.ts +1 -1
  159. package/dist/harnesses/impls/hermes-agent/config-builder.js +4 -2
  160. package/dist/harnesses/impls/hermes-agent/config-builder.js.map +1 -1
  161. package/dist/harnesses/impls/hermes-agent/harness.d.ts +14 -0
  162. package/dist/harnesses/impls/hermes-agent/harness.js +16 -2
  163. package/dist/harnesses/impls/hermes-agent/harness.js.map +1 -1
  164. package/dist/harnesses/impls/hermes-agent/prompt.d.ts +6 -6
  165. package/dist/harnesses/impls/hermes-agent/prompt.js +6 -6
  166. package/dist/harnesses/impls/learner/adapters/claude-code.d.ts +17 -0
  167. package/dist/harnesses/impls/learner/adapters/claude-code.js +113 -14
  168. package/dist/harnesses/impls/learner/adapters/claude-code.js.map +1 -1
  169. package/dist/harnesses/impls/learner/adapters/codex-code.d.ts +9 -0
  170. package/dist/harnesses/impls/learner/adapters/codex-code.js +30 -8
  171. package/dist/harnesses/impls/learner/adapters/codex-code.js.map +1 -1
  172. package/dist/harnesses/impls/learner/harness.d.ts +24 -0
  173. package/dist/harnesses/impls/learner/harness.js +27 -3
  174. package/dist/harnesses/impls/learner/harness.js.map +1 -1
  175. package/dist/harnesses/impls/learner/harvest.d.ts +1 -1
  176. package/dist/harnesses/impls/learner/harvest.js +23 -5
  177. package/dist/harnesses/impls/learner/harvest.js.map +1 -1
  178. package/dist/harnesses/impls/learner/restoration-patch.d.ts +2 -2
  179. package/dist/harnesses/impls/learner/restoration-patch.js +25 -6
  180. package/dist/harnesses/impls/learner/restoration-patch.js.map +1 -1
  181. package/dist/harnesses/impls/swe-rebench-v2-evaluator/eval-runner.js +21 -1
  182. package/dist/harnesses/impls/swe-rebench-v2-evaluator/eval-runner.js.map +1 -1
  183. package/dist/harnesses/impls/swe-rebench-v2-evaluator/hf-fetcher.d.ts +74 -5
  184. package/dist/harnesses/impls/swe-rebench-v2-evaluator/hf-fetcher.js +103 -32
  185. package/dist/harnesses/impls/swe-rebench-v2-evaluator/hf-fetcher.js.map +1 -1
  186. package/dist/harnesses/readiness-registry.d.ts +7 -0
  187. package/dist/harnesses/readiness-registry.js +9 -0
  188. package/dist/harnesses/readiness-registry.js.map +1 -1
  189. package/dist/learner/revert-decision.d.ts +59 -0
  190. package/dist/learner/revert-decision.js +53 -0
  191. package/dist/learner/revert-decision.js.map +1 -0
  192. package/dist/learner/revert-stats.d.ts +24 -0
  193. package/dist/learner/revert-stats.js +44 -0
  194. package/dist/learner/revert-stats.js.map +1 -0
  195. package/dist/main.js +177 -104
  196. package/dist/main.js.map +1 -1
  197. package/dist/mcp/get-codedigest-reward.d.ts +13 -0
  198. package/dist/mcp/get-codedigest-reward.js +23 -0
  199. package/dist/mcp/get-codedigest-reward.js.map +1 -0
  200. package/dist/mcp/server.js +23 -0
  201. package/dist/mcp/server.js.map +1 -1
  202. package/dist/observability/debug-report-assemble.d.ts +43 -0
  203. package/dist/observability/debug-report-assemble.js +80 -0
  204. package/dist/observability/debug-report-assemble.js.map +1 -0
  205. package/dist/observability/emit-event.d.ts +9 -2
  206. package/dist/observability/emit-event.js +36 -2
  207. package/dist/observability/emit-event.js.map +1 -1
  208. package/dist/observability/file-logger.d.ts +69 -0
  209. package/dist/observability/file-logger.js +177 -0
  210. package/dist/observability/file-logger.js.map +1 -0
  211. package/dist/observability/redact-secrets.d.ts +65 -0
  212. package/dist/observability/redact-secrets.js +300 -0
  213. package/dist/observability/redact-secrets.js.map +1 -0
  214. package/dist/observability/tar.d.ts +30 -0
  215. package/dist/observability/tar.js +102 -0
  216. package/dist/observability/tar.js.map +1 -0
  217. package/dist/plugins/learner/skills/learn/consolidator-prompt.md +18 -1
  218. package/dist/plugins/learner/skills/learn/promoter-prompt.md +72 -1
  219. package/dist/preflight/pidfile-liveness.d.ts +44 -0
  220. package/dist/preflight/pidfile-liveness.js +103 -0
  221. package/dist/preflight/pidfile-liveness.js.map +1 -0
  222. package/dist/preflight/rpc-network.d.ts +40 -0
  223. package/dist/preflight/rpc-network.js +67 -1
  224. package/dist/preflight/rpc-network.js.map +1 -1
  225. package/dist/rpc/transport.d.ts +109 -0
  226. package/dist/rpc/transport.js +220 -0
  227. package/dist/rpc/transport.js.map +1 -0
  228. package/dist/scripts/donation-consumption-acceptance.js +7 -28
  229. package/dist/scripts/donation-consumption-acceptance.js.map +1 -1
  230. package/dist/scripts/swe-rebench-v2-pytest-missing.json +16 -0
  231. package/dist/solver-nets/prediction-operator-ux.d.ts +1 -2
  232. package/dist/solver-nets/prediction-operator-ux.js +56 -53
  233. package/dist/solver-nets/prediction-operator-ux.js.map +1 -1
  234. package/dist/solver-nets/registry.d.ts +19 -1
  235. package/dist/solver-nets/registry.js +37 -24
  236. package/dist/solver-nets/registry.js.map +1 -1
  237. package/dist/solver-types/_swe-rebench-v2-pool.d.ts +9 -2
  238. package/dist/solver-types/_swe-rebench-v2-pool.js +15 -20
  239. package/dist/solver-types/_swe-rebench-v2-pool.js.map +1 -1
  240. package/dist/solver-types/_swe-rebench-v2-state.d.ts +15 -0
  241. package/dist/solver-types/_swe-rebench-v2-state.js +19 -0
  242. package/dist/solver-types/_swe-rebench-v2-state.js.map +1 -1
  243. package/dist/solver-types/_swe-rebench-v2-validated-pool.d.ts +116 -2
  244. package/dist/solver-types/_swe-rebench-v2-validated-pool.js +296 -21
  245. package/dist/solver-types/_swe-rebench-v2-validated-pool.js.map +1 -1
  246. package/dist/solver-types/swe-rebench-v2-auto.d.ts +20 -11
  247. package/dist/solver-types/swe-rebench-v2-auto.js +64 -19
  248. package/dist/solver-types/swe-rebench-v2-auto.js.map +1 -1
  249. package/dist/solver-types/swe-rebench-v2.d.ts +8 -2
  250. package/dist/solver-types/swe-rebench-v2.js +127 -11
  251. package/dist/solver-types/swe-rebench-v2.js.map +1 -1
  252. package/dist/solvernets/daemon-init.d.ts +1 -1
  253. package/dist/solvernets/daemon-init.js +19 -4
  254. package/dist/solvernets/daemon-init.js.map +1 -1
  255. package/dist/solvernets/launched-record-dispatcher.d.ts +4 -0
  256. package/dist/solvernets/launched-record-dispatcher.js +10 -4
  257. package/dist/solvernets/launched-record-dispatcher.js.map +1 -1
  258. package/dist/solvernets/registry-client-erc8004.js +11 -0
  259. package/dist/solvernets/registry-client-erc8004.js.map +1 -1
  260. package/dist/solvernets/store.d.ts +2 -2
  261. package/dist/spend/ai-units-config.d.ts +39 -0
  262. package/dist/spend/ai-units-config.js +28 -0
  263. package/dist/spend/ai-units-config.js.map +1 -0
  264. package/dist/spend/ai-units.d.ts +89 -0
  265. package/dist/spend/ai-units.js +156 -0
  266. package/dist/spend/ai-units.js.map +1 -0
  267. package/dist/spend/cost-surface-status.d.ts +12 -0
  268. package/dist/spend/cost-surface-status.js +24 -0
  269. package/dist/spend/cost-surface-status.js.map +1 -0
  270. package/dist/spend/credential.d.ts +39 -0
  271. package/dist/spend/credential.js +71 -0
  272. package/dist/spend/credential.js.map +1 -0
  273. package/dist/spend/daemon-config.d.ts +13 -0
  274. package/dist/spend/daemon-config.js +24 -0
  275. package/dist/spend/daemon-config.js.map +1 -0
  276. package/dist/spend/pricing.d.ts +16 -0
  277. package/dist/spend/pricing.js +26 -0
  278. package/dist/spend/pricing.js.map +1 -0
  279. package/dist/spend/record.d.ts +13 -0
  280. package/dist/spend/record.js +36 -0
  281. package/dist/spend/record.js.map +1 -0
  282. package/dist/spend/usage.d.ts +27 -0
  283. package/dist/spend/usage.js +113 -0
  284. package/dist/spend/usage.js.map +1 -0
  285. package/dist/store/store.d.ts +101 -0
  286. package/dist/store/store.js +304 -4
  287. package/dist/store/store.js.map +1 -1
  288. package/dist/trajectory/transcript-parsers/codex-session.d.ts +12 -6
  289. package/dist/trajectory/transcript-parsers/codex-session.js +114 -13
  290. package/dist/trajectory/transcript-parsers/codex-session.js.map +1 -1
  291. package/dist/trajectory/transcript-parsers/types.d.ts +8 -8
  292. package/dist/trajectory/transcript-session-dirs.d.ts +18 -0
  293. package/dist/trajectory/transcript-session-dirs.js +85 -0
  294. package/dist/trajectory/transcript-session-dirs.js.map +1 -0
  295. package/dist/trajectory/transcript-watcher.d.ts +20 -1
  296. package/dist/trajectory/transcript-watcher.js +108 -32
  297. package/dist/trajectory/transcript-watcher.js.map +1 -1
  298. package/dist/tx-retry.d.ts +25 -0
  299. package/dist/tx-retry.js +95 -7
  300. package/dist/tx-retry.js.map +1 -1
  301. package/dist/types/payloads/portfolio-v0.d.ts +3 -3
  302. package/dist/types/payloads/prediction-apy-v0.d.ts +3 -3
  303. package/dist/types/payloads/prediction-v0.d.ts +12 -12
  304. package/package.json +11 -3
  305. package/plugins/learner/skills/learn/consolidator-prompt.md +18 -1
  306. package/plugins/learner/skills/learn/promoter-prompt.md +72 -1
  307. package/plugins/swe-rebench-v2-diffmin/README.md +10 -9
  308. package/plugins/swe-rebench-v2-diffmin/jinn.plugin.json +1 -1
  309. package/plugins/swe-rebench-v2-diffmin/skills/diffmin/SKILL.md +15 -10
  310. package/plugins/swe-rebench-v2-diffmin/skills/test-map/SKILL.md +10 -12
  311. package/plugins/swe-rebench-v2-runtime/.claude-plugin/plugin.json +1 -1
  312. package/plugins/swe-rebench-v2-runtime/.codex-plugin/plugin.json +3 -3
  313. package/plugins/swe-rebench-v2-runtime/README.md +6 -6
  314. package/plugins/swe-rebench-v2-runtime/jinn.plugin.json +2 -3
  315. package/plugins/swe-rebench-v2-runtime/skills/task/SKILL.md +81 -0
  316. package/dist/dashboard/assets/index-BUlE8F3Y.js +0 -330
  317. package/dist/dashboard/assets/index-blqc7eqq.css +0 -32
  318. package/plugins/swe-rebench-v2-runtime/skills/orient/SKILL.md +0 -29
  319. package/plugins/swe-rebench-v2-runtime/skills/plan/SKILL.md +0 -53
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Pure statistics for the per-codeDigest revert decision (issue #764).
3
+ *
4
+ * Two-proportion z-test on pass/total for "arm A" (codeDigest WITH a candidate
5
+ * Improve commit) vs "arm B" (codeDigest AT the commit's parent). No I/O; unit-
6
+ * tested directly with hand-computed z-values. `delta = pA - pB` (negative means
7
+ * the commit made the pass rate worse).
8
+ */
9
+ /** Two-proportion z-test. Returns no-signal (z=0, p=1) if either total is 0. */
10
+ export function twoProportionZTest(input) {
11
+ const { passesA, totalA, passesB, totalB } = input;
12
+ if (totalA <= 0 || totalB <= 0) {
13
+ const pA = totalA > 0 ? passesA / totalA : 0;
14
+ const pB = totalB > 0 ? passesB / totalB : 0;
15
+ return { delta: pA - pB, z: 0, pValue: 1 };
16
+ }
17
+ const pA = passesA / totalA;
18
+ const pB = passesB / totalB;
19
+ const delta = pA - pB;
20
+ const pooled = (passesA + passesB) / (totalA + totalB);
21
+ const se = Math.sqrt(pooled * (1 - pooled) * (1 / totalA + 1 / totalB));
22
+ if (se === 0) {
23
+ // Both arms 0% or both 100% — no measurable difference.
24
+ return { delta, z: 0, pValue: 1 };
25
+ }
26
+ const z = delta / se;
27
+ const pValue = 2 * (1 - standardNormalCdf(Math.abs(z)));
28
+ return { delta, z, pValue };
29
+ }
30
+ /** Standard normal CDF via the Abramowitz & Stegun 7.1.26 erf approximation. */
31
+ function standardNormalCdf(x) {
32
+ return 0.5 * (1 + erf(x / Math.SQRT2));
33
+ }
34
+ function erf(x) {
35
+ // Abramowitz & Stegun 7.1.26, max abs error ~1.5e-7.
36
+ const t = 1 / (1 + 0.3275911 * Math.abs(x));
37
+ const y = 1 -
38
+ ((((1.061405429 * t - 1.453152027) * t + 1.421413741) * t - 0.284496736) * t +
39
+ 0.254829592) *
40
+ t *
41
+ Math.exp(-x * x);
42
+ return x >= 0 ? y : -y;
43
+ }
44
+ //# sourceMappingURL=revert-stats.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"revert-stats.js","sourceRoot":"","sources":["../../src/learner/revert-stats.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAkBH,gFAAgF;AAChF,MAAM,UAAU,kBAAkB,CAAC,KAAyB;IAC1D,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IACnD,IAAI,MAAM,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,EAAE,CAAC;QAC/B,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7C,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7C,OAAO,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;IAC7C,CAAC;IACD,MAAM,EAAE,GAAG,OAAO,GAAG,MAAM,CAAC;IAC5B,MAAM,EAAE,GAAG,OAAO,GAAG,MAAM,CAAC;IAC5B,MAAM,KAAK,GAAG,EAAE,GAAG,EAAE,CAAC;IACtB,MAAM,MAAM,GAAG,CAAC,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IACvD,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;IACxE,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC;QACb,wDAAwD;QACxD,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;IACpC,CAAC;IACD,MAAM,CAAC,GAAG,KAAK,GAAG,EAAE,CAAC;IACrB,MAAM,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACxD,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;AAC9B,CAAC;AAED,gFAAgF;AAChF,SAAS,iBAAiB,CAAC,CAAS;IAClC,OAAO,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;AACzC,CAAC;AAED,SAAS,GAAG,CAAC,CAAS;IACpB,qDAAqD;IACrD,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5C,MAAM,CAAC,GACL,CAAC;QACD,CAAC,CAAC,CAAC,CAAC,WAAW,GAAG,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC;YAC1E,WAAW,CAAC;YACZ,CAAC;YACD,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACzB,CAAC"}
package/dist/main.js CHANGED
@@ -33,6 +33,7 @@ import { setDefaultTxSubmissionLedger } from './tx-retry.js';
33
33
  import { CapturePublishUnavailableError } from './api/captures.js';
34
34
  import { invalidatePredictionOperatorStatusCache } from './api/gather-status.js';
35
35
  import { ensureUiToken } from './api/ui-token.js';
36
+ import { getFileLogger, closeFileLogger } from './observability/file-logger.js';
36
37
  import { hashImplStateDir } from './harnesses/freeze.js';
37
38
  import { readModeState } from './harnesses/mode-state.js';
38
39
  import { attachAgentWs, updateAgentClaudePath } from './agent/agent-ws.js';
@@ -41,6 +42,7 @@ import { requestDaemonRestart } from './restart-daemon.js';
41
42
  import { buildEnvelope, emitEnvelope } from './errors/envelope.js';
42
43
  import { clearBootstrapError, persistBootstrapError, } from './errors/persisted-bootstrap-error.js';
43
44
  import { emitStructured } from './events/emitter.js';
45
+ import { applyPidfileLivenessGate } from './preflight/pidfile-liveness.js';
44
46
  import { FleetBootstrapper, recoverEvictedService as recoverEvictedServiceFn } from './earning/bootstrap.js';
45
47
  import { DEFAULT_TESTNET_ARTIFACTS, applyChainGasOverrides, getChainConfig, loadJinnMviConfig } from './earning/contracts.js';
46
48
  import { runLegacyAgentIdMigration } from './earning/migrate-agent-id.js';
@@ -50,6 +52,9 @@ import { decryptMnemonic, deriveMasterSigner, walletPrivateKeyAtIndex } from './
50
52
  import { MechAdapter } from './adapters/mech/adapter.js';
51
53
  import { ClaudeRunner } from './runner/claude.js';
52
54
  import { Daemon } from './daemon/daemon.js';
55
+ import { buildSpendCapConfig } from './spend/daemon-config.js';
56
+ import { buildAiUnitsConfig } from './spend/ai-units-config.js';
57
+ import { REFERENCE_CEILING } from './spend/ai-units.js';
53
58
  import { buildJinnClaimLoopConfig, shouldWireJinnClaimL1Signer, } from './daemon/jinn-claim-loop-wiring.js';
54
59
  import { createJinnPublicClient, createJinnWalletClient, createJinnL1PublicClient, createJinnL1WalletClient } from './earning/viem-clients.js';
55
60
  import { privateKeyToAccount } from 'viem/accounts';
@@ -62,7 +67,7 @@ import { CLAUDE_CODE_HARNESS, CODEX_HARNESS, HERMES_AGENT_HARNESS, harnessStateD
62
67
  import { resolveContractFromSolverNetId } from './solvernets/launched-record-dispatcher.js';
63
68
  import { HarnessReadinessRegistry } from './harnesses/readiness-registry.js';
64
69
  import { createClients } from './adapters/mech/safe.js';
65
- import { loadSolverNets } from './solver-nets/registry.js';
70
+ import { findJoinedByName, loadSolverNets, solverTypeFromJoinedContract, } from './solver-nets/registry.js';
66
71
  import { createCorpus } from './corpus/index.js';
67
72
  import { DEFAULT_EXECUTION_DISCOVERY_FROM_BLOCK } from './corpus/onchain-query.js';
68
73
  import { CapturesStore } from './store/captures.js';
@@ -78,10 +83,12 @@ import { ClaudeCodeJsonlParser } from './trajectory/transcript-parsers/claude-co
78
83
  import { CodexSessionParser } from './trajectory/transcript-parsers/codex-session.js';
79
84
  import { GeminiSessionParser } from './trajectory/transcript-parsers/gemini-session.js';
80
85
  import { CursorSqliteParser } from './trajectory/transcript-parsers/cursor-sqlite.js';
86
+ import { startTranscriptWatcher, } from './trajectory/transcript-watcher.js';
87
+ import { defaultTranscriptWatchDirectories } from './trajectory/transcript-session-dirs.js';
81
88
  import { buildInfo } from './build-info.js';
82
89
  import { BASE_FEEDS } from './venues/chainlink/feeds.js';
83
90
  import { GeneratedTaskSource, StaticConfiguredTaskSource, filterBindableTasks } from './tasks/sources.js';
84
- import { checkRpcNetwork, logRpcLocalDevToStderr, rpcNetworkFailureHint } from './preflight/rpc-network.js';
91
+ import { checkRpcNetwork, logRpcLocalDevToStderr, probeFallbackChain, rpcNetworkFailureHint, summarizeFallbackChain, } from './preflight/rpc-network.js';
85
92
  import { apiPortFailureMessage, checkApiPortAvailable } from './preflight/api-port.js';
86
93
  import { openBrowser } from './cli/open-browser.js';
87
94
  import { keepSetupUiOnBootstrapError } from './setup/halt-mode.js';
@@ -203,25 +210,15 @@ class EnsurePendingCaptureProcessor {
203
210
  onStart() { }
204
211
  onEnd(span) {
205
212
  const sessionId = stringAttribute(span.attributes['jinn.session.id']);
206
- if (!sessionId || this.captures.getBySession(sessionId))
213
+ if (!sessionId)
207
214
  return;
208
- try {
209
- this.captures.savePending({
210
- sessionId,
211
- capturedAt: hrTimeToIso(span.startTime),
212
- originatingTool: { name: inferCaptureTool(span) },
213
- capturePath: 'A',
214
- status: 'pending',
215
- spanCount: 0,
216
- durationMs: 0,
217
- redactedSpanCount: 0,
218
- ...repoMetadataFromSpan(span),
219
- });
220
- }
221
- catch (err) {
222
- if (!this.captures.getBySession(sessionId))
223
- throw err;
224
- }
215
+ ensurePendingCapture(this.captures, {
216
+ sessionId,
217
+ capturedAt: hrTimeToIso(span.startTime),
218
+ tool: inferCaptureTool(span),
219
+ capturePath: inferCapturePath(span),
220
+ ...repoMetadataFromSpan(span),
221
+ });
225
222
  }
226
223
  }
227
224
  function stringAttribute(value) {
@@ -236,6 +233,11 @@ function inferCaptureTool(span) {
236
233
  ?? stringAttribute(span.resource.attributes['service.name'])
237
234
  ?? 'otel';
238
235
  }
236
+ function inferCapturePath(span) {
237
+ if (stringAttribute(span.attributes['transcript.tool']))
238
+ return 'B';
239
+ return 'A';
240
+ }
239
241
  function repoMetadataFromSpan(span) {
240
242
  const attrs = span.attributes;
241
243
  const repoRemoteUrl = stringAttribute(attrs['repo.remote_url'])
@@ -265,28 +267,35 @@ function parserForStopHookTool(tool) {
265
267
  }
266
268
  }
267
269
  }
268
- function ensurePendingStopHookCapture(captures, payload) {
269
- if (captures.getBySession(payload.sessionId))
270
+ function ensurePendingCapture(captures, params) {
271
+ if (captures.getBySession(params.sessionId))
270
272
  return;
271
273
  try {
272
274
  captures.savePending({
273
- sessionId: payload.sessionId,
274
- capturedAt: payload.stoppedAt,
275
- originatingTool: { name: payload.tool },
276
- capturePath: 'D',
275
+ sessionId: params.sessionId,
276
+ capturedAt: params.capturedAt,
277
+ originatingTool: { name: params.tool },
278
+ capturePath: params.capturePath,
277
279
  status: 'pending',
278
280
  spanCount: 0,
279
281
  durationMs: 0,
280
282
  redactedSpanCount: 0,
283
+ ...(params.repoRemoteUrl ? { repoRemoteUrl: params.repoRemoteUrl } : {}),
284
+ ...(params.repoCommitHash ? { repoCommitHash: params.repoCommitHash } : {}),
281
285
  });
282
286
  }
283
287
  catch (err) {
284
- if (!captures.getBySession(payload.sessionId))
288
+ if (!captures.getBySession(params.sessionId))
285
289
  throw err;
286
290
  }
287
291
  }
288
292
  async function ingestStopHookCapture(captures, receiver, payload) {
289
- ensurePendingStopHookCapture(captures, payload);
293
+ ensurePendingCapture(captures, {
294
+ sessionId: payload.sessionId,
295
+ capturedAt: payload.stoppedAt,
296
+ tool: payload.tool,
297
+ capturePath: 'D',
298
+ });
290
299
  if (!payload.transcriptPath)
291
300
  return;
292
301
  if (!receiver) {
@@ -641,6 +650,11 @@ function emitProgress(envelope) {
641
650
  }
642
651
  export async function main() {
643
652
  console.log(`[main] jinn-client starting on ${NETWORK_CHAIN}`);
653
+ // Issue #420: initialise the rotating daemon file logger early so lifecycle
654
+ // events (tapped in `observability/emit-event.ts`) accumulate durable,
655
+ // pre-redacted log lines for the one-click debug report. Constructing the
656
+ // singleton here also runs the startup age-based cleanup of stale rotations.
657
+ getFileLogger();
644
658
  // ── Daemon API bearer token (jinn-mono-pr64 hardening) ───────────────────
645
659
  //
646
660
  // Cost-mutating API routes (`POST /v1/artifacts/acquire`, `POST /artifacts`)
@@ -681,6 +695,15 @@ export async function main() {
681
695
  else {
682
696
  logRpcLocalDevToStderr(rpcPreflight);
683
697
  }
698
+ // Boot-time RPC fallback-chain probe (issue #592, AC7 + AC9). Log-only —
699
+ // per-slot 429s/5xx never gate startup. checkRpcNetwork above already
700
+ // fail-loud on chain-id mismatch against the head provider.
701
+ await probeFallbackChain(config.rpcUrls, config.network, 'L2');
702
+ console.error(summarizeFallbackChain('L2', config.rpcUrls));
703
+ if (config.jinnClaimLoopEnabled && config.ethereumRpcUrls) {
704
+ await probeFallbackChain(config.ethereumRpcUrls, config.network, 'L1');
705
+ console.error(summarizeFallbackChain('L1', config.ethereumRpcUrls));
706
+ }
684
707
  const portPreflight = await checkApiPortAvailable(config.apiPort);
685
708
  if (!portPreflight.ok) {
686
709
  emitEnvelope({
@@ -734,11 +757,56 @@ export async function main() {
734
757
  console.warn('[main] Capture OTLP receiver disabled; path-A telemetry capture unavailable: ' +
735
758
  `${err instanceof Error ? err.message : String(err)}`);
736
759
  }
760
+ let transcriptWatcher;
761
+ let pathBSyntheticSpanProvider;
762
+ const closePathBTranscriptWatcher = async () => {
763
+ const watcher = transcriptWatcher;
764
+ const provider = pathBSyntheticSpanProvider;
765
+ transcriptWatcher = undefined;
766
+ pathBSyntheticSpanProvider = undefined;
767
+ await Promise.all([
768
+ watcher?.shutdown().catch(() => undefined),
769
+ provider?.shutdown().catch(() => undefined),
770
+ ]);
771
+ };
737
772
  const closeCaptureReceiver = async () => {
773
+ await closePathBTranscriptWatcher();
738
774
  const receiver = captureReceiver;
739
775
  captureReceiver = undefined;
740
776
  await receiver?.shutdown().catch(() => undefined);
741
777
  };
778
+ if (captureReceiver) {
779
+ try {
780
+ const watchDirectories = defaultTranscriptWatchDirectories();
781
+ if (watchDirectories.length > 0) {
782
+ pathBSyntheticSpanProvider = startSyntheticSpanProvider({
783
+ otlpHttpEndpoint: `http://127.0.0.1:${captureReceiver.httpPort}/v1/traces`,
784
+ });
785
+ transcriptWatcher = await startTranscriptWatcher({
786
+ directories: watchDirectories,
787
+ onEvent: (envelope) => {
788
+ ensurePendingCapture(capturesStore, {
789
+ sessionId: envelope.sessionId,
790
+ capturedAt: new Date().toISOString(),
791
+ tool: envelope.tool,
792
+ capturePath: 'B',
793
+ });
794
+ emitSyntheticSpan(pathBSyntheticSpanProvider, envelope);
795
+ },
796
+ });
797
+ console.log('[main] Path-B transcript watcher started for ' +
798
+ watchDirectories.map((d) => `${d.tool}@${d.directory}`).join(', '));
799
+ }
800
+ else {
801
+ console.log('[main] Path-B transcript watcher skipped — no Codex/Claude session directories on disk yet');
802
+ }
803
+ }
804
+ catch (err) {
805
+ await closePathBTranscriptWatcher();
806
+ console.warn('[main] Path-B transcript watcher disabled: ' +
807
+ `${err instanceof Error ? err.message : String(err)}`);
808
+ }
809
+ }
742
810
  const capturePublishRef = { current: undefined };
743
811
  const earningStateStore = new FleetStateStore(config.earningDir);
744
812
  const initialFleet = await earningStateStore.tryLoadExisting();
@@ -790,11 +858,6 @@ export async function main() {
790
858
  // builder-artifacts. Holder ref lets the routes register eagerly and
791
859
  // start returning real data the moment main.ts assigns holder.current.
792
860
  const discoveryApiHolder = { current: undefined };
793
- // hjex.3: holder for the restake callback. Populated in running mode after
794
- // bootstrap completes (when mnemonic + distributorAddress are available).
795
- const restakeCallbackRef = {
796
- current: undefined,
797
- };
798
861
  // hjex.6: retry signal for the bootstrap halt-and-resume loop.
799
862
  // When a SetupBootstrapHalted is caught (fatal non-funding error or funding
800
863
  // timeout), main() waits on this promise instead of returning, so the setup
@@ -836,9 +899,7 @@ export async function main() {
836
899
  // requestDaemonRestart so the operator is never stranded.
837
900
  preSpawnCleanup: async () => {
838
901
  await setupApiServer.close().catch(() => undefined);
839
- if (captureReceiver) {
840
- await captureReceiver.shutdown().catch(() => undefined);
841
- }
902
+ await closeCaptureReceiver();
842
903
  },
843
904
  }),
844
905
  },
@@ -871,6 +932,14 @@ export async function main() {
871
932
  config.operator = operator;
872
933
  },
873
934
  },
935
+ // Issue #420: one-click operator debug report. The bundle assembler
936
+ // reads the live resolved `config` so the download reflects env
937
+ // overrides + defaults, not just the on-disk config file.
938
+ debugReport: {
939
+ store: sharedStore,
940
+ config,
941
+ configPath: CONFIG_PATH ?? DEFAULT_CONFIG_PATH,
942
+ },
874
943
  captures: {
875
944
  captures: capturesStore,
876
945
  publishCapture: async (sessionId) => {
@@ -894,7 +963,6 @@ export async function main() {
894
963
  configReader: () => ({
895
964
  rpcUrl: config.rpcUrl,
896
965
  defaultRpcUrl: CHAIN_CONFIG.rpcUrl,
897
- solverNets: config.solverNets,
898
966
  joinedSolverNets: config.joinedSolverNets,
899
967
  }),
900
968
  },
@@ -1017,22 +1085,15 @@ export async function main() {
1017
1085
  configPath: CONFIG_PATH ?? DEFAULT_CONFIG_PATH,
1018
1086
  defaultRpcUrlForChain: () => CHAIN_CONFIG.rpcUrl,
1019
1087
  onClaudePathSelected: selectClaudePath,
1020
- onSolverNetsUpdated: (solverNets) => {
1021
- config.solverNets = solverNets;
1022
- // The prediction operator status is memoised per-`JinnConfig`
1023
- // reference; mutating in place leaves the cache pointing at the
1024
- // pre-edit snapshot. Drop the entry so the next /v1/status read
1025
- // (and thus Overview's `solverNet.enabled` gating) reflects the
1026
- // toggle immediately. (jinn-mono-l2zl.15.4.12)
1088
+ // Issue #421 retired the legacy `solverNets` write target. Setup
1089
+ // endpoints no longer call back into the daemon to mutate operator
1090
+ // SolverNet config; the canonical join flow is
1091
+ // `POST /v1/operator/join/:cid`, which mutates
1092
+ // `config.joinedSolverNets` directly via its own write path.
1093
+ // The cache-invalidation hook is no longer needed here.
1094
+ onSolverNetsUpdated: () => {
1027
1095
  invalidatePredictionOperatorStatusCache(config);
1028
1096
  },
1029
- // hjex.3: delegate to the live callback populated once running mode starts.
1030
- restake: (serviceId) => {
1031
- if (!restakeCallbackRef.current) {
1032
- return Promise.resolve({ ok: false, error: 'restake_not_available_in_setup_mode' });
1033
- }
1034
- return restakeCallbackRef.current(serviceId);
1035
- },
1036
1097
  // hjex.6: re-trigger the bootstrap state machine from the SPA Retry button.
1037
1098
  // Resolves the halt-and-resume promise; main() will loop back and call
1038
1099
  // bootstrap() again. Rejects if the daemon is not currently halted.
@@ -1094,29 +1155,30 @@ export async function main() {
1094
1155
  // TODO(jinn-mono launcher Task 8): real `getReservedBudgetWei`
1095
1156
  // (sum of unconsumed claim payments across open Tasks).
1096
1157
  launcher: {
1097
- getConfig: () => ({ solverNets: config.solverNets }),
1158
+ getConfig: () => ({ joinedSolverNets: config.joinedSolverNets }),
1098
1159
  configPath: CONFIG_PATH ?? DEFAULT_CONFIG_PATH,
1099
- // Cache-invalidation hook retained for the operator-mode
1100
- // setup-endpoints flow; the launcher-mode PATCH route was retired
1101
- // by Task 22, so this currently fires only when operator mode
1102
- // mutates `solverNets`.
1103
- onSolverNetsUpdated: (solverNets) => {
1104
- config.solverNets = solverNets;
1160
+ // Issue #421 retired the legacy `solverNets` write target. The hook
1161
+ // only needs to invalidate the prediction-operator status cache when
1162
+ // operator mode mutates joinedSolverNets via setup endpoints.
1163
+ onSolverNetsUpdated: () => {
1105
1164
  invalidatePredictionOperatorStatusCache(config);
1106
1165
  },
1107
1166
  getGeneratorState: (netName) => {
1108
1167
  if (netName === 'prediction') {
1109
1168
  return predictionGeneratorRef?.getState();
1110
1169
  }
1111
- const solverType = config.solverNets?.[netName]?.solverType;
1170
+ const joined = findJoinedByName(config.joinedSolverNets, netName);
1171
+ const solverType = joined ? solverTypeFromJoinedContract(joined) : undefined;
1112
1172
  if (!solverType)
1113
1173
  return undefined;
1114
1174
  return launchedGeneratorStateBySolverType.get(solverType)?.();
1115
1175
  },
1116
1176
  getOpenTaskCount: (netName) => {
1117
- const net = config.solverNets?.[netName];
1118
- const solverType = net?.solverType;
1119
- if (!solverType || !safeAddressForLauncher)
1177
+ if (!safeAddressForLauncher)
1178
+ return 0;
1179
+ const joined = findJoinedByName(config.joinedSolverNets, netName);
1180
+ const solverType = joined ? solverTypeFromJoinedContract(joined) : undefined;
1181
+ if (!solverType)
1120
1182
  return 0;
1121
1183
  return sharedStore.countPostedTasksByCreatorAndSolverType({
1122
1184
  creatorSafeAddress: safeAddressForLauncher,
@@ -1327,7 +1389,7 @@ export async function main() {
1327
1389
  return Number.isFinite(n) && n > 0 ? n : 15_000;
1328
1390
  })();
1329
1391
  if (isHaltedOnFunding && haltAddress && haltRequired !== null) {
1330
- const publicClient = createJinnPublicClient(config.rpcUrl, NETWORK_CHAIN);
1392
+ const publicClient = createJinnPublicClient(config.rpcUrls, NETWORK_CHAIN);
1331
1393
  const schedulePoll = () => {
1332
1394
  fundingPollHandle = setTimeout(async () => {
1333
1395
  // Guard: if the signal was already fired, stop polling.
@@ -1425,36 +1487,9 @@ export async function main() {
1425
1487
  const earningStore = new FleetStateStore(config.earningDir);
1426
1488
  const mnemonicForMaster = await decryptMnemonic(await earningStore.loadMnemonicKeystore(), PASSWORD);
1427
1489
  const masterAccount = deriveMasterSigner(mnemonicForMaster);
1428
- const publicClient = createJinnPublicClient(config.rpcUrl, NETWORK_CHAIN);
1490
+ const publicClient = createJinnPublicClient(config.rpcUrls, NETWORK_CHAIN);
1429
1491
  publicClientForLauncher = publicClient;
1430
- const masterWallet = createJinnWalletClient(config.rpcUrl, NETWORK_CHAIN, masterAccount);
1431
- // hjex.3: populate the restake callback now that mnemonic is available.
1432
- if (config.stakingMode === 'standard' && CHAIN_CONFIG.distributorAddress) {
1433
- const fleetStore = earningStore;
1434
- restakeCallbackRef.current = async (serviceId) => {
1435
- try {
1436
- const state = await fleetStore.load(NETWORK_CHAIN);
1437
- const svc = state.services.find(s => s.service_id === serviceId);
1438
- if (!svc)
1439
- return { ok: false, error: `service_not_found:${serviceId}` };
1440
- if (!svc.staking_address)
1441
- return { ok: false, error: 'staking_address_missing' };
1442
- await recoverEvictedServiceFn({
1443
- serviceDisplayIndex: Math.max(0, svc.index - 1),
1444
- serviceId,
1445
- stakingAddress: svc.staking_address,
1446
- distributorAddress: CHAIN_CONFIG.distributorAddress,
1447
- rpcUrl: config.rpcUrl,
1448
- chain: NETWORK_CHAIN,
1449
- mnemonic: mnemonicForMaster,
1450
- });
1451
- return { ok: true };
1452
- }
1453
- catch (err) {
1454
- return { ok: false, error: err instanceof Error ? err.message : String(err) };
1455
- }
1456
- };
1457
- }
1492
+ const masterWallet = createJinnWalletClient(config.rpcUrls, NETWORK_CHAIN, masterAccount);
1458
1493
  const evictionRecovery = config.stakingMode === 'standard' &&
1459
1494
  serviceId !== null &&
1460
1495
  stakingAddress &&
@@ -1513,7 +1548,7 @@ export async function main() {
1513
1548
  // the /build page rendered "Discovery unavailable" permanently.
1514
1549
  discoveryApiHolder.current = sharedDiscoveryApi;
1515
1550
  const adapter = new MechAdapter({
1516
- rpcUrl: config.rpcUrl,
1551
+ rpcUrl: config.rpcUrls,
1517
1552
  mechMarketplaceAddress: MARKETPLACE_ADDRESS,
1518
1553
  routerAddress: ROUTER_ADDRESS,
1519
1554
  mechContractAddress: mechAddress,
@@ -1529,12 +1564,18 @@ export async function main() {
1529
1564
  ? {
1530
1565
  discoveryApi: sharedDiscoveryApi,
1531
1566
  solverNetManifestCids: taskDiscoveryManifestCids,
1532
- // No explicit `onchainFromBlock` — let `MechAdapter`'s
1567
+ // No explicit `onchainFromBlock` by default — let `MechAdapter`'s
1533
1568
  // `DEFAULT_TASK_DISCOVERY_FROM_BLOCK` per-chain default flow
1534
1569
  // through. Hardcoding here shadowed the adapter's default and
1535
1570
  // re-introduced the ghost-task floor every release; removing the
1536
1571
  // shadow makes `adapter.ts` the single source of truth. See gh
1537
- // #300.
1572
+ // #300. An operator MAY opt in to a recent floor via
1573
+ // `taskDiscoveryOnchainFromBlock` to bound the canonical getLogs
1574
+ // scan (which otherwise parses a large history on the main thread
1575
+ // and can stall the loop) and lean on the indexer DiscoveryAPI.
1576
+ ...(config.taskDiscoveryOnchainFromBlock !== undefined
1577
+ ? { onchainFromBlock: config.taskDiscoveryOnchainFromBlock }
1578
+ : {}),
1538
1579
  ...(config.taskDiscoveryAllowedTaskIds?.length
1539
1580
  ? { allowedTaskIds: config.taskDiscoveryAllowedTaskIds }
1540
1581
  : {}),
@@ -1551,10 +1592,10 @@ export async function main() {
1551
1592
  const agentChainContracts = agentChain.contracts;
1552
1593
  const optimismPortalAddress = agentChainContracts?.portal?.[l1Chain.id]?.address;
1553
1594
  const disputeGameFactoryAddress = agentChainContracts?.disputeGameFactory?.[l1Chain.id]?.address;
1554
- const l2ProofClient = config.l2ProofRpcUrl
1555
- ? createJinnPublicClient(config.l2ProofRpcUrl, NETWORK_CHAIN)
1595
+ const l2ProofClient = config.l2ProofRpcUrls
1596
+ ? createJinnPublicClient(config.l2ProofRpcUrls, NETWORK_CHAIN)
1556
1597
  : undefined;
1557
- const agentClients = createClients(config.rpcUrl, agentPrivateKey, agentChain);
1598
+ const agentClients = createClients(config.rpcUrls, agentPrivateKey, agentChain);
1558
1599
  // ── L1 (Sepolia / Ethereum mainnet) clients for cross-chain JINN claim loop ──
1559
1600
  // Uses the agent EOA because MockMessenger.owner is the agent on testnet.
1560
1601
  // Same key as L2; only the chain differs.
@@ -1565,10 +1606,10 @@ export async function main() {
1565
1606
  distributorAddress: JINN_MVI_CONFIG.distributor,
1566
1607
  ethereumRpcUrl: config.ethereumRpcUrl,
1567
1608
  });
1568
- const l1ClientsForJinnClaim = shouldWireJinnClaimL1 && config.ethereumRpcUrl
1609
+ const l1ClientsForJinnClaim = shouldWireJinnClaimL1 && config.ethereumRpcUrls
1569
1610
  ? {
1570
- public: createJinnL1PublicClient(config.ethereumRpcUrl, config.jinnL1Network),
1571
- wallet: createJinnL1WalletClient(config.ethereumRpcUrl, config.jinnL1Network, privateKeyToAccount(agentPrivateKey)),
1611
+ public: createJinnL1PublicClient(config.ethereumRpcUrls, config.jinnL1Network),
1612
+ wallet: createJinnL1WalletClient(config.ethereumRpcUrls, config.jinnL1Network, privateKeyToAccount(agentPrivateKey)),
1572
1613
  }
1573
1614
  : undefined;
1574
1615
  const jinnClaimLoopConfig = buildJinnClaimLoopConfig({
@@ -2029,6 +2070,7 @@ export async function main() {
2029
2070
  agentEoa: agentEoaAddress,
2030
2071
  safeAddress,
2031
2072
  agentPrivateKey,
2073
+ ...(sharedDiscoveryApi ? { discoveryApi: sharedDiscoveryApi } : {}),
2032
2074
  },
2033
2075
  logger: {
2034
2076
  info: (message) => console.log(message),
@@ -2096,6 +2138,21 @@ export async function main() {
2096
2138
  console.warn('[main] Corpus disabled (no DiscoveryAPI or on-chain identity registry); ' +
2097
2139
  'MCP record lookup and artifact acquisition network branches will be unavailable.');
2098
2140
  }
2141
+ const spendCap = buildSpendCapConfig(config, process.env);
2142
+ const aiUnits = buildAiUnitsConfig(config, process.env);
2143
+ if (aiUnits) {
2144
+ // Surface the resolved AI-units cap so an operator inspecting logs can
2145
+ // distinguish the baked-in default (100/2800) from a deliberate
2146
+ // `JINN_AI_UNITS_CEILING_OVERRIDE` raise (e.g. 10000/280000 in CI).
2147
+ // Source reflects the actual outcome: a malformed override falls back
2148
+ // to default and emits its own warn from resolveReferenceCeiling.
2149
+ const overrideSet = typeof process.env['JINN_AI_UNITS_CEILING_OVERRIDE'] === 'string' &&
2150
+ process.env['JINN_AI_UNITS_CEILING_OVERRIDE'].trim() !== '';
2151
+ const matchesDefault = aiUnits.capPerBlock === REFERENCE_CEILING.units_per_block &&
2152
+ aiUnits.capPerWeek === REFERENCE_CEILING.units_per_week;
2153
+ const source = overrideSet && !matchesDefault ? 'env' : 'default';
2154
+ console.log(`[ai-units] cap=${aiUnits.capPerBlock}/${aiUnits.capPerWeek} per (block, week) source=${source}`);
2155
+ }
2099
2156
  const daemon = new Daemon({
2100
2157
  adapter,
2101
2158
  runner,
@@ -2112,6 +2169,8 @@ export async function main() {
2112
2169
  creatorSafeAddress: safeAddress,
2113
2170
  corpusFactory,
2114
2171
  harnessReadinessRegistry,
2172
+ spendCap,
2173
+ aiUnits,
2115
2174
  status: {
2116
2175
  earningDir: config.earningDir,
2117
2176
  rpcUrl: config.rpcUrl,
@@ -2121,6 +2180,11 @@ export async function main() {
2121
2180
  tjinnTokenAddress: JINN_MVI_CONFIG.jinn,
2122
2181
  tjinnChainId: JINN_MVI_CONFIG.l1ChainId,
2123
2182
  tjinnDistributorAddress: JINN_MVI_CONFIG.distributor,
2183
+ // stOLAS L2 distributor — mirrors `CHAIN_CONFIG.distributorAddress`
2184
+ // used to gate the EvictionLoop (issue #651). Threaded through so the
2185
+ // SPA's autoRestake predicate keys off the same on-chain artifact as
2186
+ // the daemon's `evictionCheck` predicate (~line 2520 below).
2187
+ stOlasDistributorAddress: CHAIN_CONFIG.distributorAddress,
2124
2188
  network: config.network,
2125
2189
  pollIntervalMs: config.pollIntervalMs,
2126
2190
  masterEthDailyEstimateWei: config.masterEthDailyEstimateWei,
@@ -2132,6 +2196,8 @@ export async function main() {
2132
2196
  engine: config.engine,
2133
2197
  config,
2134
2198
  configPath: CONFIG_PATH ?? DEFAULT_CONFIG_PATH,
2199
+ spendCaps: spendCap?.caps,
2200
+ aiUnits,
2135
2201
  },
2136
2202
  rewardClaim: config.rewardClaimIntervalMs > 0
2137
2203
  ? {
@@ -2244,10 +2310,15 @@ export async function main() {
2244
2310
  }
2245
2311
  : undefined,
2246
2312
  });
2247
- // Write pidfile so `jinn stop` can find us.
2313
+ // Write pidfile so `jinn stop` can find us. First, refuse the run if another
2314
+ // daemon already owns this earning directory — see issue #649. The gate
2315
+ // handles all three branches (refuse-and-exit, unlink-stale-and-continue,
2316
+ // proceed); the writeFileSync below MUST stay outside the helper so the
2317
+ // "// DO NOT add store mutations above this line — see #649" invariant is
2318
+ // visible right here at the call site.
2248
2319
  const pidPath = join(config.earningDir, 'daemon.pid');
2249
- const { writeFileSync, unlinkSync } = await import('node:fs');
2250
- writeFileSync(pidPath, String(process.pid) + '\n', 'utf-8');
2320
+ applyPidfileLivenessGate(pidPath);
2321
+ writeFileSyncMain(pidPath, String(process.pid) + '\n', 'utf-8');
2251
2322
  const removePidfile = () => {
2252
2323
  try {
2253
2324
  unlinkSync(pidPath);
@@ -2285,6 +2356,8 @@ export async function main() {
2285
2356
  catch {
2286
2357
  /* ignore */
2287
2358
  }
2359
+ // Issue #420: flush + close the rotating daemon file logger.
2360
+ closeFileLogger();
2288
2361
  }
2289
2362
  console.log('[main] Shutdown complete.');
2290
2363
  process.exit(exitCode);