@jinn-network/client 0.1.9-canary.5c19fc6d → 0.1.9-canary.5ff3d8cb

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 (295) hide show
  1. package/CONTRIBUTING.md +2 -2
  2. package/dist/adapters/mech/adapter.d.ts +10 -0
  3. package/dist/adapters/mech/adapter.js +19 -1
  4. package/dist/adapters/mech/adapter.js.map +1 -1
  5. package/dist/adapters/mech/types.d.ts +1 -88
  6. package/dist/adapters/mech/types.js +1 -45
  7. package/dist/adapters/mech/types.js.map +1 -1
  8. package/dist/api/bootstrap-endpoint.d.ts +18 -3
  9. package/dist/api/bootstrap-endpoint.js +3 -0
  10. package/dist/api/bootstrap-endpoint.js.map +1 -1
  11. package/dist/api/gather-status.js +6 -5
  12. package/dist/api/gather-status.js.map +1 -1
  13. package/dist/api/launcher-endpoints.js +6 -1
  14. package/dist/api/launcher-endpoints.js.map +1 -1
  15. package/dist/api/launcher-status.d.ts +2 -0
  16. package/dist/api/launcher-status.js.map +1 -1
  17. package/dist/api/launcher-tasks.d.ts +47 -0
  18. package/dist/api/launcher-tasks.js +88 -3
  19. package/dist/api/launcher-tasks.js.map +1 -1
  20. package/dist/api/loop-completion-build.d.ts +2 -2
  21. package/dist/api/loop-completion-build.js +2 -3
  22. package/dist/api/loop-completion-build.js.map +1 -1
  23. package/dist/api/portfolio-v0-build.d.ts +2 -1
  24. package/dist/api/portfolio-v0-build.js +5 -7
  25. package/dist/api/portfolio-v0-build.js.map +1 -1
  26. package/dist/api/prediction-v1-build.d.ts +2 -2
  27. package/dist/api/prediction-v1-build.js +5 -7
  28. package/dist/api/prediction-v1-build.js.map +1 -1
  29. package/dist/api/setup-endpoints.d.ts +4 -0
  30. package/dist/api/setup-endpoints.js +13 -7
  31. package/dist/api/setup-endpoints.js.map +1 -1
  32. package/dist/api/status-build.js +1 -4
  33. package/dist/api/status-build.js.map +1 -1
  34. package/dist/api/task-run-routing.d.ts +1 -1
  35. package/dist/api/task-runs-build.d.ts +2 -2
  36. package/dist/api/task-runs-build.js +5 -7
  37. package/dist/api/task-runs-build.js.map +1 -1
  38. package/dist/bin/jinn-distill-mcp.js +813 -0
  39. package/dist/bin/jinn-layer.js +4992 -1151
  40. package/dist/build-info.json +4 -4
  41. package/dist/build-meta.json +1 -1
  42. package/dist/captures/distil-export.d.ts +54 -0
  43. package/dist/captures/distil-export.js +135 -0
  44. package/dist/captures/distil-export.js.map +1 -0
  45. package/dist/captures/ingest.d.ts +21 -0
  46. package/dist/captures/ingest.js +144 -0
  47. package/dist/captures/ingest.js.map +1 -0
  48. package/dist/captures/live-publisher.js +4 -3
  49. package/dist/captures/live-publisher.js.map +1 -1
  50. package/dist/captures/publish.d.ts +4 -0
  51. package/dist/captures/publish.js +2 -2
  52. package/dist/captures/publish.js.map +1 -1
  53. package/dist/cli/execution-context.js +2 -1
  54. package/dist/cli/execution-context.js.map +1 -1
  55. package/dist/config.js +34 -1
  56. package/dist/config.js.map +1 -1
  57. package/dist/contracts/abis.d.ts +100 -0
  58. package/dist/contracts/abis.js +58 -0
  59. package/dist/contracts/abis.js.map +1 -0
  60. package/dist/contracts/addresses.d.ts +36 -0
  61. package/dist/contracts/addresses.js +60 -0
  62. package/dist/contracts/addresses.js.map +1 -0
  63. package/dist/corpus/onchain-query.d.ts +0 -1
  64. package/dist/corpus/onchain-query.js +2 -5
  65. package/dist/corpus/onchain-query.js.map +1 -1
  66. package/dist/daemon/balance-topup-loop.js +27 -12
  67. package/dist/daemon/balance-topup-loop.js.map +1 -1
  68. package/dist/daemon/creator.js +15 -13
  69. package/dist/daemon/creator.js.map +1 -1
  70. package/dist/daemon/daemon.js +35 -13
  71. package/dist/daemon/daemon.js.map +1 -1
  72. package/dist/daemon/loop-heartbeat.d.ts +62 -7
  73. package/dist/daemon/loop-heartbeat.js +50 -13
  74. package/dist/daemon/loop-heartbeat.js.map +1 -1
  75. package/dist/{api/peers.js → daemon/peer-sync.js} +2 -2
  76. package/dist/daemon/peer-sync.js.map +1 -0
  77. package/dist/daemon/reward-claim-loop.js +27 -12
  78. package/dist/daemon/reward-claim-loop.js.map +1 -1
  79. package/dist/daemon/spend-cap-gate.d.ts +0 -6
  80. package/dist/daemon/spend-cap-gate.js +1 -8
  81. package/dist/daemon/spend-cap-gate.js.map +1 -1
  82. package/dist/dashboard/assets/index-BdGCkGPF.js +157 -0
  83. package/dist/dashboard/assets/index-D7rvJRNa.css +1 -0
  84. package/dist/dashboard/index.html +2 -2
  85. package/dist/discovery/http.js +83 -1
  86. package/dist/discovery/http.js.map +1 -1
  87. package/dist/discovery/onchain.js +16 -8
  88. package/dist/discovery/onchain.js.map +1 -1
  89. package/dist/discovery/types.d.ts +43 -0
  90. package/dist/discovery/types.js.map +1 -1
  91. package/dist/discovery/with-fallback.js +10 -0
  92. package/dist/discovery/with-fallback.js.map +1 -1
  93. package/dist/earning/bootstrap-run.d.ts +25 -0
  94. package/dist/earning/bootstrap-run.js +315 -0
  95. package/dist/earning/bootstrap-run.js.map +1 -0
  96. package/dist/earning/bootstrap.d.ts +6 -11
  97. package/dist/earning/bootstrap.js +45 -195
  98. package/dist/earning/bootstrap.js.map +1 -1
  99. package/dist/earning/contracts.d.ts +2 -3
  100. package/dist/earning/contracts.js +12 -21
  101. package/dist/earning/contracts.js.map +1 -1
  102. package/dist/earning/master-gas.d.ts +10 -0
  103. package/dist/earning/master-gas.js +11 -0
  104. package/dist/earning/master-gas.js.map +1 -0
  105. package/dist/earning/safe-adapter.js +1 -45
  106. package/dist/earning/safe-adapter.js.map +1 -1
  107. package/dist/earning/steps/context.d.ts +42 -0
  108. package/dist/earning/steps/context.js +4 -0
  109. package/dist/earning/steps/context.js.map +1 -0
  110. package/dist/earning/steps/fleet-identity-register.d.ts +4 -0
  111. package/dist/earning/steps/fleet-identity-register.js +65 -0
  112. package/dist/earning/steps/fleet-identity-register.js.map +1 -0
  113. package/dist/earning/steps/fleet-safe-deploy.d.ts +4 -0
  114. package/dist/earning/steps/fleet-safe-deploy.js +62 -0
  115. package/dist/earning/steps/fleet-safe-deploy.js.map +1 -0
  116. package/dist/earning/steps/fleet-safe-predict.d.ts +4 -0
  117. package/dist/earning/steps/fleet-safe-predict.js +18 -0
  118. package/dist/earning/steps/fleet-safe-predict.js.map +1 -0
  119. package/dist/earning/steps/receipt-parsing.d.ts +12 -0
  120. package/dist/earning/steps/receipt-parsing.js +71 -0
  121. package/dist/earning/steps/receipt-parsing.js.map +1 -0
  122. package/dist/earning/stolas-staking.js +20 -14
  123. package/dist/earning/stolas-staking.js.map +1 -1
  124. package/dist/erc8004/addresses.d.ts +6 -5
  125. package/dist/erc8004/addresses.js +7 -5
  126. package/dist/erc8004/addresses.js.map +1 -1
  127. package/dist/erc8004/identity.d.ts +12 -1
  128. package/dist/erc8004/identity.js +31 -0
  129. package/dist/erc8004/identity.js.map +1 -1
  130. package/dist/erc8004/index.d.ts +1 -1
  131. package/dist/erc8004/index.js +1 -1
  132. package/dist/erc8004/index.js.map +1 -1
  133. package/dist/erc8004/reputation.js +16 -12
  134. package/dist/erc8004/reputation.js.map +1 -1
  135. package/dist/erc8004/validation.js +5 -4
  136. package/dist/erc8004/validation.js.map +1 -1
  137. package/dist/eval/capability-slate.d.ts +54 -0
  138. package/dist/eval/capability-slate.js +116 -0
  139. package/dist/eval/capability-slate.js.map +1 -0
  140. package/dist/eval/capability-stats.d.ts +39 -0
  141. package/dist/eval/capability-stats.js +123 -0
  142. package/dist/eval/capability-stats.js.map +1 -0
  143. package/dist/eval/contested-band.d.ts +18 -0
  144. package/dist/eval/contested-band.js +19 -0
  145. package/dist/eval/contested-band.js.map +1 -0
  146. package/dist/eval/corpus-index.d.ts +21 -0
  147. package/dist/eval/corpus-index.js +55 -0
  148. package/dist/eval/corpus-index.js.map +1 -0
  149. package/dist/eval/disjointness.d.ts +26 -0
  150. package/dist/eval/disjointness.js +67 -0
  151. package/dist/eval/disjointness.js.map +1 -0
  152. package/dist/eval/mcnemar-power.d.ts +14 -0
  153. package/dist/eval/mcnemar-power.js +40 -0
  154. package/dist/eval/mcnemar-power.js.map +1 -0
  155. package/dist/harnesses/engine/engine.d.ts +2 -1
  156. package/dist/harnesses/engine/engine.js +15 -2
  157. package/dist/harnesses/engine/engine.js.map +1 -1
  158. package/dist/harnesses/engine/persistence.d.ts +2 -61
  159. package/dist/harnesses/engine/persistence.js.map +1 -1
  160. package/dist/harnesses/impls/_evaluator-base.d.ts +48 -0
  161. package/dist/harnesses/impls/_evaluator-base.js +35 -0
  162. package/dist/harnesses/impls/_evaluator-base.js.map +1 -0
  163. package/dist/harnesses/impls/claude-mcp-prediction/index.d.ts +2 -3
  164. package/dist/harnesses/impls/claude-mcp-prediction/index.js +29 -99
  165. package/dist/harnesses/impls/claude-mcp-prediction/index.js.map +1 -1
  166. package/dist/harnesses/impls/claude-mcp-prediction/mcp-tools.js +4 -21
  167. package/dist/harnesses/impls/claude-mcp-prediction/mcp-tools.js.map +1 -1
  168. package/dist/harnesses/impls/claude-mcp-prediction/session-orchestrator.d.ts +2 -0
  169. package/dist/harnesses/impls/claude-mcp-prediction/session-orchestrator.js +1 -1
  170. package/dist/harnesses/impls/claude-mcp-prediction/session-orchestrator.js.map +1 -1
  171. package/dist/harnesses/impls/claude-mcp-prediction-apy/index.js +30 -79
  172. package/dist/harnesses/impls/claude-mcp-prediction-apy/index.js.map +1 -1
  173. package/dist/harnesses/impls/claude-mcp-prediction-apy/mcp-tools.js +4 -19
  174. package/dist/harnesses/impls/claude-mcp-prediction-apy/mcp-tools.js.map +1 -1
  175. package/dist/harnesses/impls/claude-mcp-prediction-apy/session-orchestrator.d.ts +2 -0
  176. package/dist/harnesses/impls/claude-mcp-prediction-apy/session-orchestrator.js +1 -1
  177. package/dist/harnesses/impls/claude-mcp-prediction-apy/session-orchestrator.js.map +1 -1
  178. package/dist/harnesses/impls/claude-mcp-shared/mcp-server-script.d.ts +39 -0
  179. package/dist/harnesses/impls/claude-mcp-shared/mcp-server-script.js +62 -0
  180. package/dist/harnesses/impls/claude-mcp-shared/mcp-server-script.js.map +1 -0
  181. package/dist/harnesses/impls/claude-mcp-shared/mcp-server.d.ts +40 -0
  182. package/dist/harnesses/impls/claude-mcp-shared/mcp-server.js +44 -0
  183. package/dist/harnesses/impls/claude-mcp-shared/mcp-server.js.map +1 -0
  184. package/dist/harnesses/impls/claude-mcp-shared/single-session-harness.d.ts +56 -0
  185. package/dist/harnesses/impls/claude-mcp-shared/single-session-harness.js +79 -0
  186. package/dist/harnesses/impls/claude-mcp-shared/single-session-harness.js.map +1 -0
  187. package/dist/harnesses/impls/learner/adapters/codex-code.d.ts +3 -1
  188. package/dist/harnesses/impls/learner/adapters/codex-code.js +39 -4
  189. package/dist/harnesses/impls/learner/adapters/codex-code.js.map +1 -1
  190. package/dist/harnesses/impls/portfolio-v0-evaluator/index.d.ts +5 -15
  191. package/dist/harnesses/impls/portfolio-v0-evaluator/index.js +10 -29
  192. package/dist/harnesses/impls/portfolio-v0-evaluator/index.js.map +1 -1
  193. package/dist/harnesses/impls/prediction-apy-v0-evaluator/index.d.ts +5 -15
  194. package/dist/harnesses/impls/prediction-apy-v0-evaluator/index.js +10 -23
  195. package/dist/harnesses/impls/prediction-apy-v0-evaluator/index.js.map +1 -1
  196. package/dist/harnesses/impls/prediction-v0-evaluator/index.d.ts +5 -15
  197. package/dist/harnesses/impls/prediction-v0-evaluator/index.js +10 -25
  198. package/dist/harnesses/impls/prediction-v0-evaluator/index.js.map +1 -1
  199. package/dist/harnesses/impls/swe-rebench-v2-evaluator/eval-runner.js +8 -0
  200. package/dist/harnesses/impls/swe-rebench-v2-evaluator/eval-runner.js.map +1 -1
  201. package/dist/learner/verification-gate.d.ts +53 -0
  202. package/dist/learner/verification-gate.js +80 -0
  203. package/dist/learner/verification-gate.js.map +1 -0
  204. package/dist/main.js +74 -457
  205. package/dist/main.js.map +1 -1
  206. package/dist/monitoring/net-liveness.d.ts +143 -0
  207. package/dist/monitoring/net-liveness.js +301 -0
  208. package/dist/monitoring/net-liveness.js.map +1 -0
  209. package/dist/observability/progress.d.ts +11 -0
  210. package/dist/observability/progress.js +16 -0
  211. package/dist/observability/progress.js.map +1 -0
  212. package/dist/pilot/cost.d.ts +19 -0
  213. package/dist/pilot/cost.js +31 -0
  214. package/dist/pilot/cost.js.map +1 -0
  215. package/dist/pilot/instance.d.ts +20 -0
  216. package/dist/pilot/instance.js +19 -0
  217. package/dist/pilot/instance.js.map +1 -0
  218. package/dist/pilot/repo.d.ts +31 -0
  219. package/dist/pilot/repo.js +42 -0
  220. package/dist/pilot/repo.js.map +1 -0
  221. package/dist/pilot/solve.d.ts +22 -0
  222. package/dist/pilot/solve.js +37 -0
  223. package/dist/pilot/solve.js.map +1 -0
  224. package/dist/pilot/tally.d.ts +35 -0
  225. package/dist/pilot/tally.js +61 -0
  226. package/dist/pilot/tally.js.map +1 -0
  227. package/dist/plugins/local-trace-distiller/.claude-plugin/plugin.json +9 -0
  228. package/dist/plugins/local-trace-distiller/.codex-plugin/plugin.json +41 -0
  229. package/dist/plugins/local-trace-distiller/.mcp.json +8 -0
  230. package/dist/plugins/local-trace-distiller/README.md +27 -0
  231. package/dist/plugins/local-trace-distiller/jinn.plugin.json +36 -0
  232. package/dist/plugins/local-trace-distiller/skills/distill/SKILL.md +51 -0
  233. package/dist/preflight/rpc-network.d.ts +10 -3
  234. package/dist/preflight/rpc-network.js +46 -13
  235. package/dist/preflight/rpc-network.js.map +1 -1
  236. package/dist/preflight/stable-cwd.d.ts +29 -0
  237. package/dist/preflight/stable-cwd.js +98 -0
  238. package/dist/preflight/stable-cwd.js.map +1 -0
  239. package/dist/solvernets/launched-record-dispatcher.js +6 -0
  240. package/dist/solvernets/launched-record-dispatcher.js.map +1 -1
  241. package/dist/spend/credential.d.ts +2 -2
  242. package/dist/spend/credential.js +9 -3
  243. package/dist/spend/credential.js.map +1 -1
  244. package/dist/spend/spend-cap.d.ts +10 -0
  245. package/dist/spend/spend-cap.js +13 -0
  246. package/dist/spend/spend-cap.js.map +1 -0
  247. package/dist/store/store.d.ts +14 -0
  248. package/dist/store/store.js +10 -1
  249. package/dist/store/store.js.map +1 -1
  250. package/dist/trajectory/processors/identity-scrub.js +22 -3
  251. package/dist/trajectory/processors/identity-scrub.js.map +1 -1
  252. package/dist/trajectory/scrub/build.d.ts +19 -0
  253. package/dist/trajectory/scrub/build.js +25 -0
  254. package/dist/trajectory/scrub/build.js.map +1 -1
  255. package/dist/trajectory/scrub/layer2.d.ts +23 -0
  256. package/dist/trajectory/scrub/layer2.js +33 -0
  257. package/dist/trajectory/scrub/layer2.js.map +1 -0
  258. package/dist/trajectory/scrub/openredaction-stage.d.ts +127 -0
  259. package/dist/trajectory/scrub/openredaction-stage.js +186 -2
  260. package/dist/trajectory/scrub/openredaction-stage.js.map +1 -1
  261. package/dist/trajectory/scrub/pipeline.d.ts +21 -0
  262. package/dist/trajectory/scrub/pipeline.js +57 -0
  263. package/dist/trajectory/scrub/pipeline.js.map +1 -1
  264. package/dist/trajectory/scrub/plain-patterns-stage.d.ts +14 -1
  265. package/dist/trajectory/scrub/plain-patterns-stage.js +35 -5
  266. package/dist/trajectory/scrub/plain-patterns-stage.js.map +1 -1
  267. package/dist/trajectory/scrub/secretlint-stage.d.ts +22 -3
  268. package/dist/trajectory/scrub/secretlint-stage.js +118 -27
  269. package/dist/trajectory/scrub/secretlint-stage.js.map +1 -1
  270. package/dist/trajectory/transcript-watcher.d.ts +26 -0
  271. package/dist/trajectory/transcript-watcher.js +33 -0
  272. package/dist/trajectory/transcript-watcher.js.map +1 -1
  273. package/dist/types/skill-artifact.d.ts +442 -0
  274. package/dist/types/skill-artifact.js +137 -0
  275. package/dist/types/skill-artifact.js.map +1 -0
  276. package/dist/types/task-run-read-model.d.ts +21 -0
  277. package/dist/types/task-run-read-model.js +2 -0
  278. package/dist/types/task-run-read-model.js.map +1 -0
  279. package/dist/types/task-run.d.ts +75 -0
  280. package/dist/types/task-run.js +2 -0
  281. package/dist/types/task-run.js.map +1 -0
  282. package/dist/util/redact-rpc-urls.d.ts +1 -1
  283. package/dist/util/redact-rpc-urls.js +57 -2
  284. package/dist/util/redact-rpc-urls.js.map +1 -1
  285. package/package.json +11 -8
  286. package/plugins/local-trace-distiller/.claude-plugin/plugin.json +9 -0
  287. package/plugins/local-trace-distiller/.codex-plugin/plugin.json +41 -0
  288. package/plugins/local-trace-distiller/.mcp.json +8 -0
  289. package/plugins/local-trace-distiller/README.md +27 -0
  290. package/plugins/local-trace-distiller/jinn.plugin.json +36 -0
  291. package/plugins/local-trace-distiller/skills/distill/SKILL.md +51 -0
  292. package/dist/api/peers.js.map +0 -1
  293. package/dist/dashboard/assets/index-BsrAAmvC.js +0 -171
  294. package/dist/dashboard/assets/index-DQOWJ2SF.css +0 -1
  295. /package/dist/{api/peers.d.ts → daemon/peer-sync.d.ts} +0 -0
@@ -0,0 +1,301 @@
1
+ /**
2
+ * Net-liveness probe — operator-independent detector for the #1038 silent-stall
3
+ * class.
4
+ *
5
+ * Context: when the shared indexer blips, every operator daemon's discovery
6
+ * loops can wedge while the indexer-independent loops (jinn-claim, balance-topup)
7
+ * keep emitting on-chain activity and mask the outage. No single operator can
8
+ * be trusted to notice, so liveness must be observed from *outside* any daemon.
9
+ *
10
+ * This module reads on-chain truth two ways and cross-references them:
11
+ * - chain head — direct RPC `getBlockNumber()` (always live)
12
+ * - latest indexed attempt/verdict block — indexer GraphQL
13
+ * - indexer head — indexer `/status` (the indexer's own indexed head)
14
+ *
15
+ * The core decision is a pure function (`classifyNetLiveness`). The orchestrator
16
+ * (`runNetLivenessProbe`) injects all I/O so the whole flow is testable with no
17
+ * network. Designed to run from a stateless cron entry script
18
+ * (`scripts/net-liveness-probe.ts`), NOT in-daemon.
19
+ */
20
+ // ── Pure classifier ─────────────────────────────────────────────────────────
21
+ /**
22
+ * Base produces ~one block every 2s → 30 blocks per minute. The probe works in
23
+ * block-space (the schema carries `createdAtBlock`, no timestamp column), so the
24
+ * minute threshold is converted to blocks with this constant.
25
+ */
26
+ export const BASE_BLOCKS_PER_MINUTE = 30;
27
+ /** Convert a minute threshold to a Base block-count. */
28
+ export function minutesToThresholdBlocks(minutes) {
29
+ return minutes * BASE_BLOCKS_PER_MINUTE;
30
+ }
31
+ /**
32
+ * Decide net-liveness from the four cross-referenced reads. PURE — no I/O.
33
+ *
34
+ * Decision order matters: only the `stale` state alerts. Each preceding state is
35
+ * a confound that would otherwise look like a stall but isn't a *net* stall (a
36
+ * down/lagging indexer or a halted chain is reported, not alerted).
37
+ */
38
+ export function classifyNetLiveness(inputs) {
39
+ const { chainHeadBlock, prevChainHeadBlock, latestActivityBlock, indexerHeadBlock, thresholdBlocks } = inputs;
40
+ const threshold = BigInt(thresholdBlocks);
41
+ const rawChainStaleForBlocks = chainHeadBlock - (latestActivityBlock ?? 0n);
42
+ const chainStaleForBlocks = rawChainStaleForBlocks < 0n ? 0n : rawChainStaleForBlocks;
43
+ // 1. Indexer unreachable — we have no indexed-activity truth to compare.
44
+ if (indexerHeadBlock === null) {
45
+ return {
46
+ state: 'indexer-down',
47
+ staleForBlocks: chainStaleForBlocks,
48
+ reason: 'indexer /status unreachable; cannot cross-reference indexed activity',
49
+ };
50
+ }
51
+ // 2. Indexer reachable but far behind chain head — its activity reads are
52
+ // stale-by-construction, so absence of recent activity proves nothing.
53
+ const indexerLagForBlocks = chainHeadBlock - indexerHeadBlock;
54
+ if (indexerLagForBlocks > threshold) {
55
+ return {
56
+ state: 'indexer-lagging',
57
+ staleForBlocks: chainStaleForBlocks,
58
+ reason: `indexer head ${indexerHeadBlock} is ${indexerLagForBlocks} blocks behind chain head ${chainHeadBlock}`,
59
+ };
60
+ }
61
+ // 3. Chain head did not advance between the two reads — a halted chain has no
62
+ // new blocks to carry activity, so this is not a net stall.
63
+ if (prevChainHeadBlock !== null && chainHeadBlock <= prevChainHeadBlock) {
64
+ return {
65
+ state: 'chain-halted',
66
+ staleForBlocks: chainStaleForBlocks,
67
+ reason: `chain head did not advance (${prevChainHeadBlock} → ${chainHeadBlock})`,
68
+ };
69
+ }
70
+ const rawIndexedStaleForBlocks = indexerHeadBlock - (latestActivityBlock ?? 0n);
71
+ const staleForBlocks = rawIndexedStaleForBlocks < 0n ? 0n : rawIndexedStaleForBlocks;
72
+ // 4. Chain advancing + indexer usable, but no recent indexed activity
73
+ // relative to the indexed head → the #1038 silent-stall signature. ALERT.
74
+ if (latestActivityBlock === null || staleForBlocks > threshold) {
75
+ return {
76
+ state: 'stale',
77
+ staleForBlocks,
78
+ reason: latestActivityBlock === null
79
+ ? 'no indexed attempt/verdict found at all'
80
+ : `last indexed activity at block ${latestActivityBlock} is ${staleForBlocks} blocks behind indexer head ${indexerHeadBlock}`,
81
+ };
82
+ }
83
+ // 5. Recent activity within threshold.
84
+ return {
85
+ state: 'healthy',
86
+ staleForBlocks,
87
+ reason: `last indexed activity ${staleForBlocks} blocks behind indexer head (under ${thresholdBlocks})`,
88
+ };
89
+ }
90
+ /** Default delay between the two chain-head samples (ms). See headSampleDelayMs. */
91
+ export const DEFAULT_HEAD_SAMPLE_DELAY_MS = 4_000;
92
+ export function parseNetLivenessIntegerEnv(raw, spec) {
93
+ if (raw === undefined)
94
+ return spec.defaultValue;
95
+ const trimmed = raw.trim();
96
+ const fail = () => {
97
+ throw new Error(`${spec.name} must be an integer between ${spec.min} and ${spec.max}`);
98
+ };
99
+ if (!/^[0-9]+$/.test(trimmed))
100
+ fail();
101
+ const value = Number(trimmed);
102
+ if (!Number.isSafeInteger(value) || value < spec.min || value > spec.max)
103
+ fail();
104
+ return value;
105
+ }
106
+ /**
107
+ * Run one probe: read chain head twice (to detect advancement within the run),
108
+ * read the indexer head and latest activity (tolerating throws as
109
+ * indexer-down), classify, and POST an alert only when the state is `stale` and
110
+ * a webhook is configured. Never throws on a read failure; returns the
111
+ * classification for the caller to log. Webhook delivery failures still throw
112
+ * so cron can flag the alert path itself as broken.
113
+ */
114
+ export async function runNetLivenessProbe(deps) {
115
+ // Sample the chain head twice, separated by a real delay, so a healthy chain
116
+ // has time to mint a new block between reads. Without the gap both reads land
117
+ // in the same block (and viem caches getBlockNumber for ~4s), making the two
118
+ // samples identical → the classifier would always read `chain-halted` and the
119
+ // alert branch would be unreachable.
120
+ const prevChainHeadBlock = await deps.fetchChainHead();
121
+ await deps.sleep(deps.headSampleDelayMs ?? DEFAULT_HEAD_SAMPLE_DELAY_MS);
122
+ const chainHeadBlock = await deps.fetchChainHead();
123
+ // A throw on either indexer read means the indexer is unhealthy — we cannot
124
+ // cross-reference indexed activity, so the run reports indexer-down rather than
125
+ // crashing or mistaking an error for a genuine stall. Distinguish a *throw* (the
126
+ // reader itself failed) from a clean null (the indexer answered "no rows"): only
127
+ // the former is indexer-down. A failed activity read therefore forces the
128
+ // indexer head to be treated as unreadable too, so the classifier short-circuits
129
+ // to indexer-down (decision-order step 1) before it can read the empty activity
130
+ // as `stale`.
131
+ const indexerHead = await safeRead(deps.fetchIndexerHeadBlock);
132
+ const activity = await safeRead(deps.fetchLatestActivityBlock);
133
+ const indexerHeadBlock = indexerHead.threw || activity.threw ? null : indexerHead.value;
134
+ const latestActivityBlock = activity.value;
135
+ const result = classifyNetLiveness({
136
+ chainHeadBlock,
137
+ prevChainHeadBlock,
138
+ latestActivityBlock,
139
+ indexerHeadBlock,
140
+ thresholdBlocks: minutesToThresholdBlocks(deps.thresholdMinutes),
141
+ });
142
+ if (result.state === 'stale' && deps.postWebhook) {
143
+ const staleForMinutes = Math.round(Number(result.staleForBlocks) / BASE_BLOCKS_PER_MINUTE);
144
+ const runAt = deps.now().toISOString();
145
+ const payload = {
146
+ text: `Jinn net-liveness alert: no on-chain attempt/verdict indexed for ` +
147
+ `~${staleForMinutes} min (${result.staleForBlocks} blocks). ` +
148
+ `Chain head ${chainHeadBlock} is advancing and indexed activity is stale relative to indexer head ${indexerHeadBlock}, ` +
149
+ `so this is a network stall, not an indexer outage. ${result.reason}`,
150
+ state: result.state,
151
+ staleForBlocks: result.staleForBlocks.toString(),
152
+ staleForMinutes,
153
+ chainHeadBlock: chainHeadBlock.toString(),
154
+ latestActivityBlock: latestActivityBlock === null ? null : latestActivityBlock.toString(),
155
+ runAt,
156
+ };
157
+ await deps.postWebhook(payload);
158
+ }
159
+ return result;
160
+ }
161
+ async function safeRead(read) {
162
+ try {
163
+ return { value: await read(), threw: false };
164
+ }
165
+ catch {
166
+ return { value: null, threw: true };
167
+ }
168
+ }
169
+ // ── Indexer readers ──────────────────────────────────────────────────────────
170
+ /**
171
+ * Per-request timeout for every indexer fetch. Mirrors http.ts: a never-settling
172
+ * fetch (half-open socket mid-redeploy) is bounded so a hang becomes a bounded
173
+ * failure, not a wedged probe.
174
+ */
175
+ const FETCH_TIMEOUT_MS = 15_000;
176
+ /**
177
+ * Read the indexer's own indexed head via Ponder's host-root `/status` endpoint.
178
+ * `/status` returns `{ <chainName>: { id, block: { number, timestamp } } }`.
179
+ * Select the monitored chain by explicit name, falling back to chain ID when
180
+ * the status key does not match. Returns null on failure or shape mismatch —
181
+ * the probe classifies null as indexer-down.
182
+ */
183
+ export async function fetchIndexerHeadBlock(args) {
184
+ const fetchImpl = args.fetchImpl ?? globalThis.fetch;
185
+ // `/status` is served at the host root, not under `/graphql` (mirror http.ts).
186
+ const statusUrl = `${args.baseUrl.replace(/\/graphql\/?$/, '').replace(/\/$/, '')}/status`;
187
+ try {
188
+ const res = await fetchImpl(statusUrl, { signal: AbortSignal.timeout(FETCH_TIMEOUT_MS) });
189
+ if (!res.ok)
190
+ return null;
191
+ const body = (await res.json());
192
+ const chain = body[args.chainName] ??
193
+ Object.values(body).find((entry) => Number(entry?.id) === args.chainId);
194
+ return parseBlockNumber(chain?.block?.number);
195
+ }
196
+ catch {
197
+ return null;
198
+ }
199
+ }
200
+ /**
201
+ * Read the newest indexed activity block — the max `createdAtBlock` across the
202
+ * latest verdict and the latest attempt on the monitored chain (NOT task: a
203
+ * posted-but-unclaimed task is itself the stall condition). Two `limit:1`
204
+ * descending GraphQL queries. Returns null only when both legs are clean empty
205
+ * result sets. Throws on transport,
206
+ * HTTP, GraphQL, or malformed-response failures so the orchestrator can classify
207
+ * those as indexer-down instead of a false net-stall page.
208
+ */
209
+ export async function fetchLatestActivityBlock(args) {
210
+ const [verdict, attempt] = await Promise.all([
211
+ latestBlockFor(args, 'verdicts'),
212
+ latestBlockFor(args, 'attempts'),
213
+ ]);
214
+ if (verdict === null && attempt === null)
215
+ return null;
216
+ return maxNullable(verdict, attempt);
217
+ }
218
+ async function latestBlockFor(args, field) {
219
+ const fetchImpl = args.fetchImpl ?? globalThis.fetch;
220
+ const query = `query LatestActivity($chainId: Int!) {
221
+ ${field}(where: { chainId: $chainId }, orderBy: "createdAtBlock", orderDirection: "desc", limit: 1) {
222
+ items { createdAtBlock }
223
+ }
224
+ }`;
225
+ try {
226
+ const res = await fetchImpl(args.gqlUrl, {
227
+ method: 'POST',
228
+ headers: { 'content-type': 'application/json' },
229
+ body: JSON.stringify({ query, variables: { chainId: args.chainId } }),
230
+ signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
231
+ });
232
+ if (!res.ok)
233
+ throw new Error();
234
+ const json = (await res.json());
235
+ if (json.errors?.length)
236
+ throw new Error();
237
+ if (!json.data?.[field] || !Array.isArray(json.data[field].items)) {
238
+ throw new Error();
239
+ }
240
+ const items = json.data[field].items;
241
+ const raw = items[0]?.createdAtBlock;
242
+ if (raw === undefined || raw === null)
243
+ return null;
244
+ return BigInt(raw);
245
+ }
246
+ catch {
247
+ throw new Error(`GraphQL latest activity read failed for ${field}`);
248
+ }
249
+ }
250
+ function maxNullable(a, b) {
251
+ if (a === null)
252
+ return b;
253
+ if (b === null)
254
+ return a;
255
+ return a > b ? a : b;
256
+ }
257
+ function parseBlockNumber(value) {
258
+ if (typeof value === 'number' && Number.isFinite(value))
259
+ return BigInt(Math.trunc(value));
260
+ if (typeof value === 'string' && /^[0-9]+$/.test(value))
261
+ return BigInt(value);
262
+ return null;
263
+ }
264
+ // ── Webhook POST helper ──────────────────────────────────────────────────────
265
+ /**
266
+ * Build the `postWebhook` seam. Returns null when no URL is configured (NO-OP —
267
+ * the probe still classifies and logs, it just never alerts). The returned
268
+ * function POSTs the JSON payload to a generic incoming webhook.
269
+ */
270
+ export function postNetLivenessWebhook(url, fetchImpl = globalThis.fetch) {
271
+ if (!url)
272
+ return null;
273
+ let webhookUrl;
274
+ try {
275
+ webhookUrl = new URL(url);
276
+ }
277
+ catch {
278
+ throw new Error('invalid webhook URL');
279
+ }
280
+ if (webhookUrl.protocol !== 'https:' && webhookUrl.protocol !== 'http:') {
281
+ throw new Error('invalid webhook URL');
282
+ }
283
+ return async (payload) => {
284
+ let response;
285
+ try {
286
+ response = await fetchImpl(webhookUrl.toString(), {
287
+ method: 'POST',
288
+ headers: { 'content-type': 'application/json' },
289
+ body: JSON.stringify(payload),
290
+ signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
291
+ });
292
+ }
293
+ catch {
294
+ throw new Error('net-liveness webhook delivery failed: transport error');
295
+ }
296
+ if (!response.ok) {
297
+ throw new Error(`net-liveness webhook delivery failed: HTTP ${response.status}`);
298
+ }
299
+ };
300
+ }
301
+ //# sourceMappingURL=net-liveness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"net-liveness.js","sourceRoot":"","sources":["../../src/monitoring/net-liveness.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export interface ProgressEnvelope {
2
+ type: 'progress';
3
+ phase: 'init' | 'bootstrap' | 'daemon';
4
+ step: string;
5
+ attempt?: number;
6
+ blocking?: boolean;
7
+ nextAction?: string;
8
+ addresses?: Record<string, string>;
9
+ estimatedWaitMs?: number;
10
+ }
11
+ export declare function emitProgress(envelope: ProgressEnvelope): void;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * --json-progress: emit NDJSON progress envelopes on stdout during long
3
+ * phases (init, bootstrap, daemon startup). The `jinn run --json-progress`
4
+ * flag flips JINN_JSON_PROGRESS=1 in run.ts before calling main(); when
5
+ * unset this is a no-op so tests / non-flag invocations stay silent on
6
+ * stdout.
7
+ */
8
+ function progressEnabled() {
9
+ return process.env['JINN_JSON_PROGRESS'] === '1';
10
+ }
11
+ export function emitProgress(envelope) {
12
+ if (progressEnabled()) {
13
+ process.stdout.write(JSON.stringify(envelope) + '\n');
14
+ }
15
+ }
16
+ //# sourceMappingURL=progress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.js","sourceRoot":"","sources":["../../src/observability/progress.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,SAAS,eAAe;IACtB,OAAO,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,KAAK,GAAG,CAAC;AACnD,CAAC;AAaD,MAAM,UAAU,YAAY,CAAC,QAA0B;IACrD,IAAI,eAAe,EAAE,EAAE,CAAC;QACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,CAAC;IACxD,CAAC;AACH,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { SolveTokens } from './solve.js';
2
+ export interface RateTable {
3
+ inputPerM: number;
4
+ outputPerM: number;
5
+ cacheReadPerM?: number;
6
+ }
7
+ export declare const DEEPSEEK_V4_FLASH_RATES: RateTable;
8
+ /** gpt-5.4-mini published API rate (used to price Codex-subscription token
9
+ * counts at a representative metered cost — the sub bills flat, but the gate
10
+ * measures what a metered user would pay). $0.75/M in, $4.50/M out. */
11
+ export declare const GPT_5_4_MINI_RATES: RateTable;
12
+ /** USD for one solve from provider-actual token counts. `output_tokens` already
13
+ * INCLUDES `reasoning_tokens` (OpenAI `completion_tokens` semantics, verified
14
+ * empirically on the Codex backend), so reasoning is NOT added again — it is
15
+ * surfaced separately only for reporting. Likewise `input_tokens` is inclusive
16
+ * of `cache_read_tokens`: when a cacheReadPerM rate is supplied, cache-read
17
+ * tokens are re-priced at that (discounted) rate and the remaining (fresh)
18
+ * input at inputPerM; otherwise all input is inputPerM. */
19
+ export declare function solveCostUsd(tokens: SolveTokens, rates: RateTable): number;
@@ -0,0 +1,31 @@
1
+ export const DEEPSEEK_V4_FLASH_RATES = { inputPerM: 0.09, outputPerM: 0.18 };
2
+ /** gpt-5.4-mini published API rate (used to price Codex-subscription token
3
+ * counts at a representative metered cost — the sub bills flat, but the gate
4
+ * measures what a metered user would pay). $0.75/M in, $4.50/M out. */
5
+ export const GPT_5_4_MINI_RATES = { inputPerM: 0.75, outputPerM: 4.5 };
6
+ /** USD for one solve from provider-actual token counts. `output_tokens` already
7
+ * INCLUDES `reasoning_tokens` (OpenAI `completion_tokens` semantics, verified
8
+ * empirically on the Codex backend), so reasoning is NOT added again — it is
9
+ * surfaced separately only for reporting. Likewise `input_tokens` is inclusive
10
+ * of `cache_read_tokens`: when a cacheReadPerM rate is supplied, cache-read
11
+ * tokens are re-priced at that (discounted) rate and the remaining (fresh)
12
+ * input at inputPerM; otherwise all input is inputPerM. */
13
+ export function solveCostUsd(tokens, rates) {
14
+ const per = (n, rate) => n * rate * 1e-6;
15
+ const outputCost = per(tokens.outputTokens, rates.outputPerM);
16
+ if (typeof rates.cacheReadPerM === 'number') {
17
+ // The fresh/cache split only matters when a discounted cacheReadPerM rate is
18
+ // priced. Here the `input ⊇ cache_read` invariant must hold — silently
19
+ // clamping fresh to 0 would hide a bad token export and mis-price the solve,
20
+ // so fail loud instead. (The no-cache-rate path below is untouched: it prices
21
+ // all input at inputPerM and never reads cacheReadTokens.)
22
+ if (tokens.cacheReadTokens > tokens.inputTokens) {
23
+ throw new Error(`solveCostUsd: cache_read_tokens (${tokens.cacheReadTokens}) > input_tokens (${tokens.inputTokens}) ` +
24
+ `violates the input ⊇ cache_read invariant when a cacheReadPerM rate is priced`);
25
+ }
26
+ const fresh = tokens.inputTokens - tokens.cacheReadTokens;
27
+ return per(fresh, rates.inputPerM) + per(tokens.cacheReadTokens, rates.cacheReadPerM) + outputCost;
28
+ }
29
+ return per(tokens.inputTokens, rates.inputPerM) + outputCost;
30
+ }
31
+ //# sourceMappingURL=cost.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost.js","sourceRoot":"","sources":["../../src/pilot/cost.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,uBAAuB,GAAc,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;AACxF;;wEAEwE;AACxE,MAAM,CAAC,MAAM,kBAAkB,GAAc,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC;AAElF;;;;;;4DAM4D;AAC5D,MAAM,UAAU,YAAY,CAAC,MAAmB,EAAE,KAAgB;IAChE,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,IAAY,EAAU,EAAE,CAAC,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;IACjE,MAAM,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,YAAY,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IAC9D,IAAI,OAAO,KAAK,CAAC,aAAa,KAAK,QAAQ,EAAE,CAAC;QAC5C,6EAA6E;QAC7E,uEAAuE;QACvE,6EAA6E;QAC7E,8EAA8E;QAC9E,2DAA2D;QAC3D,IAAI,MAAM,CAAC,eAAe,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;YAChD,MAAM,IAAI,KAAK,CACb,oCAAoC,MAAM,CAAC,eAAe,qBAAqB,MAAM,CAAC,WAAW,IAAI;gBACrG,+EAA+E,CAChF,CAAC;QACJ,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,GAAG,MAAM,CAAC,eAAe,CAAC;QAC1D,OAAO,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,eAAe,EAAE,KAAK,CAAC,aAAa,CAAC,GAAG,UAAU,CAAC;IACrG,CAAC;IACD,OAAO,GAAG,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,CAAC,SAAS,CAAC,GAAG,UAAU,CAAC;AAC/D,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Solve-side pilot instance fields. The grader's `HfRow` (swe-rebench-v2-evaluator/hf-fetcher.ts)
3
+ * omits `base_commit` and `problem_statement` — this parses those out of the raw HF row.
4
+ */
5
+ export interface PilotInstance {
6
+ instance_id: string;
7
+ repo: string;
8
+ base_commit: string;
9
+ problem_statement: string;
10
+ /** SWE-rebench-V2 acceptance spec (the API contract the solution must satisfy).
11
+ * Optional — fed to BOTH arms when present so it never biases the comparison;
12
+ * it is the *spec*, not the hidden test (feeding the test would be cheating). */
13
+ interface?: string;
14
+ hf_dataset: string;
15
+ hf_split: string;
16
+ }
17
+ export declare function parsePilotInstanceRow(row: Record<string, unknown>, ctx: {
18
+ hf_dataset: string;
19
+ hf_split: string;
20
+ }): PilotInstance;
@@ -0,0 +1,19 @@
1
+ export function parsePilotInstanceRow(row, ctx) {
2
+ const s = (k) => {
3
+ const v = row[k];
4
+ if (typeof v !== 'string' || !v)
5
+ throw new Error(`pilot instance row missing '${k}'`);
6
+ return v;
7
+ };
8
+ const iface = typeof row['interface'] === 'string' && row['interface'] ? row['interface'] : undefined;
9
+ return {
10
+ instance_id: s('instance_id'),
11
+ repo: s('repo'),
12
+ base_commit: s('base_commit'),
13
+ problem_statement: s('problem_statement'),
14
+ ...(iface ? { interface: iface } : {}),
15
+ hf_dataset: ctx.hf_dataset,
16
+ hf_split: ctx.hf_split,
17
+ };
18
+ }
19
+ //# sourceMappingURL=instance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instance.js","sourceRoot":"","sources":["../../src/pilot/instance.ts"],"names":[],"mappings":"AAiBA,MAAM,UAAU,qBAAqB,CACnC,GAA4B,EAC5B,GAA6C;IAE7C,MAAM,CAAC,GAAG,CAAC,CAAS,EAAU,EAAE;QAC9B,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;QACjB,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,GAAG,CAAC,CAAC;QACtF,OAAO,CAAC,CAAC;IACX,CAAC,CAAC;IACF,MAAM,KAAK,GAAG,OAAO,GAAG,CAAC,WAAW,CAAC,KAAK,QAAQ,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,CAAE,GAAG,CAAC,WAAW,CAAY,CAAC,CAAC,CAAC,SAAS,CAAC;IAClH,OAAO;QACL,WAAW,EAAE,CAAC,CAAC,aAAa,CAAC;QAC7B,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,WAAW,EAAE,CAAC,CAAC,aAAa,CAAC;QAC7B,iBAAiB,EAAE,CAAC,CAAC,mBAAmB,CAAC;QACzC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtC,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,QAAQ,EAAE,GAAG,CAAC,QAAQ;KACvB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,31 @@
1
+ /** Git helpers for the pilot orchestrator, factored out so their fail-loud
2
+ * behaviour is unit-testable with an injected runner (the orchestrator's own
3
+ * I/O is validated by dry-run + smoke, per the pilot plan). */
4
+ export type CmdRunner = (cmd: string, args: string[], opts?: {
5
+ cwd?: string;
6
+ }) => Promise<{
7
+ stdout: string;
8
+ stderr: string;
9
+ exitCode: number;
10
+ }>;
11
+ /** A git base-checkout step (clone/checkout) exited non-zero. The base repo is
12
+ * unusable, so the INSTANCE is ungradeable — it MUST NOT silently proceed into
13
+ * an empty repo where both arms score `passed:false` (that mis-attributes an
14
+ * environment failure to the agent and understates the resolve rate). Caught at
15
+ * run-pilot's per-instance boundary, which skips the instance and continues. */
16
+ export declare class GitStepError extends Error {
17
+ readonly step: 'clone' | 'checkout';
18
+ readonly exitCode: number;
19
+ readonly detail: string;
20
+ constructor(step: 'clone' | 'checkout', exitCode: number, detail: string);
21
+ }
22
+ /** Clone `repo` into `baseDir` and check out `baseCommit`, FAIL-LOUD on a
23
+ * non-zero exit from either step. A 404'd/renamed repo or an unfetchable commit
24
+ * must throw here rather than leave an empty/wrong checkout that both arms then
25
+ * "solve" into empty patches. */
26
+ export declare function prepareBaseCheckout(run: CmdRunner, repo: string, baseCommit: string, baseDir: string): Promise<void>;
27
+ /** Recover the working-tree patch, INCLUDING new (untracked) files: `git add -A`
28
+ * stages everything, then `git diff --cached` emits the full diff. A plain
29
+ * `git diff` misses untracked files, so a fix that ADDS a file would look like
30
+ * an empty patch (a spurious not-resolved). */
31
+ export declare function recoverPatch(run: CmdRunner, cwd: string): Promise<string>;
@@ -0,0 +1,42 @@
1
+ /** Git helpers for the pilot orchestrator, factored out so their fail-loud
2
+ * behaviour is unit-testable with an injected runner (the orchestrator's own
3
+ * I/O is validated by dry-run + smoke, per the pilot plan). */
4
+ /** A git base-checkout step (clone/checkout) exited non-zero. The base repo is
5
+ * unusable, so the INSTANCE is ungradeable — it MUST NOT silently proceed into
6
+ * an empty repo where both arms score `passed:false` (that mis-attributes an
7
+ * environment failure to the agent and understates the resolve rate). Caught at
8
+ * run-pilot's per-instance boundary, which skips the instance and continues. */
9
+ export class GitStepError extends Error {
10
+ step;
11
+ exitCode;
12
+ detail;
13
+ constructor(step, exitCode, detail) {
14
+ super(`git ${step} failed (exit ${exitCode})${detail ? `: ${detail}` : ''}`);
15
+ this.step = step;
16
+ this.exitCode = exitCode;
17
+ this.detail = detail;
18
+ this.name = 'GitStepError';
19
+ }
20
+ }
21
+ /** Clone `repo` into `baseDir` and check out `baseCommit`, FAIL-LOUD on a
22
+ * non-zero exit from either step. A 404'd/renamed repo or an unfetchable commit
23
+ * must throw here rather than leave an empty/wrong checkout that both arms then
24
+ * "solve" into empty patches. */
25
+ export async function prepareBaseCheckout(run, repo, baseCommit, baseDir) {
26
+ const clone = await run('git', ['clone', `https://github.com/${repo}.git`, baseDir]);
27
+ if (clone.exitCode !== 0)
28
+ throw new GitStepError('clone', clone.exitCode, clone.stderr.trim().slice(0, 300));
29
+ const checkout = await run('git', ['checkout', baseCommit], { cwd: baseDir });
30
+ if (checkout.exitCode !== 0)
31
+ throw new GitStepError('checkout', checkout.exitCode, checkout.stderr.trim().slice(0, 300));
32
+ }
33
+ /** Recover the working-tree patch, INCLUDING new (untracked) files: `git add -A`
34
+ * stages everything, then `git diff --cached` emits the full diff. A plain
35
+ * `git diff` misses untracked files, so a fix that ADDS a file would look like
36
+ * an empty patch (a spurious not-resolved). */
37
+ export async function recoverPatch(run, cwd) {
38
+ await run('git', ['add', '-A'], { cwd });
39
+ const diff = await run('git', ['diff', '--cached'], { cwd });
40
+ return diff.stdout;
41
+ }
42
+ //# sourceMappingURL=repo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo.js","sourceRoot":"","sources":["../../src/pilot/repo.ts"],"names":[],"mappings":"AAAA;;gEAEgE;AAQhE;;;;iFAIiF;AACjF,MAAM,OAAO,YAAa,SAAQ,KAAK;IAE1B;IACA;IACA;IAHX,YACW,IAA0B,EAC1B,QAAgB,EAChB,MAAc;QAEvB,KAAK,CAAC,OAAO,IAAI,iBAAiB,QAAQ,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAJpE,SAAI,GAAJ,IAAI,CAAsB;QAC1B,aAAQ,GAAR,QAAQ,CAAQ;QAChB,WAAM,GAAN,MAAM,CAAQ;QAGvB,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF;AAED;;;kCAGkC;AAClC,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,GAAc,EACd,IAAY,EACZ,UAAkB,EAClB,OAAe;IAEf,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,sBAAsB,IAAI,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACrF,IAAI,KAAK,CAAC,QAAQ,KAAK,CAAC;QAAE,MAAM,IAAI,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAC7G,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;IAC9E,IAAI,QAAQ,CAAC,QAAQ,KAAK,CAAC;QAAE,MAAM,IAAI,YAAY,CAAC,UAAU,EAAE,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;AAC3H,CAAC;AAED;;;gDAGgD;AAChD,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAc,EAAE,GAAW;IAC5D,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;IAC7D,OAAO,IAAI,CAAC,MAAM,CAAC;AACrB,CAAC"}
@@ -0,0 +1,22 @@
1
+ export interface Arm {
2
+ name: 'A' | 'B';
3
+ skills: string[];
4
+ }
5
+ export interface SolveTokens {
6
+ inputTokens: number;
7
+ outputTokens: number;
8
+ cacheReadTokens: number;
9
+ reasoningTokens: number;
10
+ }
11
+ /** The jinn-agent argv for one solve. Arm A = empty loadout enforced via
12
+ * --ignore-rules (no memory/AGENTS.md/preloaded-skill leakage, spike §3.1);
13
+ * arm B = arm A + `-s <skill>` for each loadout skill. When `provider`/`model`
14
+ * are supplied they pin the inference endpoint for this invocation (e.g.
15
+ * `openai-codex` + `gpt-5.4-mini`) without touching the global config default. */
16
+ export declare function buildSolveArgs(arm: Arm, prompt: string, opts: {
17
+ maxTurns: number;
18
+ provider?: string;
19
+ model?: string;
20
+ }): string[];
21
+ export declare function parseSessionTokens(exportLine: string): SolveTokens;
22
+ export declare function extractSessionId(stderr: string): string | null;
@@ -0,0 +1,37 @@
1
+ /** The jinn-agent argv for one solve. Arm A = empty loadout enforced via
2
+ * --ignore-rules (no memory/AGENTS.md/preloaded-skill leakage, spike §3.1);
3
+ * arm B = arm A + `-s <skill>` for each loadout skill. When `provider`/`model`
4
+ * are supplied they pin the inference endpoint for this invocation (e.g.
5
+ * `openai-codex` + `gpt-5.4-mini`) without touching the global config default. */
6
+ export function buildSolveArgs(arm, prompt, opts) {
7
+ const base = ['chat', '-q', prompt, '-Q', '--yolo', '--ignore-rules'];
8
+ const endpoint = [
9
+ ...(opts.provider ? ['--provider', opts.provider] : []),
10
+ ...(opts.model ? ['-m', opts.model] : []),
11
+ ];
12
+ const skills = arm.skills.flatMap((s) => ['-s', s]);
13
+ return [...base, ...endpoint, ...skills, '--pass-session-id', '--max-turns', String(opts.maxTurns)];
14
+ }
15
+ export function parseSessionTokens(exportLine) {
16
+ const o = JSON.parse(exportLine);
17
+ const num = (k) => {
18
+ const v = o[k];
19
+ if (typeof v !== 'number')
20
+ throw new Error(`session export missing numeric token field '${k}'`);
21
+ return v;
22
+ };
23
+ const optNum = (k) => (typeof o[k] === 'number' ? o[k] : 0);
24
+ return {
25
+ inputTokens: num('input_tokens'),
26
+ outputTokens: num('output_tokens'),
27
+ cacheReadTokens: optNum('cache_read_tokens'),
28
+ // Reasoning models (e.g. gpt-5.4-mini) report reasoning tokens separately;
29
+ // they are billed at the output rate. Absent for non-reasoning models → 0.
30
+ reasoningTokens: optNum('reasoning_tokens'),
31
+ };
32
+ }
33
+ export function extractSessionId(stderr) {
34
+ const m = stderr.match(/session_id:\s*(\S+)/);
35
+ return m ? m[1] : null;
36
+ }
37
+ //# sourceMappingURL=solve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"solve.js","sourceRoot":"","sources":["../../src/pilot/solve.ts"],"names":[],"mappings":"AAGA;;;;mFAImF;AACnF,MAAM,UAAU,cAAc,CAC5B,GAAQ,EACR,MAAc,EACd,IAA6D;IAE7D,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,gBAAgB,CAAC,CAAC;IACtE,MAAM,QAAQ,GAAG;QACf,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACvD,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;KAC1C,CAAC;IACF,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACpD,OAAO,CAAC,GAAG,IAAI,EAAE,GAAG,QAAQ,EAAE,GAAG,MAAM,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;AACtG,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,UAAkB;IACnD,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAA4B,CAAC;IAC5D,MAAM,GAAG,GAAG,CAAC,CAAS,EAAU,EAAE;QAChC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACf,IAAI,OAAO,CAAC,KAAK,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,GAAG,CAAC,CAAC;QAChG,OAAO,CAAC,CAAC;IACX,CAAC,CAAC;IACF,MAAM,MAAM,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACxF,OAAO;QACL,WAAW,EAAE,GAAG,CAAC,cAAc,CAAC;QAChC,YAAY,EAAE,GAAG,CAAC,eAAe,CAAC;QAClC,eAAe,EAAE,MAAM,CAAC,mBAAmB,CAAC;QAC5C,2EAA2E;QAC3E,2EAA2E;QAC3E,eAAe,EAAE,MAAM,CAAC,kBAAkB,CAAC;KAC5C,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;IAC9C,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,35 @@
1
+ export interface SolveOutcome {
2
+ instance_id: string;
3
+ arm: 'A' | 'B';
4
+ repeat: number;
5
+ passed: boolean | null;
6
+ costUsd: number;
7
+ }
8
+ export interface PilotReport {
9
+ n: number;
10
+ armA: {
11
+ resolveRate: number;
12
+ };
13
+ armB: {
14
+ resolveRate: number;
15
+ };
16
+ bothSolveTasks: number;
17
+ excluded: number;
18
+ quality: {
19
+ lowerBound: number;
20
+ nonInferior: boolean;
21
+ deltaPP: number;
22
+ };
23
+ /** `n` is the both-solve NON-ZERO cost-diff count the Wilcoxon actually uses;
24
+ * `underpowered` marks n below its one-sided minimum-rejectable size (~5), so a
25
+ * tiny-n verdict is not mistaken for a powered one. */
26
+ cost: {
27
+ verdict: 'lower' | 'not-lower' | 'inconclusive';
28
+ medianDeltaUsd: number;
29
+ n: number;
30
+ underpowered: boolean;
31
+ };
32
+ }
33
+ export declare function tallyPilot(outcomes: SolveOutcome[], opts: {
34
+ rng: () => number;
35
+ }): PilotReport;