Commit 64011dd
* feat(devx): check:published-files gates an exports map retrofitted onto an already-published package
GATED asserts an `exports` map exists; it is silent on the TRANSITION, and the
transition is where the damage is. 17.3.0 added a map to `@objectstack/cli`,
which had published without one, and every deep path a consumer reached through
`dist/` stopped resolving at once -- found after publish, by the consumer,
twice (#13662, #15325).
ANNOUNCED is the second half of #15589, ruled B1 on #15715: a base-vs-HEAD
comparison, the same shape `check-adr-0087-registration --base` already uses,
and deliberately not `git log -S` archaeology. A `package.json` absent at the
merge base -- or present but private/unnamed there -- is born-sealed and passes,
because it has no published predecessor whose consumers could be deep-importing
it. Measured when #15715 was filed: 69 publishable packages declare a map from
51 introducing commits, but 56 were born with it and only 13 retrofitted, from
7 commits. Gating all 51 would demand a consumer note 44 times from packages
that had no consumers, every one of them on a new-package PR -- and a gate
answered by boilerplate 44 times out of 51 has stopped being read by the 7th
time it matters.
What the announcement must say is checked against the head map rather than for
a form of words: a `minor`-or-greater changeset on the package whose body names
a deep specifier the new map does NOT resolve. Naming a path that still
resolves tells a consumer nothing and does not satisfy it.
Absence is never a pass (#4690). Every way the base read can fail -- no
`origin/main`, no merge base, an unreadable `.changeset/` -- makes every package
look born-sealed and the clause vacuously green, so each is a refusal that names
itself, and the read carries its own census control (BASE_READ_FLOOR) exactly as
GATED carries EXPORTS_CENSUS_FLOOR. In CI the base comes from `Lint & Repo
Gates` checking out at `fetch-depth: 0`.
Claude-Session: https://claude.ai/code/session_01PU9zBGbH2s2ZtxSyu963M3
Co-authored-by: Claude <noreply@anthropic.com>
* fix(devx): only the changesets a change introduces can announce what it narrows
Measured while ablating the clause: a real `./console` subpath removal went
GREEN because an unrelated changeset already on main contained the string
`./console` in a sentence about a different release. The pending stock is ~1300
files of prose about these same packages, so "some changeset mentions this path"
is satisfied by accident constantly -- the boilerplate-answered gate this clause
exists to avoid, reached from the other direction.
The subject is now the diff: a changeset absent at the merge base, or one whose
text differs from its base copy. The removal half also reads the changeset BODY
rather than the whole file, since the frontmatter names the package on every
changeset and would otherwise let the bump line answer the note.
Nothing in the file is exported any more either. `check:entry-guard`'s second
rule is that a `scripts/**` file exporting a binding can be imported for it,
whereupon this gate's top-level dispatch -- and its `process.exit` -- runs inside
the importer; the self-test is in the same module and needs no exports.
Claude-Session: https://claude.ai/code/session_01PU9zBGbH2s2ZtxSyu963M3
Co-authored-by: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 2648774 commit 64011dd
1 file changed
Lines changed: 786 additions & 3 deletions
0 commit comments