🤖 Generated by the Daily AI Engineer
Evidence
#653 is fixed: all 10 repos consuming create-release.yaml now carry the bang-breaking
configuration in their own .releaserc, verified live on main in each.
Nothing prevents that from silently reverting. Each .releaserc is an ordinary file in an ordinary
repo; a refactor, a template sync, or a well-meant "simplify the config" PR could drop the
parserOpts/releaseRules block, and nothing would notice — the repo would go back to
producing no release at all for feat!:, and the first sign would be a breaking change shipping
unversioned. That is exactly how the original bug went unnoticed across 10 repos.
The delivery-side central fix was rejected on its merits (#655): rewriting a consumer's config had
to be correct for every possible config shape, and it wasn't. A central guard is a different
proposition — it only has to read.
Audience & problem
Every repo releasing through create-release.yaml. The failure is silent, and the blast radius is
"a breaking change shipped without a major version", which consumers discover the hard way.
Hypothesis
A read-only assertion in the shared workflow catches drift the moment it happens, at no risk to the
release path — because it changes nothing.
Proposed direction
In create-release.yaml, before semantic-release runs, warn (not fail) when the resolved config
has no bang handling:
.releaserc-shaped JSON or package.json's release key with no breakingHeaderPattern on
@semantic-release/commit-analyzer → emit a ::warning:: naming the fix.
- Non-JSON config, or one relying on default plugins → say nothing. The guard must not become the
thing that fails releases; that is what the previous attempt got wrong.
Warn rather than fail deliberately: a repo may have a considered reason not to want it, and a shared
workflow that hard-fails on a config preference is the same overreach as rewriting the config.
An enforce-breaking-bang input (default-off) could upgrade it to an error for repos that want the
stronger guarantee.
Acceptance criteria
Size
Small — read-only, one step, no new dependencies.
Follows #653; informed by #655.
Evidence
#653 is fixed: all 10 repos consuming
create-release.yamlnow carry the bang-breakingconfiguration in their own
.releaserc, verified live onmainin each.Nothing prevents that from silently reverting. Each
.releasercis an ordinary file in an ordinaryrepo; a refactor, a template sync, or a well-meant "simplify the config" PR could drop the
parserOpts/releaseRulesblock, and nothing would notice — the repo would go back toproducing no release at all for
feat!:, and the first sign would be a breaking change shippingunversioned. That is exactly how the original bug went unnoticed across 10 repos.
The delivery-side central fix was rejected on its merits (#655): rewriting a consumer's config had
to be correct for every possible config shape, and it wasn't. A central guard is a different
proposition — it only has to read.
Audience & problem
Every repo releasing through
create-release.yaml. The failure is silent, and the blast radius is"a breaking change shipped without a major version", which consumers discover the hard way.
Hypothesis
A read-only assertion in the shared workflow catches drift the moment it happens, at no risk to the
release path — because it changes nothing.
Proposed direction
In
create-release.yaml, before semantic-release runs, warn (not fail) when the resolved confighas no bang handling:
.releaserc-shaped JSON orpackage.json'sreleasekey with nobreakingHeaderPatternon@semantic-release/commit-analyzer→ emit a::warning::naming the fix.thing that fails releases; that is what the previous attempt got wrong.
Warn rather than fail deliberately: a repo may have a considered reason not to want it, and a shared
workflow that hard-fails on a config preference is the same overreach as rewriting the config.
An
enforce-breaking-banginput (default-off) could upgrade it to an error for repos that want thestronger guarantee.
Acceptance criteria
warning noise, no failure.
is worthless; one that always fires is noise).
Size
Small — read-only, one step, no new dependencies.
Follows #653; informed by #655.