lint-new

por sentry

Crear una nueva regla de ESLint con pruebas para eslintPluginScraps. Usar cuando se pida "crear una regla de lint", "añadir una regla de eslint", "scaffold una regla", "escribir una nueva…

npx skills add https://github.com/getsentry/sentry --skill lint-new

Create a new ESLint rule named $ARGUMENTS in the eslintPluginScraps plugin.

Step 1: Choose Your Archetype

Read references/rule-archetypes.md and pick the archetype that matches your rule's intent:

You want to...ArchetypeReference to load
Rewrite import pathsImport rewriteInline — simple pattern
Validate token/value usage per CSS propertyProperty validationstyle-collector-guide.md
Restrict JSX elements in specific propsJSX structuralrule-archetypes.md §Archetype 3
Detect patterns in static CSS textTemplate text analysisrule-archetypes.md §Archetype 4

Read the relevant reference before writing code. The archetypes document which AST visitors to use, which shared utilities apply, and which patterns are NOT appropriate for each approach.

Step 2: Check Shared Utilities

Before writing AST traversal logic, check static/eslint/eslintPluginScraps/src/ast/ for reusable code:

UtilityLocationUse for
getStyledCallInfosrc/ast/utils/styled.tsClassifying styled/css calls as element, component, or css
createQuasiScannersrc/ast/scanner/index.tsScanning static CSS text in template literals (Archetype 4)
createImportTrackersrc/ast/tracker/imports.tsResolving where a local name was imported from
createStyleCollectorsrc/ast/extractor/index.tsCollecting CSS-in-JS dynamic value declarations (NOT static text)
shouldAnalyzesrc/ast/extractor/index.tsFast pre-scan to skip files without Emotion usage
normalizePropertyNamesrc/ast/utils/normalizePropertyName.tsNormalizing CSS property names
decomposeValuesrc/ast/extractor/value-decomposer.tsBreaking complex expressions into all possible values
Theme trackersrc/ast/tracker/theme.tsTracking useTheme() and callback theme bindings

If another rule already solves a similar problem, extract shared logic into src/ast/utils/ and reuse it.

Step 3: Create Files

  1. Rule: static/eslint/eslintPluginScraps/src/rules/$ARGUMENTS.ts
  2. Test: static/eslint/eslintPluginScraps/src/rules/$ARGUMENTS.spec.ts

Rule Template

import {ESLintUtils} from '@typescript-eslint/utils';

export const $RULE_NAME = ESLintUtils.RuleCreator.withoutDocs({
  meta: {
    type: 'problem',
    docs: {
      description: '[Rule description]',
    },
    fixable: 'code', // include if rule has autofix — see Autofix Guidance
    schema: [],
    messages: {
      forbidden: 'Error message shown to user',
    },
  },
  create(context) {
    return {
      // AST visitor methods — see your chosen archetype
    };
  },
});

If your rule needs configurable options, load references/schema-patterns.md.

Test Template

import {RuleTester} from '@typescript-eslint/rule-tester';

import {$RULE_NAME} from './$ARGUMENTS';

const ruleTester = new RuleTester();

ruleTester.run('$ARGUMENTS', $RULE_NAME, {
  valid: [
    {
      code: '// valid code',
      filename: '/project/src/file.tsx',
    },
  ],
  invalid: [
    {
      code: '// invalid code',
      filename: '/project/src/file.tsx',
      errors: [{messageId: 'forbidden'}],
      output: '// expected output after autofix', // REQUIRED for fixable rules
    },
  ],
});

Run tests:

pnpm test-ci "static/eslint/eslintPluginScraps/src/rules/$ARGUMENTS.spec.ts"

Autofix Guidance

Default stance: implement autofix unless the transformation is ambiguous or could change runtime behavior.

Safe autofix patterns

  • Import path rewrites (see no-core-import.ts as canonical example)
  • Adding/removing JSX attributes with known values
  • Wrapping expressions in a known component
  • Identifier renames with no shadowing risk

Do NOT autofix when

  • Multiple valid fixes exist and the right choice requires human judgment
  • The fix requires type information not available from the AST alone
  • The transformation alters control flow or runtime behavior
  • The change spans multiple files

Fixer API

context.report({
  node,
  messageId: 'forbidden',
  fix(fixer) {
    return fixer.replaceText(node, newText);
    // Also: fixer.replaceTextRange([start, end], text)
    //        fixer.insertTextBefore(node, text)
    //        fixer.insertTextAfter(node, text)
    //        fixer.remove(node)
    // Return single fix or array of fixes
  },
});

When a rule is fixable, every invalid test case MUST include output showing the expected code after the fix.

Step 4: Register the Rule

1. Rule Index

Add to static/eslint/eslintPluginScraps/src/rules/index.ts:

import {$RULE_NAME} from './$ARGUMENTS';

export const rules = {
  // existing rules...
  $ARGUMENTS: $RULE_NAME,
};

2. ESLint Config

Add to eslint.config.ts inside the name: 'plugin/@sentry/scraps' block:

'@sentry/scraps/$ARGUMENTS': 'error',
// or with options:
'@sentry/scraps/$ARGUMENTS': ['error', { /* options */ }],

3. Verify

pnpm test-ci "static/eslint/eslintPluginScraps/src/rules/$ARGUMENTS.spec.ts"

Extending an Existing Rule

If modifying an existing rule rather than creating a new one:

  1. Read the existing rule and its config files to understand the architecture
  2. For config-driven rules (like use-semantic-token): changes often only require editing the config file (e.g., src/config/tokenRules.ts), not the rule logic
  3. Watch for reverse-mapping side effects — adding a new category can change which category is suggested for shared properties (last writer wins in buildPropertyToRule)
  4. Update existing tests for any changed behavior, then add new test cases

Naming Convention

  • Rule name (kebab-case): my-rule-name — verb-noun pattern (e.g., no-token-import, use-semantic-token)
  • Export name (camelCase): myRuleName
  • File name: matches rule name exactly (my-rule-name.ts, my-rule-name.spec.ts)

Más skills de sentry

generate-frontend-forms
sentry
Guía para crear formularios usando el nuevo sistema de formularios de Sentry. Úsalo al implementar formularios, campos de formulario, validación o funcionalidad de guardado automático.
official
sentry-snapshots-cocoa
sentry
Configuración completa de Sentry Snapshots para proyectos Apple/Cocoa. Úsalo cuando se te pida "configurar SnapshotPreviews", "configurar pruebas de snapshot en Apple", "subir snapshots de Apple a…
official
architecture-review
sentry
Revisión de salud del código a nivel de equipo. Encuentra módulos monolíticos, fallos silenciosos, brechas de seguridad de tipos, vacíos en la cobertura de pruebas y problemas de compatibilidad con LLM.
official
linear-type-labeler
sentry
Clasifica los issues de Linear y aplica una etiqueta de Tipo de la taxonomía de etiquetas del espacio de trabajo de Sentry basándose en el contenido del título y la descripción de cada issue.
official
vercel-react-best-practices
sentry
Directrices de optimización de rendimiento para React y Next.js de Vercel Engineering. Esta habilidad debe usarse al escribir, revisar o refactorizar React/Next.js…
official
bump-size-limit
sentry
Aumenta los límites de tamaño en .size-limit.js cuando la verificación de CI de size-limit falla. Úsalo cuando el usuario mencione fallos en los límites de tamaño, comprobaciones de tamaño de paquete fallidas, tamaño de CI…
official
generate-migration
sentry
Genera migraciones de base de datos de Django para Sentry. Úsalo al crear migraciones, agregar/eliminar columnas o tablas, agregar índices o resolver migraciones…
official
security-review
sentry
Encuentra vulnerabilidades de seguridad explotables en cambios de código. Úsalo para escaneos de seguridad de Warden, revisión de appsec, verificaciones estilo OWASP, autenticación o…
official