agent-platform release v4.18.0
Added
- The Substrate WorkerPool’s CPU generation pin —
karpenter.k8s.aws/instance-generation next to the vendor in kagent.substrateWorkerPool.template.nodeSelector — is documented, render-guarded and verified (giantswarm/agent-platform#457, the caveat #430 recorded). One pool runs one CPU feature set: an actor’s golden snapshot is a gVisor checkpoint that restores only on a host whose CPU offers every feature it recorded, and #429’s vendor pin left the generation open — on gazelle (2026-09-14) Karpenter put two workers on an m7a.2xlarge (generation 7, AVX-512) and two on c5ad.xlarge (generation 5), the goldens were taken on the m7a workers, and every cold turn placed on a c5ad worker failed incompatible FeatureSet: missing features: … avx512f … twice (30 s each), then SendStreamingMessage Internal, “the turn failed” in Slack; the next morning’s pool (c6a, c5a ×2, m6a) restored everywhere only because the goldens had been re-taken on a gen-5 worker. The pin is a second label in the same map, set per installation (the fleet template renders it from the installation’s values the way it renders the vendor): pick a generation that is one CPU model across its families — for AMD on AWS 6 (c6a/m6a/r6a, EPYC Milan) or 7 (c7a/m7a/r7a, Genoa); 5 mixes Naples (m5a/r5a) with Rome (c5a/c5ad) and is no feature-set pin — and one the goldens restore on (an older generation’s golden restores on a newer one, never the reverse), and check the spot pool it leaves (the generation’s families × the NodePool’s sizes; three families is the floor). The meta chart now refuses a nodeSelector value that is not a string naming the key (agent-platform.validateWorkerPool): the label is "6", and a bare 6 rendered, passed the open kagent schema and would have failed only when helm-controller applied the kagent release on every installation carrying it. make verify-workerpool (in CI) asserts the default forwards the architecture alone, an installation’s three-label pin reaches the kagent release verbatim with every value a string, the unquoted generation fails the render, and the kagent chart the range resolves to renders the pin unchanged into the one WorkerPool’s spec.template.nodeSelector — the lab has no Karpenter labels, so this render is where the pin is proven. Docs: values.yaml, the chart README, the root README’s Substrate section and UPGRADE.md name the generation next to the vendor. A restore that fails with incompatible FeatureSet is retried on the same worker; placing it on another worker is Substrate’s (giantswarm/giantswarm#37742 row 12), not this chart’s. No rendered object changes for an installation that sets no generation.