Skip to content

Commit 2f93bdb

Browse files
fix(ci): rsr-antipattern.yml duplicate heredoc (#6)
* fix(ci): rsr-antipattern.yml duplicate heredoc **rsr-antipattern.yml**: deletes the orphan duplicate Python script (lines 274-428) that escapes the heredoc and exits 127. Mirrors hyperpolymath/rsr-template-repo#39. 🤖 Generated with [Claude Code](https://claude.com/claude-code) * fix(ci): repair corrupted rsr-antipattern.yml on this branch Repairs the corrupted `rsr-antipattern.yml` from the prior commit on this branch. See hyperpolymath/stapeln#34 for the full root-cause writeup — the original sweep built its canonical via `gh api --jq '.content'` piped through PowerShell, but `gh` line-wraps base64 in the terminal pipe, so each chunk was decoded separately and the rejoined file has mid-word line breaks (`# SPDX-License-Id\nentifier:`, `name: RSR A\nnti-Pattern`, etc.). GitHub Actions can't parse the resulting YAML — the workflow completes in 0 seconds with no jobs. This commit overwrites the file with the correct content, built via raw byte download (`Accept: application/vnd.github.raw`) and `[System.IO.File]::WriteAllBytes` so no pipe ever touches the bytes. Round-trip byte-verified against canonical.
1 parent 6c235ff commit 2f93bdb

1 file changed

Lines changed: 55 additions & 102 deletions

File tree

.github/workflows/rsr-antipattern.yml

Lines changed: 55 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,30 @@
11
# SPDX-License-Identifier: PMPL-1.0-or-later
2-
name: RSR Language Policy
2+
# RSR Anti-Pattern CI Check
3+
# SPDX-License-Identifier: PMPL-1.0-or-later
4+
#
5+
# Enforces: No TypeScript, No Go, No Python (except SaltStack), No npm
6+
# Allows: ReScript, Deno, WASM, Rust, OCaml, Haskell, Guile/Scheme
7+
8+
name: RSR Anti-Pattern Check
39

410
on:
511
push:
6-
branches: [main]
12+
branches: [main, master, develop]
713
pull_request:
8-
branches: [main]
14+
branches: [main, master, develop]
15+
916

1017
permissions:
1118
contents: read
1219

1320
jobs:
14-
check-banned-patterns:
15-
name: Check for banned languages/patterns
21+
antipattern-check:
1622
runs-on: ubuntu-latest
23+
permissions:
24+
contents: read
1725
steps:
18-
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
19-
26+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
27+
2028
- name: Check for TypeScript
2129
run: |
2230
python3 << 'PYEOF'
@@ -130,112 +138,57 @@ jobs:
130138
print(f"✅ No TypeScript files outside allowlist ({len(exemption_patterns)} per-repo exemption(s) parsed).")
131139
PYEOF
132140
133-
# Universal builtin allowlist — bridges that need no per-repo declaration.
134-
# Files matching any of these patterns are always allowed.
135-
BUILTIN_GLOBS = [
136-
'*.d.ts',
137-
'**/bindings/**',
138-
'**/tests/**', '**/test/**',
139-
'**/scripts/**',
140-
'**/mcp-adapter/**',
141-
'**/*vscode*/**',
142-
'**/cli/**',
143-
'**/mod.ts',
144-
'**/lsp-server.ts', '**/lsp_server.ts', '**/lsp.ts', '**/*-lsp.ts',
145-
'**/deno-*/**',
146-
'**/node_modules/**',
147-
'**/vendor/**',
148-
'**/examples/**',
149-
'**/ffi/**',
150-
]
151-
152-
# Per-repo exemptions parsed from .claude/CLAUDE.md "TypeScript Exemptions" table.
153-
# Single source of truth — adding a row here unblocks CI for that path.
154-
# Format expected:
155-
# ### TypeScript Exemptions ...
156-
# | Path | Files | Rationale | Unblock condition |
157-
# |---|---|---|---|
158-
# | `path/to/file.ts` | 1 | ... | ... |
159-
# | `dir/*.ts` | 6 | ... | ... |
160-
exemptions = []
161-
claude_md = pathlib.Path('.claude/CLAUDE.md')
162-
if claude_md.exists():
163-
in_table = False
164-
for line in claude_md.read_text(encoding='utf-8').splitlines():
165-
if re.search(r'TypeScript [Ee]xemptions', line):
166-
in_table = True
167-
continue
168-
if in_table and line.startswith(('### ', '## ', '# ')):
169-
break
170-
if in_table and line.startswith('|'):
171-
m = re.match(r'\|\s*`([^`]+)`', line)
172-
if m:
173-
exemptions.append(m.group(1))
174-
175-
# Find all .ts and .tsx files
176-
found = []
177-
for ext in ('ts', 'tsx'):
178-
found.extend(str(p) for p in pathlib.Path('.').rglob(f'*.{ext}'))
179-
180-
def allowed(path):
181-
p = path.lstrip('./')
182-
for g in BUILTIN_GLOBS + exemptions:
183-
if fnmatch.fnmatchcase(p, g):
184-
return True
185-
# also treat glob ending with / as a directory prefix
186-
base = g.rstrip('/').rstrip('*').rstrip('/')
187-
if base and (p == base or p.startswith(base + '/')):
188-
return True
189-
return False
190-
191-
bad = sorted(f for f in found if not allowed(f))
192-
if bad:
193-
print("❌ TypeScript files detected outside the allowlist.\n")
194-
for f in bad:
195-
print(f" {f}")
196-
print()
197-
print("To resolve, either:")
198-
print(" (a) migrate the file to AffineScript")
199-
print(" (see Human_Programming_Guide.adoc migration chapter), OR")
200-
print(" (b) move it to an allowlisted bridge path")
201-
print(" (bindings/, tests/, scripts/, mcp-adapter/, *vscode*/, cli/, deno-*/, etc.), OR")
202-
print(" (c) add an entry to the 'TypeScript Exemptions' table in .claude/CLAUDE.md")
203-
print(" with rationale + unblock condition.")
204-
if exemptions:
205-
print(f"\n(Currently {len(exemptions)} exemption(s) parsed from .claude/CLAUDE.md.)")
206-
sys.exit(1)
207-
print(f"✅ No TypeScript files outside allowlist ({len(exemptions)} per-repo exemption(s) parsed).")
208-
PYEOF
209-
210141
- name: Check for Go
211142
run: |
212143
if find . -name "*.go" | grep -q .; then
213-
echo "::error::Go files found! Use Rust instead (per RSR policy)"
144+
echo "❌ Go files detected - use Rust/WASM instead"
145+
find . -name "*.go"
214146
exit 1
215147
fi
216-
echo " No Go files found"
217-
218-
- name: Check for npm/Node artifacts
148+
echo " No Go files"
149+
150+
- name: Check for Python (non-SaltStack)
219151
run: |
220-
if [ -f "package-lock.json" ] || [ -d "node_modules" ]; then
221-
echo "::error::npm artifacts found! Use Deno instead (per RSR policy)"
152+
PY_FILES=$(find . -name "*.py" | grep -v salt | grep -v _states | grep -v _modules | grep -v pillar | grep -v venv | grep -v __pycache__ || true)
153+
if [ -n "$PY_FILES" ]; then
154+
echo "❌ Python files detected - only allowed for SaltStack"
155+
echo "$PY_FILES"
222156
exit 1
223157
fi
224-
echo " No npm artifacts found"
225-
226-
- name: Check for Python (non-SaltStack)
158+
echo " No non-SaltStack Python files"
159+
160+
- name: Check for npm lockfiles
227161
run: |
228-
banned_py=$(find . -name "*.py" | grep -v -E "(salt|pillar|states|_modules|_states)" | head -1)
229-
if [ -n "$banned_py" ]; then
230-
echo "::error::Python files found outside SaltStack! Use ReScript/Rust (per RSR policy)"
162+
if [ -f "package-lock.json" ] || [ -f "yarn.lock" ]; then
163+
echo "❌ npm/yarn lockfile detected - use Deno instead"
231164
exit 1
232165
fi
233-
echo " No banned Python files found"
234-
235-
- name: Check for Makefiles
166+
echo " No npm lockfiles"
167+
168+
- name: Check for tsconfig
236169
run: |
237-
if [ -f "Makefile" ] || [ -f "makefile" ] || find . -name "*.mk" | grep -q .; then
238-
echo "::error::Makefile found! Use Justfile or Mustfile instead (per RSR policy)"
170+
if [ -f "tsconfig.json" ]; then
171+
echo "❌ tsconfig.json detected - use ReScript instead"
239172
exit 1
240173
fi
241-
echo "✓ No Makefiles found"
174+
echo "✅ No tsconfig.json"
175+
176+
- name: Verify Deno presence (if package.json exists)
177+
run: |
178+
if [ -f "package.json" ]; then
179+
if [ ! -f "deno.json" ] && [ ! -f "deno.jsonc" ]; then
180+
echo "⚠️ Warning: package.json without deno.json - migration recommended"
181+
fi
182+
fi
183+
echo "✅ Deno configuration check complete"
184+
185+
- name: Summary
186+
run: |
187+
echo "╔════════════════════════════════════════════════════════════╗"
188+
echo "║ RSR Anti-Pattern Check Passed ✅ ║"
189+
echo "║ ║"
190+
echo "║ Allowed: ReScript, Deno, WASM, Rust, OCaml, Haskell, ║"
191+
echo "║ Guile/Scheme, SaltStack (Python) ║"
192+
echo "║ ║"
193+
echo "║ Blocked: TypeScript, Go, npm, Python (non-Salt) ║"
194+
echo "╚════════════════════════════════════════════════════════════╝"

0 commit comments

Comments
 (0)