Skip to content

Commit 0162888

Browse files
fix(ci): the invisible-character gate never matched anything (#197)
**Measured 2026-08-27: this gate caught 0 of 6 invisible-character test cases.** It has never detected an NBSP, zero-width space, BOM, soft hyphen, bidi override or word joiner. ## Root cause The pattern used UTF-8 **byte sequences** (`\xc2\xa0`) while `grep -P` matches **characters**. Bytes `c2 a0` are *one* character U+00A0; `\xc2\xa0` asks for *two*, U+00C2 then U+00A0 — never present. ``` grep -P '\xc2\xa0' -> miss grep -P '\x{a0}' -> MATCH ``` Only `\x00` worked, being single-byte in both readings. The gate ran, passed, and could not see what it exists to see. ## Fixed - **codepoint escapes** in place of byte sequences - **C0 controls** `\x01-\x08,\x0B,\x0C,\x0E-\x1F` added (TAB/LF/CR excluded) - **`grep -a`** — without it grep skips any NUL-bearing file as binary The C0 range matters: a stray **backspace byte** made a workflow unparseable in `developer-ecosystem`, so it never ran — and this linter called it clean. Canonical fix: hyperpolymath/empty-linter#70. **2 file(s)** here. **Verified:** YAML re-parsed, and the corrected pattern was confirmed to catch a real NBSP before the change was kept.
1 parent baa45b8 commit 0162888

3 files changed

Lines changed: 34 additions & 47 deletions

File tree

‎.github/workflows/dogfood-gate.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ jobs:
124124
# Checks for: zero-width spaces, zero-width joiners, BOM, soft hyphens,
125125
# non-breaking spaces, null bytes, and other invisible Unicode in source files.
126126
set +e
127-
PATTERNS='\xc2\xa0|\xe2\x80\x8b|\xe2\x80\x8c|\xe2\x80\x8d|\xef\xbb\xbf|\xc2\xad|\xe2\x80\x8e|\xe2\x80\x8f|\xe2\x80\xaa|\xe2\x80\xab|\xe2\x80\xac|\xe2\x80\xad|\xe2\x80\xae|\x00'
127+
PATTERNS='(*UTF)[\x00-\x08\x0B\x0C\x0E-\x1F\x{a0}\x{ad}\x{200b}-\x{200f}\x{202a}-\x{202f}\x{2060}\x{2066}-\x{2069}\x{feff}]'
128128
find "$GITHUB_WORKSPACE" \
129129
-not -path '*/.git/*' -not -path '*/node_modules/*' \
130130
-not -path '*/.deno/*' -not -path '*/target/*' \
@@ -135,7 +135,7 @@ jobs:
135135
-o -name '*.yml' -o -name '*.yaml' -o -name '*.md' -o -name '*.adoc' \
136136
-o -name '*.idr' -o -name '*.zig' -o -name '*.v' -o -name '*.jl' \
137137
-o -name '*.gleam' -o -name '*.hs' -o -name '*.ml' -o -name '*.sh' \) \
138-
-exec grep -Prl "$PATTERNS" {} \; > /tmp/empty-lint-results.txt 2>/dev/null
138+
-exec grep -aPrl "$PATTERNS" {} \; > /tmp/empty-lint-results.txt 2>/dev/null
139139
EL_EXIT=$?
140140
set -e
141141

‎rescript-ecosystem/idaptik-rescript13-staging/.github/workflows/dogfood-gate.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ jobs:
112112
# Checks for: zero-width spaces, zero-width joiners, BOM, soft hyphens,
113113
# non-breaking spaces, null bytes, and other invisible Unicode in source files.
114114
set +e
115-
PATTERNS='\xc2\xa0|\xe2\x80\x8b|\xe2\x80\x8c|\xe2\x80\x8d|\xef\xbb\xbf|\xc2\xad|\xe2\x80\x8e|\xe2\x80\x8f|\xe2\x80\xaa|\xe2\x80\xab|\xe2\x80\xac|\xe2\x80\xad|\xe2\x80\xae|\x00'
115+
PATTERNS='(*UTF)[\x00-\x08\x0B\x0C\x0E-\x1F\x{a0}\x{ad}\x{200b}-\x{200f}\x{202a}-\x{202f}\x{2060}\x{2066}-\x{2069}\x{feff}]'
116116
find "$GITHUB_WORKSPACE" \
117117
-not -path '*/.git/*' -not -path '*/node_modules/*' \
118118
-not -path '*/.deno/*' -not -path '*/target/*' \
@@ -123,7 +123,7 @@ jobs:
123123
-o -name '*.yml' -o -name '*.yaml' -o -name '*.md' -o -name '*.adoc' \
124124
-o -name '*.idr' -o -name '*.zig' -o -name '*.v' -o -name '*.jl' \
125125
-o -name '*.gleam' -o -name '*.hs' -o -name '*.ml' -o -name '*.sh' \) \
126-
-exec grep -Prl "$PATTERNS" {} \; > /tmp/empty-lint-results.txt 2>/dev/null
126+
-exec grep -aPrl "$PATTERNS" {} \; > /tmp/empty-lint-results.txt 2>/dev/null
127127
EL_EXIT=$?
128128
set -e
129129
Lines changed: 30 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,38 @@
11
# SPDX-License-Identifier: MPL-2.0
2-
name: npm/bun Blocker
3-
on: [push, pull_request]
2+
#
3+
# Authored replacement, 2026-08-28. The previous file contained a literal
4+
# backspace byte (0x08) inside a regex, which made the YAML unloadable - so
5+
# this workflow NEVER RAN in its entire history, while reporting nothing.
6+
# Removing the byte exposed further structural errors, so it was rewritten
7+
# against the corrected estate template rather than patched.
8+
name: npm/pnpm/yarn Blocker
9+
on:
10+
push:
11+
branches: [main]
12+
pull_request:
13+
14+
concurrency:
15+
group: ${{ github.workflow }}-${{ github.ref }}
16+
cancel-in-progress: true
17+
18+
permissions:
19+
contents: read
20+
421
jobs:
522
check:
623
runs-on: ubuntu-latest
24+
timeout-minutes: 10
25+
permissions:
26+
contents: read
727
steps:
8-
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
9-
10-
- name: Check for npm/bun usage in new files
28+
- uses: actions/checkout@v7.0.1
29+
- name: Block npm/pnpm/yarn lockfiles
1130
run: |
12-
# Check for new bun.lockb files
13-
NEW_BUN=$(git diff --name-only --diff-filter=A HEAD~1 2>/dev/null | grep -E 'bun\.lockb$' || true)
14-
15-
# Check for npm scripts calling npm/bun in new or modified files
16-
NPM_CALLS=$(git diff HEAD~1 2>/dev/null | grep -E '^\+.*(npm|bun)\s+(run|install|start|test|build)' | grep -v '#' || true)
17-
18-
ERRORS=""
19-
20-
if [ -n "$NEW_BUN" ]; then
21-
ERRORS="${ERRORS}New bun.lockb detected. Use Deno instead.
22-
${NEW_BUN}
23-
"
24-
fi
25-
26-
if [ -n "$NPM_CALLS" ]; then
27-
ERRORS="${ERRORS}npm/bun commands in new code. Use Deno tasks instead.
28-
${NPM_CALLS}
29-
"
30-
fi
31-
32-
if [ -n "$ERRORS" ]; then
33-
echo -e "$ERRORS"
34-
echo ""
35-
echo "Per language policy, use Deno instead of npm/bun for:"
36-
echo " - Package management: deno.json imports"
37-
echo " - Task running: deno task <name>"
38-
echo " - Scripts: deno run script.ts"
31+
# Bun is tier 1 (owner ruling 2026-08-26): package.json + bun.lock are
32+
# EXPECTED. Only npm/pnpm/yarn lockfiles are rejected. .npmrc is
33+
# allowed - Bun reads it for private-registry auth.
34+
if [ -f "package-lock.json" ] || [ -f "pnpm-lock.yaml" ] || [ -f "yarn.lock" ]; then
35+
echo "❌ npm/pnpm/yarn artifacts detected. Use Bun (package.json + bun.lock) instead."
3936
exit 1
4037
fi
41-
42-
echo "Deno policy enforced (no new npm/bun usage)"
43-
44-
- name: Verify deno.json exists
45-
run: |
46-
if [ ! -f "deno.json" ]; then
47-
echo "Warning: deno.json not found"
48-
echo "Consider adding deno.json for Deno configuration"
49-
else
50-
echo "deno.json found"
51-
fi
38+
echo "✅ No npm/pnpm/yarn violations"

0 commit comments

Comments
 (0)