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,53 @@
---
name: interpret-eftl-language
description: Interpret the EFTL language specification and turn the repository PDF documentation into explicit lexical, syntactic, structural, attribute, and semantic rules. Use when adding or reviewing EFTL tags, expressions, nesting constraints, ElixForms TAG payloads, examples, diagnostics, or when the documentation and current TypeScript implementation disagree.
---
# Interpret EFTL Language
Derive a small, testable language contract before changing implementation code.
## Establish the source of truth
Use the sources in this order:
1. Read the relevant section of `docs/elixForms_Doc_EFTL.pdf` for EFTL behavior and examples.
2. Read `docs/elixForms_EFTLParser_syntax_rels.pdf` for parser relationships and allowed composition.
3. Read `docs/elixForms_TAG_Sintassi.pdf` for positional `SCHEMAID` and `GETVALUEBYTAG` payloads.
4. Use [references/eftl-language-reference.md](references/eftl-language-reference.md) as a navigation aid and concise baseline, never as a replacement for a disputed PDF passage.
5. Treat `src/`, `syntaxes/`, `snippets/`, `examples/`, and `README.md` as the current implementation, not as normative language documentation.
If the PDFs contradict one another or leave a rule unclear, report the ambiguity and preserve it in tests or design notes. Do not silently infer a restrictive diagnostic.
## Produce a rule card
For every construct being changed, record:
- spelling and case-sensitivity;
- block, bodyless, expression, or comment form;
- required and optional attributes, value types, defaults, and mutual exclusions;
- allowed body and parent/child relationships;
- variable scope, result type, and runtime behavior relevant to static analysis;
- valid, invalid, and boundary examples;
- the safest diagnostic when a property cannot be proven statically.
Distinguish syntax errors from semantic warnings. Runtime-only facts such as external TAG values must not become false-positive syntax errors.
## Reconcile with the implementation
Search every support surface before proposing a change:
```powershell
rg -n "CONSTRUCT|TokenType" src syntaxes snippets examples README.md language-configuration.json
```
Compare the rule card with:
- `src/tokenizer.ts` for recognition, source positions, and case handling;
- `src/parser.ts` for nesting and ordering;
- `src/server.ts` for semantic diagnostics and symbols;
- `syntaxes/eftl.tmLanguage.json` for highlighting;
- `language-configuration.json` for brackets, folding, and comments;
- `snippets/eftl.json`, `examples/`, and `README.md` for user-facing syntax.
Return a change-surface list and explicit acceptance cases. Hand implementation work to `$evolve-eftl-linter` and validation work to `$verify-eftl-linter` when those skills are available.
@@ -0,0 +1,4 @@
interface:
display_name: "Interpret EFTL Language"
short_description: "Interpret EFTL syntax and semantic rules"
default_prompt: "Use $interpret-eftl-language to derive the EFTL rules needed for this change."
@@ -0,0 +1,101 @@
# EFTL language reference
This is a compact index derived from the documents currently under `docs/`. Re-check the PDFs when exact wording, diagrams, or edge behavior matters.
## Documentation map
- `elixForms_Doc_EFTL.pdf`: EFTL specification through the documented 3.1.0 changes, language behavior, attributes, control flow, and examples.
- `elixForms_EFTLParser_syntax_rels.pdf`: generated lexer/parser relationship diagrams.
- `elixForms_TAG_Sintassi.pdf`: positional syntax for the ElixForms `SCHEMAID` and `GETVALUEBYTAG` plugins.
## Common lexical and structural rules
- EFTL uses square-bracket tags and requires properly nested, non-overlapping elements.
- A bodyless element ends with `/]`; a block has matching opening and closing tags.
- Attribute values are quoted. Attribute order is not semantically significant.
- The main specification says uppercase and lowercase tag spellings are interpreted equally and recommends lowercase style. The current implementation is largely uppercase-only.
- Text outside `[EFTL]...[/EFTL]` is not processed. Text inside an EFTL root but outside an executable tag is emitted as user text where the grammar permits it.
- Comments use `[!-- ... --]` and may span lines.
- The generated relationships include user text, ignored whitespace, CDATA, headers, comments, statements, code blocks, and output blocks. Consult the diagram PDF before enforcing a new parent/child restriction.
## Root, directives, and context
| Construct | Form | Key rules |
| --- | --- | --- |
| EFTL | `[EFTL] ... [/EFTL]` | Root block; no documented attributes; a document needs at least one root to be processed. |
| HEADER | `[HEADER name="..." value="..." type="..." /]` | Declares a directive. The documented directive is `trimDocument`, with boolean `true` or `false`. |
| LOG | `[LOG] ... [/LOG]` | Writes evaluated content to the server log; no documented attributes. |
Predefined execution-context names include `currentDateTime`, `defaultLocale`, `currentLocale`, and `requestId`. Other values may be supplied by the calling service.
## Variables and value functions
| Construct | Form | Key rules |
| --- | --- | --- |
| VAR | `[VAR name="..." type="..." unique="..." ] ... [/VAR]` | `name` identifies a context variable. Documented types: `string`, `boolean`, `number`, `date`, `object`, `iterable`. `unique` defaults to `false` and is meaningful only for `iterable`. |
| VALUE_OF | `[VALUE_OF varname="..." index="..." /]` | Emits a variable value. `index` identifies the position for an iterable and may name another variable. |
| SIZE_OF | `[SIZE_OF varname="..." /]` | Returns iterable size, otherwise `0`. |
| IS_EMPTY | `[IS_EMPTY varname="..." /]` | Tests missing, null, blank string, empty iterable, or empty map according to the documented rules. |
| IS_NOT_EMPTY | `[IS_NOT_EMPTY varname="..." /]` | Logical negative of `IS_EMPTY`. |
| CONTAINS | `[CONTAINS varname="..." value="..." /]` or `[CONTAINS varname="..."] ... [/CONTAINS]` | Supports string or iterable input. Attribute `value` and body are alternatives; `value` has priority when both exist. |
Do not require `type` merely because current examples commonly include it: some examples omit it. Resolve requiredness from the parser relations or runtime contract before emitting an error.
## Transformations
| Construct | Form | Key rules |
| --- | --- | --- |
| FORMAT | `[FORMAT varname="..." type="..." /]` or `[FORMAT type="..." pattern="..."] ... [/FORMAT]` | `varname` takes precedence over the body. Documented formatting covers number and date families; number modes include currency, integer, double, percent, and generic. |
| SPLIT | `[SPLIT regex="..." emptyIfBlank="true|false"] ... [/SPLIT]` | Applies a valid regular expression to a string result. `emptyIfBlank` defaults to `false`. An invalid regex is a runtime parsing error and can be checked statically only for a literal. |
| TRIM | `[TRIM varname="..." /]` or `[TRIM] ... [/TRIM]` | Trims a named variable or evaluated body. A found variable takes precedence; otherwise the body is evaluated. |
## Control structures
- IF shape: `[IF] [CONDITION] ... [/CONDITION] [THEN] ... [/THEN] { [ELSE IF] ... [/ELSE IF] } [ELSE] ... [/ELSE] [/IF]`.
- `CONDITION` must evaluate to boolean. There may be multiple `ELSE IF` blocks and at most one final `ELSE`; both are optional.
- WHILE shape: `[WHILE ...] [CONDITION] ... [/CONDITION] [DO] ... [/DO] [/WHILE]`.
- The WHILE section documents an optional `threshold` with default and maximum `32766`, but also contains a sentence saying the tag has no attributes. Treat this as an explicit documentation inconsistency.
- FOR shape: `[FOR varName="item" iterable="items"] ... [/FOR]`. The loop variable exists during the loop and is removed afterward.
- The FOR prose depends on both `varName` and `iterable`, but the generated relationship only shows a generic attribute node. Treat formal requiredness, attribute-name casing, duplicate/unknown attributes, null or non-iterable input, and shadowing as unresolved until confirmed against the runtime grammar.
## Code blocks
| Kind | Form | Meaning |
| --- | --- | --- |
| Assignment | `[% target = expression; ... %]` | Mutates variables; documented statements end with `;`. |
| Evaluation | `[% expression %]` | Evaluates and returns a result, often boolean in `CONDITION`. |
| Output | `[%= variable %]` | Writes a context variable; a missing variable is a runtime error. |
The expression language examples use assignment, equality/comparison, arithmetic, boolean operators, strings, numbers, booleans, and `null`. The PDFs do not provide a complete operator-precedence grammar; avoid inventing one without a runtime grammar source.
## ElixForms TAG payloads
`SCHEMAID` is positional:
- position 0: plugin name `SCHEMAID`;
- position 1: schema ID;
- position 2: column reference;
- position 3: `IUQOID`;
- position 4: line terminator, with a space selecting the default;
- position 5: column separator;
- position 6: default value;
- position 7: date/time formatter;
- position 8: language (documented as currently unused).
Positions 0 through 4 must be present. Preserve commas for omitted intermediate optional positions.
`GETVALUEBYTAG` is positional:
- position 0: plugin name `GETVALUEBYTAG`;
- position 1: tag name;
- position 2: lookup type: `REQUEST`, `MODULE`, or `USER_PROFILE`;
- position 3: `IUQOID`;
- position 4: weight/order option;
- position 5: column separator;
- position 6: format string.
The weight list in the prose and the final syntax example differ in spelling and membership (`UPDATED_FIST`/`UPDATED_FIRST`, `UPDATE_LAST`/`UPDATED_LAST`, and `CONCAT`). Treat exact validation as ambiguous until confirmed against the TAG runtime.
## Known implementation delta at skill creation
The current TypeScript tokenizer/parser does not yet model all documented constructs. Notably absent or incomplete are `LOG`, `FOR`, `IS_EMPTY`, `IS_NOT_EMPTY`, case-insensitive spellings, structural ordering inside IF/WHILE, attribute validation beyond VAR type, and full expression parsing. Re-check source before relying on this list because it is expected to shrink as the linter evolves.