@@ -33,38 +33,85 @@ jobs:
3333
3434 - name : Check for TypeScript
3535 run : |
36- # Allowlist (TS legitimate as a bridge/adapter to a non-ReScript ecosystem):
37- # bindings/ - language bindings (Deno/TS/AssemblyScript FFI)
38- # *.d.ts - TypeScript type declarations for ReScript FFI
39- # tests/, test/ - Deno test runners
40- # scripts/ - Deno build scripts
41- # mcp-adapter/ - MCP server adapters (MCP is Deno/TS-typed by spec)
42- # *vscode* - VSCode extensions (TS is the ecosystem default)
43- # cli/ - CLI entry points (Deno scripts)
44- # mod.ts - canonical Deno module entrypoint
45- # *lsp-server.ts, *lsp.ts - Language Server Protocol implementations
46- # deno-*/ - subprojects explicitly named for Deno
47- TS_FILES=$(find . \( -name "*.ts" -o -name "*.tsx" \) \
48- | grep -v node_modules \
49- | grep -v '/bindings/' \
50- | grep -v '\.d\.ts$' \
51- | grep -v '/tests/' \
52- | grep -v '/test/' \
53- | grep -v '/scripts/' \
54- | grep -v '/mcp-adapter/' \
55- | grep -Ev '/[^/]*vscode[^/]*/' \
56- | grep -v '/cli/' \
57- | grep -v '/mod\.ts$' \
58- | grep -Ev 'lsp[-_]?server\.ts$' \
59- | grep -Ev '[/-]lsp\.ts$' \
60- | grep -Ev '/deno-[^/]+/' \
61- || true)
62- if [ -n "$TS_FILES" ]; then
63- echo "❌ TypeScript files detected - use ReScript instead"
64- echo "$TS_FILES"
65- exit 1
66- fi
67- echo "✅ No TypeScript files outside allowlisted bridge/adapter paths"
36+ python3 << 'PYEOF'
37+ import re, sys, fnmatch, pathlib
38+
39+ # Universal builtin allowlist — bridges that need no per-repo declaration.
40+ # Files matching any of these patterns are always allowed.
41+ BUILTIN_GLOBS = [
42+ '*.d.ts',
43+ '**/bindings/**',
44+ '**/tests/**', '**/test/**',
45+ '**/scripts/**',
46+ '**/mcp-adapter/**',
47+ '**/*vscode*/**',
48+ '**/cli/**',
49+ '**/mod.ts',
50+ '**/lsp-server.ts', '**/lsp_server.ts', '**/lsp.ts', '**/*-lsp.ts',
51+ '**/deno-*/**',
52+ '**/node_modules/**',
53+ '**/vendor/**',
54+ '**/examples/**',
55+ '**/ffi/**',
56+ ]
57+
58+ # Per-repo exemptions parsed from .claude/CLAUDE.md "TypeScript Exemptions" table.
59+ # Single source of truth — adding a row here unblocks CI for that path.
60+ # Format expected:
61+ # ### TypeScript Exemptions ...
62+ # | Path | Files | Rationale | Unblock condition |
63+ # |---|---|---|---|
64+ # | `path/to/file.ts` | 1 | ... | ... |
65+ # | `dir/*.ts` | 6 | ... | ... |
66+ exemptions = []
67+ claude_md = pathlib.Path('.claude/CLAUDE.md')
68+ if claude_md.exists():
69+ in_table = False
70+ for line in claude_md.read_text(encoding='utf-8').splitlines():
71+ if re.search(r'TypeScript [Ee]xemptions', line):
72+ in_table = True
73+ continue
74+ if in_table and line.startswith(('### ', '## ', '# ')):
75+ break
76+ if in_table and line.startswith('|'):
77+ m = re.match(r'\|\s*`([^`]+)`', line)
78+ if m:
79+ exemptions.append(m.group(1))
80+
81+ # Find all .ts and .tsx files
82+ found = []
83+ for ext in ('ts', 'tsx'):
84+ found.extend(str(p) for p in pathlib.Path('.').rglob(f'*.{ext}'))
85+
86+ def allowed(path):
87+ p = path.lstrip('./')
88+ for g in BUILTIN_GLOBS + exemptions:
89+ if fnmatch.fnmatchcase(p, g):
90+ return True
91+ # also treat glob ending with / as a directory prefix
92+ base = g.rstrip('/').rstrip('*').rstrip('/')
93+ if base and (p == base or p.startswith(base + '/')):
94+ return True
95+ return False
96+
97+ bad = sorted(f for f in found if not allowed(f))
98+ if bad:
99+ print("❌ TypeScript files detected outside the allowlist.\n")
100+ for f in bad:
101+ print(f" {f}")
102+ print()
103+ print("To resolve, either:")
104+ print(" (a) migrate the file to AffineScript")
105+ print(" (see Human_Programming_Guide.adoc migration chapter), OR")
106+ print(" (b) move it to an allowlisted bridge path")
107+ print(" (bindings/, tests/, scripts/, mcp-adapter/, *vscode*/, cli/, deno-*/, etc.), OR")
108+ print(" (c) add an entry to the 'TypeScript Exemptions' table in .claude/CLAUDE.md")
109+ print(" with rationale + unblock condition.")
110+ if exemptions:
111+ print(f"\n(Currently {len(exemptions)} exemption(s) parsed from .claude/CLAUDE.md.)")
112+ sys.exit(1)
113+ print(f"✅ No TypeScript files outside allowlist ({len(exemptions)} per-repo exemption(s) parsed).")
114+ PYEOF
68115
69116 - name : Check for Go
70117 run : |
0 commit comments