add docs and AI skills

This commit is contained in:
2026-08-17 18:23:10 +02:00
parent c3d5d3541b
commit 09dcfede46
13 changed files with 506 additions and 0 deletions
@@ -0,0 +1,46 @@
---
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.
@@ -0,0 +1,4 @@
interface:
display_name: "Evolve EFTL Linter"
short_description: "Implement coordinated EFTL linter changes"
default_prompt: "Use $evolve-eftl-linter to implement this EFTL language-support change safely."
@@ -0,0 +1,67 @@
# Project architecture and evolution notes
## Runtime flow
```text
.eftl document
-> VS Code language client (`src/extension.ts`)
-> LSP server (`src/server.ts`)
-> tokenizer (`src/tokenizer.ts`)
-> stack parser (`src/parser.ts`)
-> diagnostics and per-document variable definitions
```
Separately, VS Code loads the TextMate grammar, language configuration, and snippets directly from `package.json` contributions.
## Current responsibilities
- `src/extension.ts`: starts `out/server.js` over IPC for file-backed EFTL documents.
- `src/tokenizer.ts`: recognizes a fixed, mostly uppercase set of tags, expressions, comments, and plain text; stores one-based line and column plus a character length.
- `src/parser.ts`: checks stack-balanced open and close token kinds. It declares an `AstNode` interface but does not currently build an AST or enforce IF/WHILE child ordering.
- `src/server.ts`: tokenizes and parses on document changes, validates VAR `type`, collects variable declarations, publishes diagnostics, and implements same-document go-to-definition by word matching.
- `syntaxes/eftl.tmLanguage.json`: highlights a broader syntax independently of the TypeScript parser.
- `language-configuration.json`: defines comment, bracket, auto-close, surrounding-pair, and folding behavior.
- `snippets/eftl.json` and `examples/sample.eftl`: provide authoring examples and useful regression inputs.
## Baseline gaps to re-check
These observations describe the repository when this skill was created and are not permanent requirements:
- Documented `LOG`, `FOR`, `IS_EMPTY`, and `IS_NOT_EMPTY` constructs are not tokenized or structurally parsed.
- The specification describes case-insensitive tags; tokenization currently uses exact uppercase matches.
- An unrecognized `[` currently makes `scanText()` return without consuming input, so lowercase, unknown, or incomplete tags can trap tokenization in an infinite loop.
- Prefix checks such as `[VAR` need a tag-name boundary; otherwise longer unknown names can be misclassified.
- WHILE attributes and the attribute form of TRIM are not recognized by the current exact scanners.
- Parser validation is balance-only; it does not enforce root scope, IF branch ordering/cardinality, WHILE shape, or allowed bodies.
- Attribute parsing uses regular expressions in the server and validates only VAR type.
- Source positions combine one-based line/column with token string length. Multiline diagnostic end ranges and variable-definition selections require care.
- `eftl.maxNumberOfProblems` is declared but not consumed by the server.
- No automated test script is declared.
- `npm run compile` passes at the baseline. `npm run lint` fails before linting because ESLint 9 cannot find a flat `eslint.config.*` file.
## Preferred direction
Evolve incrementally toward:
1. a source-span model based on offsets with reliable LSP conversion;
2. a context-aware scanner that can report malformed input and recover;
3. structured attribute parsing with ranges;
4. an AST or equivalent parse structure that represents documented relationships;
5. separate semantic passes for declarations, references, types, and TAG payloads;
6. table-driven language metadata shared where doing so reduces drift;
7. core unit tests plus a small number of LSP integration tests.
Do not perform this redesign wholesale for an unrelated small fix. Introduce seams that make the next supported construct easier and safer.
## Completion criteria for a language construct
A construct is complete only when applicable layers agree on:
- accepted spellings and delimiters;
- attribute names and body form;
- nesting and ordering;
- malformed-input recovery;
- diagnostic message, severity, and exact range;
- highlighting and folding;
- snippet/example syntax;
- focused positive, negative, boundary, and regression tests.