Skip to content

gate pinned its own name and left the other half of the pair unpinned - #806

Merged
MongLong0214 merged 1 commit into
mainfrom
ci-lint-name-guard
Aug 19, 2026
Merged

gate pinned its own name and left the other half of the pair unpinned#806
MongLong0214 merged 1 commit into
mainfrom
ci-lint-name-guard

Conversation

@MongLong0214

Copy link
Copy Markdown
Owner

Follows #805. Closes the other way a required context can stop reporting.

The asymmetry

Protection requires gate and lint. A required context is a check-run name, which GitHub takes from an explicit name: when a job has one and from the job id otherwise.

gate pins its name (ci-gate.test.ts:37). lint did not. That was mine.

The reported hole is already caught; the real one was not

A peer reported the risk as renaming the job id. Tested by making the rename rather than by reading the assertions — lintlinting fails two tests, one here and one in action-lint.test.ts, because both assert jobs.lint exists.

The hole is the other direction:

add `name: pr-lint`, leave the job id as `lint`
  → the check-run becomes `pr-lint`
  → the required context `lint` never reports
  → every PR blocks, with no failing check to explain it
  → all 35 assertions in both files still pass

Reproduced before closing it. A job called lint still sits in the file, which is exactly what both existing assertions look at.

The shape

The name written in the required list and the place that emits it are different places, and only one of them was guarded. Same shape as the matrix-interpolated contexts in #803 and the branches: [dev] near-miss another session hit today — a name and its enforcement site drifting apart.

The assertion

That the job carries no name: — the property is its absence, not an equality. Asserting name === 'lint' would invite someone to add a redundant name: lint, which is one edit from wrong.

Negative control: adding name: pr-lint fails the assertion; restored byte-identical.

Limit, in the commit

This pins where the name comes from, not that the check ever runs. A workflow-level failure before job dispatch produces no check run at all, and neither this nor the trigger assertion sees that.

Full suite green, tsc --noEmit clean.

Branch protection requires two contexts, `gate` and `lint`, and a required
context is a check-run NAME. GitHub takes that name from an explicit `name:`
when a job has one and from the job id otherwise.

`gate` pins its name. `lint` did not, and the asymmetry was mine.

A peer reading this reported the hole as renaming the job id, which is caught:
renaming `lint` to `linting` fails two tests, one here and one in
`action-lint.test.ts`, because both assert `jobs.lint` exists. Checked by making
the rename rather than by reading the assertions.

The hole is the other direction. ADDING `name: pr-lint` while leaving the job id
`lint` breaks the required context exactly as thoroughly -- the check-run
becomes `pr-lint`, the context named `lint` never reports, and every pull
request blocks with no failing check to explain it -- and the whole suite passed
with that edit in place. A job called `lint` still sits in the file, which is
what both existing assertions look at.

This is the shape that keeps turning up: the name written in the required list
and the place that emits it are different places, and only one of them was
guarded.

Record-Id: r-lintcontextname
Provenance: authored
Certainty: firm
Blast: local
Undo: easy
Ruled-out: asserting the name equals "lint" | the job has no `name:` today and should not gain one, so the property is its absence; asserting equality would invite someone to add `name: lint`, which is redundant and one edit from wrong
Ruled-out: leaving it because renaming the id is already caught | that catches one of the two ways the context can stop reporting, and the uncaught one leaves a file that still reads correctly
Limit: this pins where the name comes from, not that the check ever runs. A workflow-level failure before job dispatch produces no check run at all, and neither this nor the trigger assertion sees that
Verified: the hole was reproduced before it was closed -- `name: pr-lint` added to the job left all 35 assertions in both files passing. The peer's reported version was tested too and does not reproduce: renaming the job id fails two assertions. One negative control on the fix, restored with the workflow byte-identical
CommitLore-Version: 2.0.0
@github-actions

Copy link
Copy Markdown

CommitLore — record lint

Trailers: clean — 1 commit in origin/main..3e78376c45490385d3ac381b996eba9bb5ef3d10
Active constraints: 2 limits · 4 ruled-out · 0 warnings — from 3 records over 1 changed path

Limits (2)

  • r-lintcontextname 3e78376 — this pins where the name comes from, not that the check ever runs. A workflow-level failure before job dispatch produces no check run at all, and neither this nor the trigger assertion sees that
  • r-lintpullrequesttrigger 7617436 — this guards the trigger, not the job name. Renaming the lint job leaves the trigger intact and still breaks the required context, and nothing here catches that

Ruled out (4)

  • r-lintcontextname 3e78376 — asserting the name equals "lint" | the job has no name: today and should not gain one, so the property is its absence; asserting equality would invite someone to add name: lint, which is redundant and one edit from wrong
  • r-lintcontextname 3e78376 — leaving it because renaming the id is already caught | that catches one of the two ways the context can stop reporting, and the uncaught one leaves a file that still reads correctly
  • r-lintpullrequesttrigger 7617436 — asserting the trigger inside the release gate instead | that gate deliberately does not know about lint, and teaching it would blur the reason it requires ten
  • r-lintpullrequesttrigger 7617436 — making lint report on pushes to main so it is visible there | it would then run on every squash for no purpose, and the release gate would have to start expecting a context it was written to do without

withheld the content of 1 record(s) graded blocked: a Limit trailer matching an injection pattern is reported, never quoted (SPEC §7)

Trailer violations fail this check. Active constraints are informational — they are what the repository already decided, not a verdict on this PR.

@MongLong0214
MongLong0214 merged commit 0078dd7 into main Aug 19, 2026
13 checks passed
@MongLong0214
MongLong0214 deleted the ci-lint-name-guard branch August 19, 2026 15:52
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