diff --git a/.github/workflows/no-emdash.yml b/.github/workflows/no-emdash.yml index 3e1b79f..68d2a0d 100644 --- a/.github/workflows/no-emdash.yml +++ b/.github/workflows/no-emdash.yml @@ -9,9 +9,28 @@ name: Em-dash gate # `docs-content/` pages that publish to docs.cosyte.com. A sweep without the gate grows # back; a gate without the sweep would have red-flagged CI on arrival. Both are one commit. # +# WHAT ACTUALLY SCANS, AND WHERE THE RULE LIVES. `pnpm check:no-emdash`, which is this +# repository's own gate script. The jobs below delegate the plumbing (checkout, pnpm, +# Node) to the shared gate workflow, and that workflow carries no pattern, no allow-list +# and no file selection of its own: it prepares the tree, runs the command, and lets the +# command's exit status decide the job. So the rule and every measurement above stay in +# this repository, and only the harness is shared. +# +# TWO CONTEXTS, NOT ONE, AND THE JOB ID IS LOAD-BEARING. A called job's check run is named +# ` / `, so the job id `no-emdash` below publishes +# `no-emdash / tracked-files` and `no-emdash / messages`. A branch ruleset binds to those +# exact strings: renaming the job detaches the requirement with no error anywhere, and a +# required context nothing emits blocks every pull request. Do not rename it. +# +# `no-emdash / tracked-files` is the half that is safe to require and the one that blocks +# a merge. `no-emdash / messages` runs, reds its own context, and is deliberately NOT +# required: Dependabot composes a pull request body out of upstream release notes, em +# dashes included, and a gate that fails on someone else's clock becomes a tax. The +# detection is unchanged either way; only what blocks is narrowed. +# # WHY A SEPARATE WORKFLOW, and not a job in ci.yml: # -# The reusable pipeline is not an option. astm's `ci` job calls +# The shared ci pipeline is not an option. astm's `ci` job calls # cosyte/.github/.github/workflows/ci.yml@main, which runs a fixed ladder and no # arbitrary repo script. # @@ -24,8 +43,7 @@ name: Em-dash gate # typo in a PR description is a large cost for no extra safety. Same call hl7 and # website made, for the same reason. # -# Run it locally with `pnpm check:no-emdash`, which is also on `scripts/verify.sh astm`'s -# ladder in the meta-repo. +# Run it locally with `pnpm check:no-emdash`. on: push: @@ -39,45 +57,16 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true -permissions: - contents: read - jobs: + # The check-run context prefix. See the note above before touching this id. no-emdash: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - with: - # Full history: the commit-message step below reads the PR's commit range, - # and the default shallow clone does not contain the base commit. - fetch-depth: 0 - - - name: Check tracked files - run: bash scripts/check-no-emdash.sh - - # The rule names commit messages explicitly, and a squash merge composes its - # message from the PR title, the PR body, and the branch commits, so all three are - # checked. Pull requests only: on a push to main the message is already written, - # and this gate exists to stop it landing. - - name: Check PR title, body, and commit messages - if: github.event_name == 'pull_request' - env: - PR_TITLE: ${{ github.event.pull_request.title }} - PR_BODY: ${{ github.event.pull_request.body }} - BASE_SHA: ${{ github.event.pull_request.base.sha }} - HEAD_SHA: ${{ github.event.pull_request.head.sha }} - run: | - # Collect first, scan second, and set the shell options here rather than trust - # the runner's default: piping the collection straight into the scanner would - # hide a failed `git log` (a rewritten base commit, or a future edit that drops - # fetch-depth) behind a clean title and body, and the gate would print OK over - # commits it never read. The title and body arrive through env and are never - # interpolated into the script, so a PR description cannot inject shell. - set -euo pipefail - { - printf '%s\n' "$PR_TITLE" - printf '%s\n' "$PR_BODY" - git log --format=%B "$BASE_SHA..$HEAD_SHA" - } > "$RUNNER_TEMP/pr-messages.txt" - bash scripts/check-no-emdash.sh --stdin "the PR title, body, or commit messages" \ - < "$RUNNER_TEMP/pr-messages.txt" + # Pinned to the 40 character commit, not to the tag beside it: a tag can be moved + # or deleted by anyone who gains write access to the workflow's repository, so a + # tag is not an immutable reference and is not a pin. The trailing comment is the + # published reference that commit was released as, so the release note stays + # findable from here. + uses: cosyte/.github/.github/workflows/gate-no-emdash.yml@84ecccd771cbc9c1ece003a3f8ff61415360395b # workflows-2026-09-18-84ecccd771cb + # No more than the scan needs. A called workflow's GITHUB_TOKEN can only be + # downgraded by its caller, and this gate reads the tree and nothing else. + permissions: + contents: read diff --git a/.github/workflows/no-internal-refs.yml b/.github/workflows/no-internal-refs.yml index 00fa317..3d18926 100644 --- a/.github/workflows/no-internal-refs.yml +++ b/.github/workflows/no-internal-refs.yml @@ -16,7 +16,21 @@ name: Public-surface gate # SUCH GATE AT ALL until this workflow landed, which is why the class had regrown into the # doc comments of fifteen source files and into the published `dist/index.d.ts`. # -# WHY A SEPARATE WORKFLOW, and not a job in ci.yml. The reusable pipeline is not an option: +# WHAT ACTUALLY SCANS, AND WHERE THE RULE LIVES. `pnpm check:no-internal-refs`, which is +# this repository's own checker. The job below delegates the plumbing (checkout, pnpm, +# Node) to the shared gate workflow, which carries no pattern, no allow-list and no file +# selection of its own: it prepares the tree, runs the command, and lets the command's +# exit status decide the job. The detection rules, the self-tests and the known project +# prefixes all stay here, because what counts as a project prefix and what counts as a +# domain designator is a property of this package. +# +# THE JOB ID IS LOAD-BEARING. A called job's check run is named +# ` / `, so the job id `no-internal-refs` below publishes +# `no-internal-refs / public-surface`, which is the context a branch ruleset must require. +# Renaming the job detaches that requirement with no error anywhere, and a required +# context nothing emits blocks every pull request. +# +# WHY A SEPARATE WORKFLOW, and not a job in ci.yml. The shared ci pipeline is not an option: # this repo's `ci` job calls cosyte/.github/.github/workflows/ci.yml@main, which runs a # fixed ladder and no arbitrary repo script. Adding this there would also flip every other # caller red on its next run, and remediating each repo is its own deliberate piece of work. @@ -40,8 +54,7 @@ name: Public-surface gate # workflow name instead blocks every pull request permanently, because no check run ever # reports under it. That trap has fired live in a sibling repo on this exact workflow. # -# Run it locally with `pnpm check:no-internal-refs`, which is also on the meta-repo's -# `scripts/verify.sh astm` ladder. +# Run it locally with `pnpm check:no-internal-refs`. on: push: @@ -53,25 +66,16 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true -permissions: - contents: read - jobs: - # The job id is the check-run context name a branch ruleset requires. Renaming it - # silently detaches the required check, so the ruleset stops protecting anything while - # still looking configured. Rename both together or neither. + # The check-run context prefix. See the note above before touching this id. no-internal-refs: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - - # The script self-tests before it reports: it proves each rule still matches its own - # positive sample AND still lets through the reference material it was most likely to - # destroy (`ASTM-E1394`, `CLSI-LIS01`, `LIS02-A2`, the `SPEC-7` / `ACC-42` example - # ids, `ICD-10-CM`, a Phase III trial, and E1381's own establishment / transfer / - # termination protocol phases). It also asserts that no rule matches a BARE section - # citation, so closing that deliberate hole has to be a decision rather than an - # accident. It refuses to print OK from a scan that did not read all of its input. - # No `|| true`, no `continue-on-error`: a check that cannot fail is documentation. - - name: Check the public surface - run: bash scripts/check-no-internal-refs.sh + # Pinned to the 40 character commit, not to the tag beside it: a tag can be moved + # or deleted by anyone who gains write access to the workflow's repository, so a + # tag is not an immutable reference and is not a pin. The trailing comment is the + # published reference that commit was released as, so the release note stays + # findable from here. + uses: cosyte/.github/.github/workflows/gate-no-internal-refs.yml@84ecccd771cbc9c1ece003a3f8ff61415360395b # workflows-2026-09-18-84ecccd771cb + # No more than the scan needs. A called workflow's GITHUB_TOKEN can only be + # downgraded by its caller, and this gate reads the tree and nothing else. + permissions: + contents: read