agent-platform release v4.12.0

Added

  • The stateful singletons can be pinned to on-demand capacity, and muster-valkey takes the #431 guards (giantswarm/agent-platform#439; on gazelle, all-spot workers, one spot-interruption wave took muster’s OAuth token store down for two minutes — every token refresh blocked inside muster, 27 s before the Slack bot reacted — and killed klaus-gateway mid-turn, its replacement waiting four minutes on Multi-Attach). #431’s guards address voluntary disruption only; a spot reclaim terminates the instance whatever the budget says. New meta-chart block scheduling.singletons (nodeSelector, tolerations; empty by default, so no installation changes behaviour until it is set): merged into, and appended to, the scheduling knobs of the four single-replica stateful pods before their releases render — muster (muster.nodeSelector), muster-valkey (valkey.valkey.nodeSelector), the kagent controller (kagent.controller.nodeSelector), klaus-gateway (klausGateway.nodeSelector) — with a component’s own keys winning (agent-platform.scheduling.apply); held back from the connectivity release (components.agent-platform-connectivity.omitKeys), so a live connectivity chart that predates the block is never failed by it. The intended value on a Karpenter spot installation is karpenter.sh/capacity-type: on-demand (one small on-demand node for the four; the fleet’s NodePools admit it untainted) — UPGRADE.md carries the cost note, the roll and the “never on a cluster without Karpenter” warning. klaus-gateway takes the keys from chart 1.3.3 on (giantswarm/klaus-gateway#253: the earlier 1.x schemas refused every key under nodeSelector — found in the lab when the release failed validation). muster-valkey now carries karpenter.sh/do-not-disrupt: "true" (the valkey subchart’s valkey.valkey.podAnnotations) and a PodDisruptionBudget muster-valkey (valkey.podDisruptionBudget, minAvailable: 1, AlwaysAllow) rendered by the connectivity chart — neither the wrapper nor the upstream subchart has a budget knob — selecting the pod as the subchart labels it (name valkey, instance valkey), named after valkey.valkey.fullnameOverride; the key never reaches the valkey release (components.valkey.omitKeys). Every installation rolls the muster-valkey pod once. make verify-disruption extended: the merge and its precedence, the empty default (byte-identical component values), the hold-back, the valkey budget on/off/inert and its guards, a stray key under the block refused by the schema.