From 3cc5e5c2f07660735940610d45990eb4ebe3d299 Mon Sep 17 00:00:00 2001 From: igneum-labs <337424239+igneum-labs@users.noreply.github.com> Date: Wed, 7 Oct 2026 06:25:12 +0000 Subject: [PATCH] Hands mover: on 0.3.18 trees the restart read-back takes powEngine and the blockrate object from igneum_getNodeInfo; a stub answer stops the sequence The shipper's read-back for 0.3.18 (7 October 2026): igneum_getNodeInfo exists again and must answer powEngine igneum-pow (a stub is a FAIL) with a blockrate object, which the mover prints; a tree before 0.3.18 answers -32601 and the engine is still read from the binary's igneum-pow source paths. The parser is checked against the three answer shapes. Co-Authored-By: Claude Fable 5.1 --- infra/build-server/hands/move-hand.sh | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/infra/build-server/hands/move-hand.sh b/infra/build-server/hands/move-hand.sh index d443c0d98..b917731fc 100755 --- a/infra/build-server/hands/move-hand.sh +++ b/infra/build-server/hands/move-hand.sh @@ -161,9 +161,27 @@ case "$MODE" in rssh "[ \$(strings $H/bin/igneumd | grep -c '$sha') -gt 0 ] && echo 'commit string $sha present in the running binary' || { echo 'NO commit string $sha in the binary'; exit 1; }" after=$(box_digest "$unit") if [ -n "$after" ] && [ "$after" = "$want" ]; then say "$unit digest ${after:0:16}... MATCHES"; else say "$unit digest ${after:-none} against wanted ${want:-any}: DIFFER (stop here)"; exit 1; fi - eng=$(rssh "curl -s --max-time 10 -X POST -H 'content-type: application/json' --data '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"igneum_getNodeInfo\",\"params\":[]}' http://127.0.0.1:$evm" | python3 -c 'import json,sys; d=json.load(sys.stdin); r=d.get("result") or {}; print(r.get("powEngine") or r.get("pow_engine") or ("ERROR: "+str(d.get("error")) if d.get("error") else "no powEngine field: "+str(list(r)[:8])))' 2>/dev/null || echo "igneum_getNodeInfo not answered on $evm") - say "$unit igneum_getNodeInfo powEngine: $eng" - case "$eng" in igneum-pow) ;; *) say "WARNING: powEngine is not igneum-pow" ;; esac + # 0.3.18 and later (the shipper, 7 Oct 2026): igneum_getNodeInfo answers with powEngine (igneum-pow; a stub is a FAIL that stops + # the sequence) and a blockrate object; a tree before it answers -32601 and the engine is read from the binary below + eng=$(rssh "curl -s --max-time 10 -X POST -H 'content-type: application/json' --data '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"igneum_getNodeInfo\",\"params\":[]}' http://127.0.0.1:$evm" | python3 -c ' +import json, sys +d = json.load(sys.stdin); r = d.get("result") or {} +if d.get("error"): print("ERROR: " + str(d["error"])); sys.exit() +eng = r.get("powEngine") or r.get("pow_engine") or "none" +br = r.get("blockrate") or r.get("blockRate") +print(eng + "|" + (json.dumps(br, separators=(",", ":"))[:160] if isinstance(br, dict) else "NO blockrate object"))' 2>/dev/null || echo "igneum_getNodeInfo not answered on $evm") + case "$eng" in + igneum-pow\|*) + say "$unit igneum_getNodeInfo powEngine: igneum-pow; blockrate: ${eng#igneum-pow|}" + case "$eng" in *"NO blockrate"*) say "WARNING: $unit igneum_getNodeInfo carries no blockrate object" ;; esac ;; + stub\|*|none\|*) say "$unit igneum_getNodeInfo powEngine: ${eng%%|*}: FAIL (stop here)"; exit 1 ;; + *-32601*|*"not found"*|*"not answered"*) + # a tree before 0.3.18 has no igneum_getNodeInfo (the shipper, 7 Oct 2026): the engine is read from the binary instead; a stub + # build carries none of the igneum-pow crate's source paths + n=$(rssh "strings $H/bin/igneumd | grep -c 'igneum-pow/src/'" || echo 0) + if [ "${n:-0}" -gt 0 ]; then say "$unit engine from the binary: igneum-pow ($n igneum-pow/src/ paths; igneum_getNodeInfo is not on this tree)"; else say "WARNING: $unit binary carries no igneum-pow/src/ path: a stub build?"; fi ;; + *) say "WARNING: $unit igneum_getNodeInfo powEngine: $eng" ;; + esac fi ;; unload)