Skip to content

Every update of an engine merges on its own once its checks passed, and the release waits for the Canary of main

  • Status: accepted
  • Date: 2026-11-10

Context

The engines are the AI: the Claude Code action, the engine's action of this repository, and the other engines, Codex with its action and its command line, the Gemini CLI and the Copilot CLI. Each runs only in the job analyze, with its secret, which only main may use, so no check of a pull request runs one with a key. Decision 0020 let a patch version merge on its own once every required check passed, engine contracts among them, and kept a minor or major version and a new commit of a tag waiting for the maintainer, with the note "This update waits for you" in its pull request.

The maintainer never reviewed those updates: the update of the other engines to the Gemini CLI 0.66.0 and Codex 0.166.0, #311, waited with every check green until it was merged by hand on 2026-11-10. He decided that such an update merges on its own and waits for no person, as the weekly refresh of the lock files had already done since the blueprint keeps it to versions a week old. What the review was meant to give must then come from the checks: the week that every update waits after its release, the required check engine contracts, and the Canary, which runs the AI's whole path with the secret on main. But the Canary runs after the merge, and a release of dependency updates alone merges itself, so nothing kept a release from bringing an update that broke the Canary to every repository before anybody looked; decision 0020 named that gap.

Options

  1. Keep the minor and major versions waiting. Safe in theory, but a person who never looks gives no safety, and the updates of the engines and their fixes reach the repositories late, or not at all.
  2. Let every update merge on its own, and let the Canary open a pull request that reverts an update after which it failed. A Canary that failed for a moment, such as when its runner wasn't there, would revert a good update, and Renovate would bring the same update again in its next run, and the revert would follow it.
  3. Let every update merge on its own, and let the release wait until the latest Canary of main passed, by a required check of the release's pull request.

Decision

Option 3. The maintainer decided on 2026-11-10 that every update of an engine merges on its own; a gate before the release keeps a broken engine from the repositories without reverting a good update after a Canary that failed for a moment, which option 2 would do.

  • Every update of an engine merges on its own once every required check passed, a minor or major version and a new commit of a tag too, a week after its release, as the rules of the blueprint have every update. .github/renovate.json5 has one rule for the engines with auto-merge and a group for each engine: the engine's action, Codex, with its action and its command line, which move together, the Gemini CLI and the Copilot CLI. So an update that fails its checks holds back no other engine. The weekly refresh of the lock files of engines/ merges on its own by the rules of the blueprint, from versions a week old, as before.
  • The release waits for the Canary of main. The job the Canary of main of .github/workflows/release-gate.yml is a required check, and runs scripts/release_gate.py on the pull request of the release bot alone; on every other pull request GitHub skips the job, which counts as passed. It reads the runs of the Canary on main while one is unfinished, such as the one that the push of the latest change started, and then passes only when the latest one passed. The check decides when the pull request of the release gets a new head, and the last job of every Canary of main that runs the AI, the release decides again, runs it again when its verdict isn't that of this Canary. So a failed Canary keeps every release back, a release that the maintainer merges too, until a Canary passes again, on Monday or by hand, without a person who runs the check again; the release bot's own auto-merge then merges a release of dependency updates. A Canary that fails after the check passed turns it red again, unless the release merged before. The check fails, rather than waits, after 100 minutes, and the PR coach explains how to run the Canary and the check again.

The release waits for a Canary of the main that it ships, not for one of the update alone: a release ships everything on main, and a Canary that fails for any reason means that the path of an issue through the AI is broken there, or not shown to work.

Consequences

Nobody needs to look at an update of an engine. A broken one stays on main, where only this repository's issues meet it: the push of its merge runs the Canary, a red Canary opens the issue of the bot-health bot and fails the release's check, and the summary of that check names the run and the commit that it ran. Reverting the update on main, or a later update that fixes it, runs the Canary again; the push also updates the release's pull request, whose check passes once that Canary passed. A Canary that failed for a moment needs another run of it and of the check, which the explanation of the check gives as commands.

Codex, Gemini and Copilot aren't checked by a run with a key: the Canary runs Claude, this repository's engine, and there is no key and no canary for each engine, as the maintainer decided on 2026-11-08. What checks them is the week that every update waits, in which most broken releases are pulled or fixed, and engine contracts: the inputs and outputs of the Codex action, the flags of each command line and the keys of the Gemini CLI's settings, that each one stops only for the missing key, and for the lock files of engines/ the signatures and attestations of npm's registry and that npm refuses another hash. What stays a risk, as the security design says: a name that keeps its meaning but changes its behaviour, an answer or a host that changes, which the firewall blocks so that the analysis fails rather than reaches it, and a new indirect dependency of a lock file, which runs with the engine's secret in every repository that uses the engine after the next release. A repository that uses one of those engines sees its failure as an issue without an analysis and a red run of its own; the fix is a revert here and a release.

tests/test_engine_contract.py keeps the rules of Renovate as this record describes them and engine contracts required, and tests/test_release_gate.py keeps the Canary of main required and skipped on every other pull request, and tests what the script decides. Decision 0020 is replaced.