Skip to content

Commit ec44d75

Browse files
feat(cicd_rules): extend :typescript_detected with linguist + /deps/ + /vscode/ carve-outs (#378)
## Summary Extends `:typescript_detected` `path_allow_prefixes` from 7 to 9 carve-out classes, closing asymmetries surfaced by the 2026-05-28 estate inventory. ## Three new classes - **`linguist/`** — hyperpolymath fork of `github-linguist/linguist`; its `samples/TypeScript/*.ts` are ML training fixtures, not estate-authored. Same class as `rescript/`/`servers/`/`repos-monorepo/`. - **`/deps/`** — Elixir Mix vendored-dep dir. Exemplar: `tma-mark2/deps/phoenix_live_view/assets/js/phoenix_live_view/*.ts` ships Phoenix LiveView's authored TS, vendored as a hex-mix dep. - **`/vscode/`** — VSCode extension entry points across 5 estate repos (`universal-language-server-plugin`, `reposystem`, `proof-burrower`, `phronesis`, `bofj-kitt`). Each has a `vscode/extension.ts`. Blocked on AffineScript VSCode-extension API binding (top-50 roadmap, unshipped); carve-out unblocks the gate. ## Test plan - [x] +3 tests for the new classes (linguist combined with existing fork test; new `**/deps/`; new `**/vscode/**` test covering all 5 estate repos) - [x] Existing 8 tests unmodified - [x] No behaviour change for the existing 7 carve-out classes - [ ] CI green ## Related - Mirrors will land in standards (`.claude/CLAUDE.md` exemption table + `LANGUAGE-POLICY.adoc` carve-outs + `language-policy.yml` grep chain) - Parent: hypatia#375 (initial 7-class TS carve-out) - Tracker: project_estate_ts_to_affinescript_2026_05_28 🤖 Generated with [Claude Code](https://claude.com/claude-code)
1 parent 9ed7a7e commit ec44d75

2 files changed

Lines changed: 62 additions & 7 deletions

File tree

lib/rules/cicd_rules.ex

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ defmodule Hypatia.Rules.CicdRules do
6767
# TS ban (org policy 2026-04-30 for NEW files; existing TS grandfathered
6868
# while in-flight migration to AffineScript proceeds — see project
6969
# tracker `project_estate_ts_to_affinescript_2026_05_28.md`).
70-
# Path-prefix allowlist covers seven classes of legitimate `.ts` presence:
70+
# Path-prefix allowlist covers nine classes of legitimate `.ts` presence:
7171
#
7272
# (1) Declaration files (`.d.ts`) — FFI/library type definitions are
7373
# headers, not implementation; they're the boundary, not the code.
@@ -93,10 +93,21 @@ defmodule Hypatia.Rules.CicdRules do
9393
#
9494
# (6) Upstream forks not estate-authored — `rescript/` (ReScript
9595
# compiler), `servers/` (third-party MCP servers),
96-
# `repos-monorepo/` (mass aggregator).
96+
# `repos-monorepo/` (mass aggregator), `linguist/` (GitHub's
97+
# language classifier — TS in `samples/` is ML training data).
9798
#
9899
# (7) Archived repos — GitHub-archived repos cannot accept PRs;
99100
# their TS is dormant. `hyperpolymath-archive/**`.
101+
#
102+
# (8) Vendored package-manager deps — `**/deps/` covers Elixir Mix
103+
# vendored deps (canonical example: `tma-mark2/deps/phoenix_live_view/`
104+
# ships Phoenix LiveView's authored TS). We don't own this code.
105+
#
106+
# (9) Editor-host extensions — `**/vscode/**` covers VSCode extension
107+
# entry points (`extension.ts` lives under `editors/vscode/`,
108+
# `extensions/vscode/`, or `clients/vscode/`). Blocked on the
109+
# AffineScript VSCode-extension API binding (top-50 roadmap);
110+
# carve-out unblocks the policy gate until bindings ship.
100111
%{id: :typescript_detected, glob: "*.ts",
101112
reason: "TypeScript banned in NEW code -- use AffineScript (org policy 2026-04-30; existing TS grandfathered while in-flight migration proceeds, see project_estate_ts_to_affinescript_2026_05_28)",
102113
# check_pattern uses String.contains?/2 so these entries match as
@@ -120,12 +131,28 @@ defmodule Hypatia.Rules.CicdRules do
120131
# (5) Bootstrap shims
121132
"affinescript-deno-test/",
122133
"affinescript-cli/",
123-
# (6) Upstream forks
134+
# (6) Upstream forks — not estate-authored; TS exists as vendored
135+
# upstream code or sample fixtures (linguist ships `.ts` files in
136+
# `samples/` as classification training data for its ML model).
124137
"rescript/",
125138
"servers/",
126139
"repos-monorepo/",
140+
"linguist/",
127141
# (7) Archived repos
128-
"hyperpolymath-archive/"
142+
"hyperpolymath-archive/",
143+
# (8) Vendored package-manager deps — `deps/` is the canonical Elixir
144+
# Mix vendored-dep directory (also used by other tools that vendor
145+
# via that name). Exemplar: `tma-mark2/deps/phoenix_live_view/`
146+
# ships Phoenix LiveView's authored TS.
147+
"/deps/",
148+
# (9) Editor-host extensions — VSCode extension entry points target
149+
# the `vscode` extension-host API which AffineScript does not yet
150+
# bind. These are blocked on the AS-bindings top-50 roadmap; the
151+
# carve-out unblocks the gate until host-API bindings ship.
152+
# Exemplars: `*/editors/vscode/`, `*/extensions/vscode/`,
153+
# `*/clients/vscode/`. The bare `/vscode/` substring suffices since
154+
# `String.contains?/2` matches any path containing it.
155+
"/vscode/"
129156
]},
130157
%{id: :rescript_detected, glob: "*.res", reason: "ReScript banned -- use AffineScript (org policy 2026-05-25; see #57 migration assistant)"},
131158
%{id: :rescript_interface_detected, glob: "*.resi", reason: "ReScript banned -- use AffineScript (org policy 2026-05-25; see #57 migration assistant)"},

test/rules/cicd_rules_typescript_test.exs

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,16 +79,18 @@ defmodule Hypatia.Rules.CicdRules.TypescriptTest do
7979
assert Enum.find(results, &(&1.rule == :typescript_detected)) == nil
8080
end
8181

82-
test "exempts upstream-fork repos (rescript/servers/repos-monorepo)" do
82+
test "exempts upstream-fork repos (rescript/servers/repos-monorepo/linguist)" do
8383
files = [
8484
"rescript/jscomp/test/test.ts",
8585
"servers/src/everything/index.ts",
86-
"repos-monorepo/some/path/file.ts"
86+
"repos-monorepo/some/path/file.ts",
87+
"linguist/samples/TypeScript/classes.ts",
88+
"linguist/samples/TypeScript/proto.ts"
8789
]
8890

8991
results = CicdRules.check_commit_blocks(files)
9092
assert Enum.find(results, &(&1.rule == :typescript_detected)) == nil,
91-
"upstream forks are not estate-authored — vendored as-is"
93+
"upstream forks are not estate-authored — linguist ships TS as ML training samples"
9294
end
9395

9496
test "exempts hyperpolymath-archive/** (archived repos)" do
@@ -101,6 +103,32 @@ defmodule Hypatia.Rules.CicdRules.TypescriptTest do
101103
assert Enum.find(results, &(&1.rule == :typescript_detected)) == nil
102104
end
103105

106+
test "exempts **/deps/ vendored package-manager dirs (Mix etc.)" do
107+
files = [
108+
"tma-mark2/deps/phoenix_live_view/assets/js/phoenix_live_view/view_hook.ts",
109+
"tma-mark2/deps/phoenix_live_view/assets/js/phoenix_live_view/index.ts",
110+
"some-elixir-app/deps/some_dep/assets/foo.ts"
111+
]
112+
113+
results = CicdRules.check_commit_blocks(files)
114+
assert Enum.find(results, &(&1.rule == :typescript_detected)) == nil,
115+
"Mix-style vendored deps under /deps/ are not estate-authored"
116+
end
117+
118+
test "exempts **/vscode/** editor-host extensions (blocked on AS-bindings)" do
119+
files = [
120+
"universal-language-server-plugin/clients/vscode/extension.ts",
121+
"reposystem/tools/rsr-certified/extensions/vscode/src/extension.ts",
122+
"proof-burrower/affinescript/editors/vscode/src/extension.ts",
123+
"phronesis/editors/vscode/src/extension.ts",
124+
"bofj-kitt/affinescript/editors/vscode/src/extension.ts"
125+
]
126+
127+
results = CicdRules.check_commit_blocks(files)
128+
assert Enum.find(results, &(&1.rule == :typescript_detected)) == nil,
129+
"VSCode extension entry points wait on AS VSCode-extension API binding"
130+
end
131+
104132
test "flags new TS even with carve-out-like names but outside carve-out paths" do
105133
# `proven/src/something.ts` is NOT in `proven/bindings/deno/`,
106134
# so it MUST still flag.

0 commit comments

Comments
 (0)