fix(hygiene): spell the marketplace script's licence header the way the gate reads it - #1354
Merged
os-steve merged 1 commit intoAug 27, 2026
Conversation
…he gate reads it
`scripts/publish-marketplace.mjs` opened with
// Copyright (c) 2026 ObjectStack contributors. Licensed under the Apache-2.0 license.
while `COPYRIGHT_HEADER` in `scripts/check-source-hygiene.mjs` is anchored
/^\/\/ Copyright \(c\) \d{4} ObjectStack\./
which requires the period directly after `ObjectStack`. The file therefore
carried a licence header to every human reader and none at all to the gate.
Normalised to the canonical spelling the regex already defines.
Nothing is red today: `scanHeaderPosition` reads `allTs`, so no `.mjs` is
judged. What the fix removes is a trap — widening the header check to `.mjs`
would have gone red on a file whose header a reviewer had just read and
approved, which is the failure mode that makes people doubt a working gate.
It also collapses a measurement that had two defensible answers. Measured with
the gate's own regex over the eight `.mjs` under `SCANNED`: headerless was 3 of
8 by the gate and 2 of 8 by `grep Copyright`; it is now 2 of 8 by both.
The deviation was one file against 335 carrying the canonical form, and it was
not a deliberate attribution: LICENSE is the stock Apache-2.0 text with its
placeholder unfilled, and the script propagates `license` from `package.json`
rather than any copyright holder, so line 2 never reaches the published payload.
`COPYRIGHT_HEADER` is unchanged and the scanned surface is unchanged.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WMzCeNC4SZcPNBpE2zCVCg
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
os-steve
marked this pull request as ready for review
August 27, 2026 08:47
This was referenced Aug 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1352
scripts/publish-marketplace.mjsopened withwhile
COPYRIGHT_HEADERinscripts/check-source-hygiene.mjs:346is anchoredThe period is required directly after
ObjectStack, so the file carried alicence header to every human reader and none at all to the gate. This
normalises line 2 to the canonical spelling the regex already defines. One line,
one file.
Nothing was red, and nothing turns green — that is the point
scanHeaderPositionis handedallTs(scripts/check-source-hygiene.mjs:565),so no
.mjsis judged at all. The gate's own banner on this branch says so:What the fix removes is a latent trap: widening the header check to
.mjswould have gone red on a file whose header a reviewer had just read and
approved — the failure mode that makes people doubt a working gate.
The premise was re-measured, and the falsifiable half was checked
The card's ruling hangs on "contributors" being a one-file deviation rather than
a deliberate attribution this file requires. Both halves were verified before
editing:
ObjectStack contributorsacross the tree (excluding.git,node_modules, build output): exactly one first-party source file —this one. The only other hit is
.changeset/header-position-prose-integers.md,which describes this defect rather than mandating the spelling.
ObjectStack. Licensed underreturns 340 occurrences across 335 files. The sweep is live, and thedeviation is 1 file against 335.
LICENSEis the stockApache-2.0 text with its
Copyright [yyyy] [name of copyright owner]placeholder unfilled. And the script propagates
licensefrompackage.json(
scripts/publish-marketplace.mjs:208,mp.license ?? pkg.license), never acopyright holder — line 2 never reaches the published marketplace payload. So
this is a typo corrected, not a licence statement changed.
No fork to report.
Verified with the gate's own regex, not by eye
Reading the header by eye is precisely what let it pass for as long as it did, so
the measurement harness lifts the regex literally out of the gate source and
evaluates it — it is never retyped:
Applied to the eight
.mjsunderSCANNED, before and after:scripts/check-lint-i18n-gate.mjsscripts/check-source-hygiene.mjsscripts/check-source-token-ratchet.mjsscripts/check-stackblitz-lock.mjsscripts/lib/main-module.mjsscripts/lib/source-hygiene-surface.mjsscripts/publish-marketplace.mjsscripts/sync-docs-screenshots.mjsThe header lands on line 2, which is the position
scanHeaderPositionwantsfor this file (
#!preamble ⇒want = 2), so a future widening finds it correctin position as well as in spelling.
The deliverable: the two counts converge
"How many
.mjslack a header" had two defensible answers and this file was theentire disagreement. It is now one answer. The two files still headerless are
headerless to reader and regex alike, which is what makes the remaining figure
mean something.
Read-coupling: #1351 rewrites the
scanHeaderPositiondocstring prose thatstates this count, and consumes the 2 of 8 left behind here. That card stays
open and is untouched by this PR — no prose stating the count was edited, and
scripts/check-source-hygiene.mjsis not in this diff.What was deliberately NOT done
COPYRIGHT_HEADERwas not widened to accept "contributors". Loosening agate's predicate so a non-conforming file passes is gate weakening, and it is
the worse answer here: it would preserve one deviant spelling at the cost of
permanently admitting a whole class.
INDENTED_COPYRIGHT_HEADERand the scanned surface are unchanged..mjs. That is a real and defensiblequestion, but a scope change that would light up the other
.mjsat once —this card is its precondition, not the change itself. Worth filing; two files
would need headers first.
Verification
pnpm verifygreen on162ac24— the commit this PR is opened at, re-run afterthe final commit so the figure below belongs to this exact tree:
Run through the shared verify lock:
VERDICT command-exit 0 · held the lock 127s · waited 0s. Exit status captured before any pipe.Changeset has empty frontmatter — the sanctioned "this PR releases nothing"
declaration
changeset-check.ymldocuments. Nosrc/metadata changed: noobject, field, view, label, flow or hook. The
skip-changesetlabel was notapplied.
Generated by Claude Code
Generated by Claude Code