diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3d0dc80..6a0e10b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -58,16 +58,15 @@ jobs: env: BASE_SHA: ${{ github.event.pull_request.base.sha }} run: | - # Local paths and session identifiers. local_data='/home/[A-Za-z0-9._-]+/|/Users/[A-Za-z0-9._-]+/|session_[0-9A-Za-z]{12,}|claude\.ai/code/session|/tmp/claude-[0-9]' - # Any address, not a handful of consumer domains: a corporate or self-hosted - # address is somebody's just as much as a gmail one. The last label must look like - # a TLD, so `claude_code@2.1.263.json` and `pkg@1.2.3.tar.gz` are not matches. email='[A-Za-z0-9._%+-]+@[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*\.[A-Za-z]{2,24}' - # Addresses that identify a service rather than a person. - allowed='@users\.noreply\.github\.com$|^noreply@anthropic\.com$|^support@github\.com$|^noreply@github\.com$' # Suffixes that make a match a file path rather than an address. not_mail='\.(json|ya?ml|md|txt|py|js|ts|tsx|sh|toml|cfg|ini|lock|log|csv|tsv|html?|svg|png|jpe?g|gif|pdf|zip|gz|tar|whl|so|dll|exe)$' + # Addresses that identify a service rather than a person. + service='@users\.noreply\.github\.com$|^noreply@anthropic\.com$|^support@github\.com$|^noreply@github\.com$' + # The maintainer's personal address, as a SHA-256 digest: writing it here in the + # clear would publish it more prominently than the commits this check guards. + blocked_digest='ecda4887099c1a8d73af02994c42938dfb0a1857674f6c3a6403af922360104f' found=0 while read -r sha; do msg=$(git log -1 --format=%B "$sha") @@ -76,10 +75,21 @@ jobs: echo "::error::commit $sha contains a local path or session identifier" found=1 fi - if printf '%s' "$msg" | grep -oiE "$email" | grep -ivE "$not_mail" | grep -qivE "$allowed"; then - echo "::error::commit $sha contains an email address; sign off with your GitHub noreply address" + # A sign-off is somebody's own attestation, so a contributor's address there is + # their choice and stays allowed. Anywhere else an address arrived by accident -- + # pasted from a log, a stack trace, or a quoted report. + body=$(printf '%s' "$msg" | grep -viE '^(Signed-off-by|Co-Authored-By|Reported-by|Reviewed-by|Tested-by|Acked-by):') + if printf '%s' "$body" | grep -oiE "$email" | grep -ivE "$not_mail" | grep -qivE "$service"; then + echo "::error::commit $sha contains an email address outside a sign-off trailer" found=1 fi + while read -r addr; do + [ -n "$addr" ] || continue + if [ "$(printf '%s' "$addr" | tr '[:upper:]' '[:lower:]' | sha256sum | cut -d' ' -f1)" = "$blocked_digest" ]; then + echo "::error::commit $sha contains the maintainer's personal address; sign off with the GitHub noreply address" + found=1 + fi + done <<< "$(printf '%s' "$msg" | grep -oiE "$email")" done < <(git rev-list --no-merges "$BASE_SHA..HEAD") exit "$found" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cde1247..b0905c0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -244,6 +244,19 @@ file it lives in, so you can go straight there instead of hunting: and, for efficacy, the run manifest under `efficacy/` — and adding it to that directory's `SUMMARY.md` extends the sample without touching the format itself. +## Figures + +Every figure under `docs/figures/` is generated from this repository's own data by a script here, +shipped as a light and a dark SVG, and regenerated in CI so a stale figure fails the build. If you +are changing one, read the standard first — it explains the palette, why absence is never drawn as +a weak grade, and why colour is never the only carrier of meaning: + +https://github.com/open-coder-ai/.github/blob/main/VISUAL.md + +`docs/figures/palette.py` and `make_family.py` are shared across every open-coder-ai repository and +carried byte-identically. Change them at the source and copy them out; never edit one copy, and +never add a per-repo lint or format exclude to work around them. + ## Code of Conduct Be kind, be curious, assume good faith. The full text is in diff --git a/docs/figures/palette.py b/docs/figures/palette.py index e5ff671..c52b6d1 100644 --- a/docs/figures/palette.py +++ b/docs/figures/palette.py @@ -1,5 +1,8 @@ """The one visual language every open-coder-ai figure is drawn in. +The standard this implements, and the reasoning behind each rule: +https://github.com/open-coder-ai/.github/blob/main/VISUAL.md + Four repositories carry this file byte-identically while configuring `ruff format` at three different line lengths (88, 100 and 120), so no formatted output could satisfy all of them. Every statement here therefore fits on a single line under 88 characters and