A preview rule signs the rehearsal's generated value as a build arg, so its builds are refused#4094
A preview rule's build policy signs the rehearsal's generated value as a build arg. ployz github preview approve derives each service's policy with BuildPolicy::derive from the rehearsed preview spec (core/crates/ployz/src/handlers/github_preview.rs, preview_service). That spec holds the rehearsal's generated value, so the policy's args carry it, for example SESSION=ad1412….
Each real preview gets its own generated value. The runner refuses a build when BuildPolicy::derive of the deployment's spec differs from the signed policy (core/crates/ployz/src/handlers/build/rule.rs, "the deployment Cloud sent does not build with the rule's policy"). So a preview of a service that builds from GitHub and has a generated variable should be refused at build time, every time.
Found by reading the code, and from the approval display in a live lane for #4087: the preview's builds line printed build args …, SESSION=<rehearsal value> while generated printed SESSION=${{ secret(48, "a-f0-9") }}. No preview build was run to confirm the refusal.
A likely fix is to treat a generated key in a preview policy as the template does: sign its generator in place of the value, and have the runner check the deployment's value with Generator::could_make before it compares. Deciding which value the image gets as a build arg is the open product question.
Scores per AGENTS.md: F=2 (it needs previews, which are unreleased, plus a GitHub-built service with a generated variable on that same service). S=5 (a broken flow, with the workaround of keeping the generated value on a service that doesn't build from Git).