Skip to content

anchor-guard: a stamped tree with no changeset is now a red check - #494

Open
brentrager wants to merge 1 commit into
mainfrom
anchor-guard-requires-changeset
Open

anchor-guard: a stamped tree with no changeset is now a red check#494
brentrager wants to merge 1 commit into
mainfrom
anchor-guard-requires-changeset

Conversation

@brentrager

Copy link
Copy Markdown
Contributor

The guard already checked that a changeset names the right package. It never checked that one exists — and that turned out to be the commoner failure with the identical symptom.

Five in a row

#470, #471, #474, #488 and the polyglot parity work all changed lockstep-stamped trees, merged green, and published nothing. Nothing in this repo distinguishes merged from shipped, so the omission stays invisible until someone reads a stale artifact — the same ending as #348 and #352, reached by a different route.

I contributed to it myself, by reasoning from #470's precedent rather than from the release mechanism. That's the tell that it's a system problem rather than five people being careless.

Why the old exemption bought nothing

The original code skipped the no-changeset case deliberately:

Deliberately conditioned on "carries a changeset". A docs- or test-only PR legitimately has none, and failing those would train everyone to ignore the check.

Sound reasoning, wrong premise: docs- and test-only PRs don't touch a stamped tree. A stamped tree is a manifest's directory (dotnet/server/src); tests live beside it in dotnet/server/tests. The exemption protected a case that was already safe, and cost five silent non-releases.

The old self-test made the same mistake in miniature — it asserted the exemption using dotnet/server/src/Foo.cs while naming the case "docs/test-only". It's replaced by the two cases it was conflating.

Escape hatch

pnpm changeset --empty — the one changesets already ships. An empty changeset declares "this deliberately releases nothing" and passes without naming the anchor: a decision rather than an omission, and no bypass flag for anyone to maintain.

Two failures, two messages

evaluate now returns reason, so "carries NO changeset" and "no changeset names the anchor" read differently. They have different fixes, and a guard that confidently explains the wrong one is a guard people learn to skip.

Verification

anchor-guard self-check: 10 passed

(was 8 — the replaced exemption became three cases: missing-changeset fails, genuinely-docs-only passes, empty-changeset passes.)

The guard passes on this PR: scripts/ is not a stamped tree, so it needs no changeset itself.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LkCz96UfUxcai5RU4LwPnG

The guard already checked that a changeset names the right package. It did
not check that one EXISTS — and that turned out to be the commoner failure
with the same symptom: #470, #471, #474, #488 and the polyglot parity work
all changed lockstep-stamped trees, merged green, and published nothing,
because they carried no changeset at all. Nothing in this repo distinguishes
merged from shipped, so the omission is invisible until someone reads a
stale artifact.

The original exemption was reaching for docs- and test-only PRs, on the
reasoning that failing those would train everyone to ignore the check. In
practice those don't touch a stamped tree: a stamped tree is a manifest's
directory (`dotnet/server/src`), and tests live beside it in
`dotnet/server/tests`. The old self-test asserted the exemption using
`dotnet/server/src/Foo.cs` while calling it "docs/test-only" — the test
itself encoded the wrong assumption, so it's replaced by the two cases it
was conflating.

Escape hatch is the one changesets already ships: `pnpm changeset --empty`
declares "this deliberately releases nothing" and passes without naming the
anchor. A decision rather than an omission, and no bypass flag to maintain.

`evaluate` now returns `reason` so the two failures read differently —
"carries NO changeset" and "no changeset names the anchor" have different
fixes, and a guard that explains the wrong one is a guard people learn to
skip.

Self-check: 10 passed (was 8). The guard passes on this PR — scripts/ is not
a stamped tree, so it needs no changeset itself.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LkCz96UfUxcai5RU4LwPnG
@changeset-bot

changeset-bot Bot commented Aug 18, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: a0cb4af

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant