feat(nodetask): consume gov task results — outputs, conditions, pending loop#451
Conversation
…ng loop Bumps seictl to v0.0.61 and consumes its gov completion contract: - sidecarExecution gains a Result() accessor capturing the terminal task result (stamped on both success and failure). - driveTask decodes the gov result and branches: committed_ok -> Complete + Ready/Confirmed + outputs; committed_failed -> Failed/TxFailed + outputs; pending -> reset to Pending and re-submit (same task ID -> engine re-run -> marker adopt), bounded by spec.timeoutSeconds; on timeout -> Failed/ InclusionUndetermined (txHash retained). Non-gov failures unchanged. - populateOutputs stamps proposalId/txHash/height into the existing CRD Outputs for the three gov kinds (decode-by-kind, no sidecar-tasks import). - SDK TaskOutputs surfaces gov outputs; the integration test now reads the proposal ID off the upgrade task output and deletes resolveProposalID (the brittle plan-name REST scan). - Refresh the stale "outputs deferred / chain-as-medium" docs. Deploy-order: this controller must roll BEFORE the v0.0.61 sidecar image (D1=X interim — an old controller sees Failed where it saw Complete). Design: sei-protocol/bdchatham-designs#98. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
PR SummaryHigh Risk Overview Gov completion semantics replace a flat Complete/Failed poll: The SDK exposes gov fields on New Reviewed by Cursor Bugbot for commit faa59a0. Bugbot is set up for automated code reviews on this repo. Configure here. |
The controller half of the SeiNodeTask governance UX work (design: sei-protocol/bdchatham-designs#98) — consumes the seictl v0.0.61 gov completion contract. This is the payoff: a completed gov task now surfaces its proposal ID / tx hash, a task reports Failed instead of a false Complete when a tx doesn't commit, and the integration test's brittle proposal-ID REST scan is deleted.
Depends on: seictl#219 (v0.0.61). Follows PR #450 (stop-resubmit).
Changes
go.mod→ seictl v0.0.61.sidecarExecution.Result()captures the terminal task result (both success and failure paths).driveTaskdecodes the gov result and branches: committed_ok → Complete + Ready/Confirmed+ outputs; committed_failed → Failed/TxFailed+ outputs; pending → reset to Pending and re-submit (same task ID → engine run+1 → marker adopt re-checks), bounded byspec.timeoutSeconds; on timeout → Failed/InclusionUndetermined(txHash retained). Non-gov failures unchanged.populateOutputsstamps proposalId/txHash/height into the existing CRD Outputs (decode-by-kind, via a local wire-mirror — no heavy sidecar-tasks import). No CRD schema change.TaskOutputsgains gov arms; integration test reads the proposal ID off the task output and deletesresolveProposalID(the plan-name REST scan).Tests
controller_gov_test.go: Confirmed / CommittedFailed / Pending→resubmit→converge / PendingTimeout / GovVote-confirmed / no-result→generic-failure, plusTestGovResultMirrorMatchesWire(guards the local mirror against seictlGovTxResultdrift).Sign-off
systems-engineer (pending loop, decode, idempotency — logic correct, no changes) and kubernetes-specialist (condition discipline, single-patch, contract-safe) — both green.
Roll this controller before the seictl v0.0.61 sidecar image. A pre-2b controller treats the new sidecar's
pending→Failed as terminal and would prematurely fail an in-flight gov tx. New-controller + old-sidecar is graceful (nil result → today's behavior).Reviewer flag for confirmation
Gov-kind success now emits Ready
reason=Confirmed(wasTaskComplete). Confirm no PromQL/runbook filters the old reason for gov kinds (gov-ops is a newer surface, likely safe).🤖 Generated with Claude Code