feat(node): seictl node watch --until=caught-up — SDK-backed readiness gate#214
Conversation
…s gate Add a serve-readiness sentinel to `seictl node watch`: --until=caught-up waits for Running, then gates on the node's published endpoints via the SDK's shared readiness primitive (sei.WaitCaughtUp = TM /status height>1 && catching_up==false; sei.WaitEVMServing = EVM eth_blockNumber bound, when the node serves EVM). This replaces the nightly's bespoke curl/jq catching_up loop with one reusable Go implementation shared across the SDK, the seitask Task steps, and the CLI. Imports github.com/sei-protocol/sei-k8s-controller/sdk/sei (core, stdlib-only) as an interim cross-repo dep — a temporary mutual module require that the seictl-> controller monorepo consolidation later dissolves. Verified the import does not drag the controller's k8s graph into seictl beyond what seictl already carries (go mod tidy: only benign indirect bumps; seictl stays at its own k8s v0.36). Inputs come from the node's .status.endpoint (read verbatim); endpointsFrom is unit-tested against the fullNode/non-EVM/pre-publish shapes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
PR SummaryMedium Risk Overview
Reviewed by Cursor Bugbot for commit 5e70706. Bugbot is set up for automated code reviews on this repo. Configure here. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 5e70706. Configure here.
| if err := sei.WaitEVMServing(ctx, nil, evmRPC); err != nil { | ||
| cliutil.EmitStatus(os.Stderr, err) | ||
| return cli.Exit("", 1) | ||
| } |
There was a problem hiding this comment.
Caught-up wait timeout wrong reason
Medium Severity
For --until=caught-up, after the Running watch succeeds, failures from sei.WaitCaughtUp or sei.WaitEVMServing (including when the shared --timeout elapses during those polls) are emitted via EmitStatus without the same WatchExitError mapping RunWatch uses. stderr then shows InternalError instead of Timeout, which breaks the command’s documented metav1.Status.reason contract for nightly orchestration.
Reviewed by Cursor Bugbot for commit 5e70706. Configure here.
Cuts **v0.0.60**. **Includes:** `seictl node watch --until=caught-up` (#214) — waits for `Running`, then gates on the node's published endpoints via the SDK's shared readiness primitive (`sei.WaitCaughtUp` TM caught-up; `sei.WaitEVMServing` EVM serving). Lets the nightly orchestration retire its bespoke `curl /status | jq` catching_up probe. Additive flag value, backward-compatible → patch bump (v0.0.59 → v0.0.60). Merging this `version.json` bump triggers `uci-release-publish` → tag + goreleaser binary, which the platform nightly then pins via `SEICTL_VERSION`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>


Wires seictl to the SDK's shared chain-readiness primitive so the nightly's bespoke bash catching_up probe can be deleted — the readiness logic lives once, in reusable Go.
What
seictl node watch --until=caught-up: waits forRunning, then gates on the node's published endpoints viasei.WaitCaughtUp(TM/status:height>1 && catching_up==false) andsei.WaitEVMServing(EVMeth_blockNumberbound, when the node serves EVM)..status.endpoint(read verbatim, never reconstructed).endpointsFromunit-tested across fullNode / non-EVM / pre-publish shapes.Why
The nightly orchestration stays seictl-CLI-driven; the win is the readiness/wait complexity moving out of bespoke
curl /status | jq '(.catching_up==false) and height>1'bash into one reusable Go implementation (sdk/sei) shared by the SDK, the seitask Task steps, and the CLI.Interim dependency note
Imports
github.com/sei-protocol/sei-k8s-controller/sdk/sei(core) — a temporary mutual module require (the controller already importsseictl/sidecar/client). The seictl→controller monorepo consolidation (designed + xreviewed) later dissolves this into a clean in-repocli→seiclientimport viago.work. Verified the import adds nothing to seictl's build beyond what it already carries (it's already a k8s CLI with client-go + controller-runtime):go mod tidymade only benign indirect bumps; seictl stays at its own k8s v0.36, andsdk/seicore is stdlib-only (0 k8s/controller-runtime deps) so pruning keeps the controller's k8s graph out.Test
go build/golangci-lint(0 issues)/go test ./seinode/...green; gofmt clean.🤖 Generated with Claude Code