---
name: evolve-eftl-linter
description: Evolve the EFTL VS Code linter and language server while keeping tokenizer, parser, LSP diagnostics, navigation, TextMate grammar, editor configuration, snippets, examples, and documentation consistent. Use for EFTL feature implementation, bug fixes, refactors, new diagnostics, language-server capabilities, or support for a newly documented EFTL construct.
---

# Evolve EFTL Linter

Implement the smallest coherent change across all affected language-support layers. Read [references/project-architecture.md](references/project-architecture.md) before a non-trivial change.

## Workflow

1. Inspect the worktree and preserve unrelated user changes.
2. Convert the request into a language rule card. Use `$interpret-eftl-language` for new or disputed EFTL behavior.
3. Search all support surfaces for the construct and record the required files.
4. Add or update focused tests and fixtures before broad refactoring. If test infrastructure is absent, introduce the smallest repository-level harness that exercises tokenizer and parser without VS Code.
5. Change recognition in `src/tokenizer.ts`. Preserve exact source spans and make a deliberate decision about case-insensitivity and malformed delimiters.
6. Change structure in `src/parser.ts`. Validate grammar relationships and ordering, not only matching close tags. Recover after an error so one defect does not flood the document with misleading diagnostics.
7. Change semantic analysis and LSP behavior in `src/server.ts`. Keep internal positions unambiguous and convert to zero-based LSP ranges only at the boundary.
8. Synchronize editor assets when user-visible syntax changes: TextMate grammar, language configuration, snippets, examples, and README.
9. Run `$verify-eftl-linter`; inspect every failure and any new diagnostic range manually.

## Design constraints

- Do not encode the same tag metadata independently in several new switch statements. Prefer a shared declarative definition when a change spans tokenization, parsing, and validation.
- Keep parsing separate from LSP transport so core behavior is testable without starting a language client.
- Do not claim full expression validation until the grammar supports precedence, literals, operators, and recovery defined by the runtime language.
- Avoid static errors for values known only at runtime. Use warnings only when they are actionable and low-noise.
- Cap published diagnostics with `eftl.maxNumberOfProblems` and make truncation deterministic when implementing server work.
- Preserve valid user text and ElixForms TAG payloads; brackets inside comments, expressions, quoted attributes, or TAG bodies need context-aware handling.
- Guarantee scanner progress: every tokenization step must consume input or terminate with an error. Include unknown and incomplete `[` constructs in regression tests.
- Treat diagnostic ranges as first-class behavior. Test single-line and multiline tokens, CRLF and LF, and non-ASCII text before the error.

## Change-surface checklist

| Concern | Primary files |
| --- | --- |
| Token kinds, scanning, locations | `src/tokenizer.ts` |
| Nesting, ordering, recovery, AST | `src/parser.ts` |
| Diagnostics, config, symbols, definitions | `src/server.ts` |
| Client activation | `src/extension.ts`, `package.json` |
| Highlighting | `syntaxes/eftl.tmLanguage.json` |
| Brackets, comments, folding | `language-configuration.json` |
| Authoring examples | `snippets/eftl.json`, `examples/`, `README.md` |
| Build and tests | `package.json`, `tsconfig.json`, test files |

Update only surfaces affected by the rule card, but explicitly state why an apparently related surface is unchanged.
