@ontrails/warden 1.0.0-beta.32 → 1.0.0-beta.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +56 -0
- package/README.md +1 -1
- package/package.json +9 -9
- package/src/cli.ts +120 -10
- package/src/command.ts +25 -5
- package/src/drift.ts +116 -7
- package/src/fix.ts +8 -2
- package/src/formatters.ts +3 -8
- package/src/index.ts +30 -2
- package/src/project-context.ts +255 -1
- package/src/rules/ast.ts +4 -0
- package/src/rules/duplicate-exported-symbol.ts +211 -0
- package/src/rules/duplicate-public-contract.ts +2 -1
- package/src/rules/governed-symbol-residue.ts +131 -0
- package/src/rules/index.ts +43 -3
- package/src/rules/metadata.ts +105 -11
- package/src/rules/no-legacy-cli-alias-export.ts +247 -0
- package/src/rules/no-retired-cross-vocabulary.ts +19 -9
- package/src/rules/public-export-example-coverage.ts +5 -0
- package/src/rules/registry-names.ts +12 -2
- package/src/rules/retired-vocabulary.ts +396 -0
- package/src/rules/signal-graph-coaching.ts +32 -3
- package/src/rules/surface-overlay-coherence.ts +262 -0
- package/src/rules/{surface-facet-coherence.ts → surface-trailhead-coherence.ts} +45 -41
- package/src/rules/trailhead-override-divergence.ts +356 -0
- package/src/rules/types.ts +58 -1
- package/src/rules/webhook-route-collision.ts +64 -1
- package/src/trails/duplicate-exported-symbol.trail.ts +48 -0
- package/src/trails/duplicate-public-contract.trail.ts +1 -1
- package/src/trails/governed-symbol-residue.trail.ts +24 -0
- package/src/trails/index.ts +6 -1
- package/src/trails/no-legacy-cli-alias-export.trail.ts +41 -0
- package/src/trails/schema.ts +39 -0
- package/src/trails/surface-overlay-coherence.trail.ts +24 -0
- package/src/trails/{surface-facet-coherence.trail.ts → surface-trailhead-coherence.trail.ts} +4 -4
- package/src/trails/trailhead-override-divergence.trail.ts +47 -0
- package/src/trails/wrap-rule.ts +10 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Flags leftover legacy app-module CLI alias exports removed in TRL-1207.
|
|
3
|
+
*
|
|
4
|
+
* Before the surfaces-overlay cutover, apps published CLI alias maps through
|
|
5
|
+
* a module-level export named `cliAliases` or `trailsCliAliases`. TRL-1207 is
|
|
6
|
+
* a hard cutover: app-owned CLI bindings now live in a
|
|
7
|
+
* `surfaceOverlay({ cli: { ... } })` envelope inside the app module's
|
|
8
|
+
* `trailsOverlays` array export, and the legacy export convention was
|
|
9
|
+
* deleted. This rule makes a leftover legacy export an error so stale app
|
|
10
|
+
* modules get a fix-forward diagnostic instead of silently losing their
|
|
11
|
+
* bindings.
|
|
12
|
+
*
|
|
13
|
+
* Detection is AST-scoped and export-shaped:
|
|
14
|
+
*
|
|
15
|
+
* - `export const cliAliases = { ... }` (also `let`/`var`, destructured
|
|
16
|
+
* bindings, and function/class declarations) is flagged.
|
|
17
|
+
* - `export { cliAliases }` and `export { whatever as trailsCliAliases }`
|
|
18
|
+
* specifiers are flagged, including re-export statements such as
|
|
19
|
+
* `export { trailsCliAliases } from './app.js'`.
|
|
20
|
+
* - A non-exported local `const cliAliases = ...` is legal and never
|
|
21
|
+
* flagged, and the identifiers appearing only in strings or comments do
|
|
22
|
+
* not match because the rule inspects export bindings, not raw text.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import {
|
|
26
|
+
getNodeArgument,
|
|
27
|
+
getNodeBodyStatements,
|
|
28
|
+
getNodeDeclaration,
|
|
29
|
+
getNodeDeclarations,
|
|
30
|
+
getNodeElements,
|
|
31
|
+
getNodeExported,
|
|
32
|
+
getNodeExportKind,
|
|
33
|
+
getNodeId,
|
|
34
|
+
getNodeLeft,
|
|
35
|
+
getNodeProperties,
|
|
36
|
+
getNodeSpecifiers,
|
|
37
|
+
getNodeValueNode,
|
|
38
|
+
getStringValue,
|
|
39
|
+
identifierName,
|
|
40
|
+
isStringLiteral,
|
|
41
|
+
offsetToLine,
|
|
42
|
+
parse,
|
|
43
|
+
} from './ast.js';
|
|
44
|
+
import type { AstNode } from './ast.js';
|
|
45
|
+
import type { WardenDiagnostic, WardenFix, WardenRule } from './types.js';
|
|
46
|
+
|
|
47
|
+
const RULE_NAME = 'no-legacy-cli-alias-export';
|
|
48
|
+
|
|
49
|
+
/** Legacy app-module CLI alias export names removed in TRL-1207. */
|
|
50
|
+
const LEGACY_CLI_ALIAS_EXPORT_NAMES: ReadonlySet<string> = new Set([
|
|
51
|
+
'cliAliases',
|
|
52
|
+
'trailsCliAliases',
|
|
53
|
+
]);
|
|
54
|
+
|
|
55
|
+
/** Declaration node types that only propagate types, never value bindings. */
|
|
56
|
+
const TYPE_ONLY_DECLARATION_TYPES: ReadonlySet<string> = new Set([
|
|
57
|
+
'TSInterfaceDeclaration',
|
|
58
|
+
'TSTypeAliasDeclaration',
|
|
59
|
+
]);
|
|
60
|
+
|
|
61
|
+
interface ExportedBinding {
|
|
62
|
+
readonly name: string;
|
|
63
|
+
readonly start: number;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Exported name of a specifier: identifier or string-literal alias. */
|
|
67
|
+
const exportedSpecifierName = (node: AstNode | undefined): string | null =>
|
|
68
|
+
identifierName(node) ??
|
|
69
|
+
(node && isStringLiteral(node) ? getStringValue(node) : null);
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Expand one binding-pattern node into legacy-named bindings, pushing child
|
|
73
|
+
* patterns onto the worklist. Destructured exports such as
|
|
74
|
+
* `export const { cliAliases } = mod` still introduce a module-level exported
|
|
75
|
+
* value binding, so patterns cannot be skipped.
|
|
76
|
+
*/
|
|
77
|
+
const visitBindingPatternNode = (
|
|
78
|
+
node: AstNode,
|
|
79
|
+
into: ExportedBinding[],
|
|
80
|
+
worklist: AstNode[]
|
|
81
|
+
): void => {
|
|
82
|
+
const name = identifierName(node);
|
|
83
|
+
if (name !== null) {
|
|
84
|
+
if (LEGACY_CLI_ALIAS_EXPORT_NAMES.has(name)) {
|
|
85
|
+
into.push({ name, start: node.start });
|
|
86
|
+
}
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
if (node.type === 'AssignmentPattern') {
|
|
90
|
+
const left = getNodeLeft(node);
|
|
91
|
+
if (left) {
|
|
92
|
+
worklist.push(left);
|
|
93
|
+
}
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (node.type === 'RestElement') {
|
|
97
|
+
const argument = getNodeArgument(node);
|
|
98
|
+
if (argument) {
|
|
99
|
+
worklist.push(argument);
|
|
100
|
+
}
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (node.type === 'ObjectPattern') {
|
|
104
|
+
for (const property of getNodeProperties(node)) {
|
|
105
|
+
const value = getNodeValueNode(property) ?? getNodeArgument(property);
|
|
106
|
+
if (value) {
|
|
107
|
+
worklist.push(value);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (node.type === 'ArrayPattern') {
|
|
113
|
+
for (const element of getNodeElements(node)) {
|
|
114
|
+
if (element) {
|
|
115
|
+
worklist.push(element);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const collectLegacyPatternBindings = (
|
|
122
|
+
pattern: AstNode | undefined,
|
|
123
|
+
into: ExportedBinding[]
|
|
124
|
+
): void => {
|
|
125
|
+
if (!pattern) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const worklist: AstNode[] = [pattern];
|
|
129
|
+
while (worklist.length > 0) {
|
|
130
|
+
const node = worklist.pop();
|
|
131
|
+
if (node) {
|
|
132
|
+
visitBindingPatternNode(node, into, worklist);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const collectLegacyDeclarationBindings = (
|
|
138
|
+
declaration: AstNode
|
|
139
|
+
): readonly ExportedBinding[] => {
|
|
140
|
+
if (TYPE_ONLY_DECLARATION_TYPES.has(declaration.type)) {
|
|
141
|
+
return [];
|
|
142
|
+
}
|
|
143
|
+
const bindings: ExportedBinding[] = [];
|
|
144
|
+
if (declaration.type === 'VariableDeclaration') {
|
|
145
|
+
for (const declarator of getNodeDeclarations(declaration)) {
|
|
146
|
+
collectLegacyPatternBindings(getNodeId(declarator), bindings);
|
|
147
|
+
}
|
|
148
|
+
return bindings;
|
|
149
|
+
}
|
|
150
|
+
const name = identifierName(getNodeId(declaration));
|
|
151
|
+
if (name !== null && LEGACY_CLI_ALIAS_EXPORT_NAMES.has(name)) {
|
|
152
|
+
bindings.push({ name, start: declaration.start });
|
|
153
|
+
}
|
|
154
|
+
return bindings;
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
const collectLegacySpecifierBindings = (
|
|
158
|
+
statement: AstNode
|
|
159
|
+
): readonly ExportedBinding[] => {
|
|
160
|
+
const bindings: ExportedBinding[] = [];
|
|
161
|
+
for (const specifier of getNodeSpecifiers(statement)) {
|
|
162
|
+
if (
|
|
163
|
+
specifier.type !== 'ExportSpecifier' ||
|
|
164
|
+
getNodeExportKind(specifier) === 'type'
|
|
165
|
+
) {
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
const name = exportedSpecifierName(getNodeExported(specifier));
|
|
169
|
+
if (name !== null && LEGACY_CLI_ALIAS_EXPORT_NAMES.has(name)) {
|
|
170
|
+
bindings.push({ name, start: specifier.start });
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return bindings;
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
const collectLegacyExportBindings = (
|
|
177
|
+
ast: AstNode
|
|
178
|
+
): readonly ExportedBinding[] => {
|
|
179
|
+
const bindings: ExportedBinding[] = [];
|
|
180
|
+
for (const statement of getNodeBodyStatements(ast)) {
|
|
181
|
+
if (
|
|
182
|
+
statement.type !== 'ExportNamedDeclaration' ||
|
|
183
|
+
getNodeExportKind(statement) === 'type'
|
|
184
|
+
) {
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
const declaration = getNodeDeclaration(statement);
|
|
188
|
+
if (declaration) {
|
|
189
|
+
bindings.push(...collectLegacyDeclarationBindings(declaration));
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
bindings.push(...collectLegacySpecifierBindings(statement));
|
|
193
|
+
}
|
|
194
|
+
return bindings;
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
const buildMessage = (name: string): string =>
|
|
198
|
+
`Legacy CLI alias export '${name}' was removed in the TRL-1207 surfaces-overlay cutover. Wrap the alias map into surfaceOverlay({ cli: { ... } }) from @ontrails/core inside the module's trailsOverlays array export.`;
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Build the fix metadata for a legacy CLI alias export finding.
|
|
202
|
+
*
|
|
203
|
+
* The rewrite is an export restructure, not a rename, so there is no
|
|
204
|
+
* mechanical single-span replacement: the fix carries no edits and Warden
|
|
205
|
+
* never applies it. Downstream, the `export-restructure` fix class routes the
|
|
206
|
+
* finding to the Regrade `export-restructure:cli-aliases` class (TRL-1210),
|
|
207
|
+
* which inverts the alias map into `surfaceOverlay({ cli: { ... } })`
|
|
208
|
+
* bindings inside the module's `trailsOverlays` array export.
|
|
209
|
+
*/
|
|
210
|
+
const buildFix = (name: string): WardenFix => ({
|
|
211
|
+
class: 'export-restructure',
|
|
212
|
+
reason: `Legacy CLI alias export '${name}' must be rewritten into a surfaceOverlay({ cli: { ... } }) entry inside the module's trailsOverlays array export; run the Regrade class export-restructure:cli-aliases (TRL-1210) to automate this restructure.`,
|
|
213
|
+
safety: 'review',
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Flags exported bindings named `cliAliases` or `trailsCliAliases`, the
|
|
218
|
+
* legacy app-module CLI alias export convention deleted in TRL-1207.
|
|
219
|
+
*/
|
|
220
|
+
export const noLegacyCliAliasExport: WardenRule = {
|
|
221
|
+
check(sourceCode: string, filePath: string): readonly WardenDiagnostic[] {
|
|
222
|
+
if (
|
|
223
|
+
!(
|
|
224
|
+
sourceCode.includes('cliAliases') ||
|
|
225
|
+
sourceCode.includes('trailsCliAliases')
|
|
226
|
+
)
|
|
227
|
+
) {
|
|
228
|
+
return [];
|
|
229
|
+
}
|
|
230
|
+
const ast = parse(filePath, sourceCode);
|
|
231
|
+
if (!ast) {
|
|
232
|
+
return [];
|
|
233
|
+
}
|
|
234
|
+
return collectLegacyExportBindings(ast).map((binding) => ({
|
|
235
|
+
filePath,
|
|
236
|
+
fix: buildFix(binding.name),
|
|
237
|
+
line: offsetToLine(sourceCode, binding.start),
|
|
238
|
+
message: buildMessage(binding.name),
|
|
239
|
+
rule: RULE_NAME,
|
|
240
|
+
severity: 'error',
|
|
241
|
+
}));
|
|
242
|
+
},
|
|
243
|
+
description:
|
|
244
|
+
'Disallow the legacy app-module CLI alias exports (cliAliases, trailsCliAliases) removed in the TRL-1207 surfaces-overlay cutover.',
|
|
245
|
+
name: RULE_NAME,
|
|
246
|
+
severity: 'error',
|
|
247
|
+
};
|
|
@@ -8,17 +8,25 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { resolve, sep } from 'node:path';
|
|
10
10
|
|
|
11
|
+
import { requireGovernedVocabularyTransition } from './retired-vocabulary.js';
|
|
11
12
|
import type { WardenDiagnostic, WardenFix, WardenRule } from './types.js';
|
|
12
13
|
|
|
13
14
|
const RULE_NAME = 'no-retired-cross-vocabulary';
|
|
14
15
|
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
{ from: 'crossInput', to: 'composeInput' },
|
|
18
|
-
{ from: 'crosses', to: 'composes' },
|
|
19
|
-
] as const;
|
|
16
|
+
const CROSS_COMPOSE_TRANSITION =
|
|
17
|
+
requireGovernedVocabularyTransition('cross-compose');
|
|
20
18
|
|
|
21
|
-
|
|
19
|
+
if (CROSS_COMPOSE_TRANSITION.target.kind !== 'single') {
|
|
20
|
+
throw new Error('cross-compose transition must have a single target.');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const COMPOSE_TARGET = CROSS_COMPOSE_TRANSITION.target.to;
|
|
24
|
+
|
|
25
|
+
const SAFE_REWRITES = Object.entries(
|
|
26
|
+
CROSS_COMPOSE_TRANSITION.safeRewriteForms
|
|
27
|
+
).map(([from, to]) => ({ from, to }));
|
|
28
|
+
|
|
29
|
+
const REVIEW_TERMS = CROSS_COMPOSE_TRANSITION.reviewForms;
|
|
22
30
|
|
|
23
31
|
const IDENTIFIER_CHAR = /[$0-9A-Z_a-z]/u;
|
|
24
32
|
|
|
@@ -28,6 +36,8 @@ const ALLOWED_PATH_SUFFIXES: readonly string[] = [
|
|
|
28
36
|
'/docs/adr/0049-composition-is-compose-not-cross.md',
|
|
29
37
|
'/packages/warden/src/rules/no-retired-cross-vocabulary.ts',
|
|
30
38
|
'/packages/warden/src/rules/metadata.ts',
|
|
39
|
+
'/packages/warden/src/rules/retired-vocabulary.ts',
|
|
40
|
+
'/packages/warden/src/trails/governed-symbol-residue.trail.ts',
|
|
31
41
|
'/packages/warden/src/trails/no-retired-cross-vocabulary.trail.ts',
|
|
32
42
|
'/scripts/vocab-cutover-rewrite.ts',
|
|
33
43
|
];
|
|
@@ -40,7 +50,7 @@ interface SafeRewriteMatch {
|
|
|
40
50
|
|
|
41
51
|
interface ReviewMatch {
|
|
42
52
|
readonly index: number;
|
|
43
|
-
readonly term:
|
|
53
|
+
readonly term: string;
|
|
44
54
|
}
|
|
45
55
|
|
|
46
56
|
const normalizePath = (filePath: string): string =>
|
|
@@ -150,7 +160,7 @@ const safeFix = (match: SafeRewriteMatch): WardenFix => ({
|
|
|
150
160
|
|
|
151
161
|
const reviewFix = (term: string): WardenFix => ({
|
|
152
162
|
class: 'term-rewrite',
|
|
153
|
-
reason: `Retired composition vocabulary '${term}' appears in a larger or ambiguous form. Review before migrating to
|
|
163
|
+
reason: `Retired composition vocabulary '${term}' appears in a larger or ambiguous form. Review before migrating to ${COMPOSE_TARGET} vocabulary.`,
|
|
154
164
|
safety: 'review',
|
|
155
165
|
});
|
|
156
166
|
|
|
@@ -158,7 +168,7 @@ const safeMessage = (match: SafeRewriteMatch): string =>
|
|
|
158
168
|
`Retired composition vocabulary '${match.from}' should be '${match.to}' after the beta.19 compose cutover.`;
|
|
159
169
|
|
|
160
170
|
const reviewMessage = (term: string): string =>
|
|
161
|
-
`Retired composition vocabulary '${term}' needs review before migrating to
|
|
171
|
+
`Retired composition vocabulary '${term}' needs review before migrating to ${COMPOSE_TARGET} vocabulary.`;
|
|
162
172
|
|
|
163
173
|
export const noRetiredCrossVocabulary: WardenRule = {
|
|
164
174
|
check(sourceCode: string, filePath: string): readonly WardenDiagnostic[] {
|
|
@@ -113,6 +113,11 @@ export const PUBLIC_API_EXAMPLE_TARGETS: readonly PublicApiPackageTarget[] = [
|
|
|
113
113
|
minimumExports: ['createApp', 'surface'],
|
|
114
114
|
packageName: '@ontrails/hono',
|
|
115
115
|
},
|
|
116
|
+
{
|
|
117
|
+
indexPath: 'adapters/cloudflare/src/index.ts',
|
|
118
|
+
minimumExports: ['createWorkersHandler', 'cloudflareKv'],
|
|
119
|
+
packageName: '@ontrails/cloudflare',
|
|
120
|
+
},
|
|
116
121
|
] as const;
|
|
117
122
|
|
|
118
123
|
export interface ResolvedPublicApiTarget extends PublicApiPackageTarget {
|
|
@@ -16,10 +16,12 @@ import { deadInternalTrail } from './dead-internal-trail.js';
|
|
|
16
16
|
import { deadPublicTrail } from './dead-public-trail.js';
|
|
17
17
|
import { draftFileMarking } from './draft-file-marking.js';
|
|
18
18
|
import { draftVisibleDebt } from './draft-visible-debt.js';
|
|
19
|
+
import { duplicateExportedSymbol } from './duplicate-exported-symbol.js';
|
|
19
20
|
import { duplicatePublicContract } from './duplicate-public-contract.js';
|
|
20
21
|
import { errorMappingCompleteness } from './error-mapping-completeness.js';
|
|
21
22
|
import { exampleValid } from './example-valid.js';
|
|
22
23
|
import { firesDeclarations } from './fires-declarations.js';
|
|
24
|
+
import { governedSymbolResidue } from './governed-symbol-residue.js';
|
|
23
25
|
import { implementationReturnsResult } from './implementation-returns-result.js';
|
|
24
26
|
import { incompleteAccessorForStandardOp } from './incomplete-accessor-for-standard-op.js';
|
|
25
27
|
import { incompleteCrud } from './incomplete-crud.js';
|
|
@@ -30,6 +32,7 @@ import { missingReconcile } from './missing-reconcile.js';
|
|
|
30
32
|
import { missingVisibility } from './missing-visibility.js';
|
|
31
33
|
import { noDevPermitInSource } from './no-dev-permit-in-source.js';
|
|
32
34
|
import { noDestructuredCompose } from './no-destructured-compose.js';
|
|
35
|
+
import { noLegacyCliAliasExport } from './no-legacy-cli-alias-export.js';
|
|
33
36
|
import { noLegacyLayerImports } from './no-legacy-layer-imports.js';
|
|
34
37
|
import { noDirectImplementationCall } from './no-direct-implementation-call.js';
|
|
35
38
|
import { noNativeErrorResult } from './no-native-error-result.js';
|
|
@@ -58,8 +61,10 @@ import { resourceMockCoverage } from './resource-mock-coverage.js';
|
|
|
58
61
|
import { scheduledDestroyIntent } from './scheduled-destroy-intent.js';
|
|
59
62
|
import { signalGraphCoaching } from './signal-graph-coaching.js';
|
|
60
63
|
import { staticResourceAccessorPreference } from './static-resource-accessor-preference.js';
|
|
61
|
-
import {
|
|
64
|
+
import { surfaceOverlayCoherence } from './surface-overlay-coherence.js';
|
|
65
|
+
import { surfaceTrailheadCoherence } from './surface-trailhead-coherence.js';
|
|
62
66
|
import { trailForkCoaching } from './trail-fork-coaching.js';
|
|
67
|
+
import { trailheadOverrideDivergence } from './trailhead-override-divergence.js';
|
|
63
68
|
import {
|
|
64
69
|
forkWithoutPreservedBlaze,
|
|
65
70
|
markerSchemaUnsupported,
|
|
@@ -94,12 +99,14 @@ export const registeredRuleNames: readonly string[] = [
|
|
|
94
99
|
deadInternalTrail.name,
|
|
95
100
|
deadPublicTrail.name,
|
|
96
101
|
deprecationWithoutGuidance.name,
|
|
102
|
+
duplicateExportedSymbol.name,
|
|
97
103
|
duplicatePublicContract.name,
|
|
98
104
|
draftFileMarking.name,
|
|
99
105
|
draftVisibleDebt.name,
|
|
100
106
|
errorMappingCompleteness.name,
|
|
101
107
|
exampleValid.name,
|
|
102
108
|
firesDeclarations.name,
|
|
109
|
+
governedSymbolResidue.name,
|
|
103
110
|
forkWithoutPreservedBlaze.name,
|
|
104
111
|
implementationReturnsResult.name,
|
|
105
112
|
incompleteAccessorForStandardOp.name,
|
|
@@ -112,6 +119,7 @@ export const registeredRuleNames: readonly string[] = [
|
|
|
112
119
|
missingVisibility.name,
|
|
113
120
|
noDevPermitInSource.name,
|
|
114
121
|
noDestructuredCompose.name,
|
|
122
|
+
noLegacyCliAliasExport.name,
|
|
115
123
|
noLegacyLayerImports.name,
|
|
116
124
|
noDirectImplementationCall.name,
|
|
117
125
|
noNativeErrorResult.name,
|
|
@@ -141,8 +149,10 @@ export const registeredRuleNames: readonly string[] = [
|
|
|
141
149
|
scheduledDestroyIntent.name,
|
|
142
150
|
signalGraphCoaching.name,
|
|
143
151
|
staticResourceAccessorPreference.name,
|
|
144
|
-
|
|
152
|
+
surfaceOverlayCoherence.name,
|
|
153
|
+
surfaceTrailheadCoherence.name,
|
|
145
154
|
trailForkCoaching.name,
|
|
155
|
+
trailheadOverrideDivergence.name,
|
|
146
156
|
unmaterializedActivationSource.name,
|
|
147
157
|
unreachableDetourShadowing.name,
|
|
148
158
|
validDetourContract.name,
|