Skip to content

Commit 2db6086

Browse files
committed
refactor(lint): retire the facade closure test for a lint rule plus budget rows
`contracts-entry-closure.test.ts` (from #1959) carried two assertions. Neither replacement subsumes it alone; together they do, on two different axes. Its whole-tree scan parsed ~490 candidate files to prove nothing value-imports the two wide facades. `eslint/no-restricted-imports` states exactly that, and `allowTypeImports` draws the one distinction that made a custom walker look necessary: `import type` is erased, so it stays legal. The rule covers every file rather than the four hubs the deleted test named, and it reaches dynamic imports too. Its hub pin checked that four named hubs never reach either facade. The lint rule forbids the import edge that was the only way that could happen, and #1960's rows add an axis the old test never had: closure SIZE drift. That cardinality check is deliberately not described here as strictly stronger, because it is not — an equal-size graph substitution leaves the count intact and passes. Size drift and forbidden edges are different properties, and the two gates own one each. The override semantics are not additive, so the rule was verified per zone rather than assumed. A same-rule override REPLACES the parent, so a top-level rule would have been silently dropped for `src/**`; and the existing blanket `"off"` for `exec.ts` and the test tree would have exempted the files that carried most of the cost #1959 removed. The paths are therefore added per zone, and that `"off"` becomes a facade-only config that keeps the `node:child_process` exemption it existed for. Planted red in all three zones — `src/core/capabilities.ts`, a `src/__tests__` file, and `packages/capture-kit/src` — each flagged, while a type-only import in the same probe file was not. The first packages probe read as a pass because the sed that built it produced a type-only import; that zone was re-probed with a real value import rather than trusting the green. Relying on config is safe here because misconfiguration fails loudly: a typo'd rule name makes oxlint exit 1 with "Rule not found in plugin", rather than pass silently the way the `rg` assertions in #1976 did. The budgets stay for what no linter can express: a transitive weight property, where a module already imported grows an import and the cost arrives without any single file's import list changing. Per-file rules cannot see that, and `no-restricted-imports` can only ban specifiers named in advance — exactly what #1950/#1956/#1959 could not have named.
1 parent 2baf7ef commit 2db6086

2 files changed

Lines changed: 59 additions & 101 deletions

File tree

‎.oxlintrc.json‎

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,21 @@
1515
"argsIgnorePattern": "^_",
1616
"caughtErrorsIgnorePattern": "^_",
1717
"destructuredArrayIgnorePattern": "^_",
18-
"fix": { "imports": "safe-fix", "variables": "suggestion" },
18+
"fix": {
19+
"imports": "safe-fix",
20+
"variables": "suggestion"
21+
},
1922
"varsIgnorePattern": "^_"
2023
}
2124
],
2225
"eslint/prefer-const": "error",
2326
"eslint/no-useless-escape": "error",
24-
"eslint/no-empty": ["error", { "allowEmptyCatch": true }],
27+
"eslint/no-empty": [
28+
"error",
29+
{
30+
"allowEmptyCatch": true
31+
}
32+
],
2533
"typescript/no-explicit-any": "off",
2634
"typescript/only-throw-error": "off",
2735
"typescript/no-var-requires": "error",
@@ -38,6 +46,16 @@
3846
{
3947
"name": "node:child_process",
4048
"message": "Use process helpers from src/utils/exec.ts instead of importing node:child_process directly."
49+
},
50+
{
51+
"name": "@agent-device/contracts/platform",
52+
"allowTypeImports": true,
53+
"message": "Value-importing this facade evaluates all 32 vocabulary modules it re-exports. Import the symbol from the module that owns it (@agent-device/contracts/<module>). `import type` stays fine \u2014 it is erased."
54+
},
55+
{
56+
"name": "@agent-device/contracts/interaction",
57+
"allowTypeImports": true,
58+
"message": "Value-importing this facade evaluates all 18 vocabulary modules it re-exports. Import the symbol from the module that owns it (@agent-device/contracts/<module>). `import type` stays fine \u2014 it is erased."
4159
}
4260
]
4361
}
@@ -47,7 +65,45 @@
4765
{
4866
"files": ["src/utils/exec.ts", "src/**/*.test.ts", "src/**/__tests__/**/*.ts"],
4967
"rules": {
50-
"eslint/no-restricted-imports": "off"
68+
"eslint/no-restricted-imports": [
69+
"error",
70+
{
71+
"paths": [
72+
{
73+
"name": "@agent-device/contracts/platform",
74+
"allowTypeImports": true,
75+
"message": "Value-importing this facade evaluates all 32 vocabulary modules it re-exports. Import the symbol from the module that owns it (@agent-device/contracts/<module>). `import type` stays fine \u2014 it is erased."
76+
},
77+
{
78+
"name": "@agent-device/contracts/interaction",
79+
"allowTypeImports": true,
80+
"message": "Value-importing this facade evaluates all 18 vocabulary modules it re-exports. Import the symbol from the module that owns it (@agent-device/contracts/<module>). `import type` stays fine \u2014 it is erased."
81+
}
82+
]
83+
}
84+
]
85+
}
86+
},
87+
{
88+
"files": ["packages/*/src/**/*.ts"],
89+
"rules": {
90+
"eslint/no-restricted-imports": [
91+
"error",
92+
{
93+
"paths": [
94+
{
95+
"name": "@agent-device/contracts/platform",
96+
"allowTypeImports": true,
97+
"message": "Value-importing this facade evaluates all 32 vocabulary modules it re-exports. Import the symbol from the module that owns it (@agent-device/contracts/<module>). `import type` stays fine \u2014 it is erased."
98+
},
99+
{
100+
"name": "@agent-device/contracts/interaction",
101+
"allowTypeImports": true,
102+
"message": "Value-importing this facade evaluates all 18 vocabulary modules it re-exports. Import the symbol from the module that owns it (@agent-device/contracts/<module>). `import type` stays fine \u2014 it is erased."
103+
}
104+
]
105+
}
106+
]
51107
}
52108
},
53109
{

‎src/__tests__/contracts-entry-closure.test.ts‎

Lines changed: 0 additions & 98 deletions
This file was deleted.

0 commit comments

Comments
 (0)