# VL Lint Rules v4.4.2

> Lint document version: 4.4.2. Normatively aligned with VL Syntax Specification v4.4.3.
> This document defines all static analysis (lint) rules enforced by the VL parser.
> When the VL syntax specification is updated, this document MUST be updated accordingly.

## 1. Overview

VL Lint is a static validation pass that checks VL source files (`.vx`, `.sc`, `.cp`, `.vs`, `.vdb`, `.vth`) for structural, syntactic, and semantic correctness **without** generating runtime artifacts (cases, previews, etc.).

### 1.1 Invocation

```json
POST /edtfn/parsevl
{
  "action": "lintPjt",
  "files": { "...": "..." },
  "target": "local",
  "platformContext": {}
}
```

`lintPjt` / `tryParsePjt` SHOULD support the same project input forms as `parsePjt`:

- files project via `files` or `file`
- deployment request project via external platform context, when the action explicitly targets an online platform deployment or synchronization flow

For equivalent project content, input forms MUST return equivalent source validation results. Ordinary local lint does not require platform group ids or work/node ids. Platform deployment identity belongs to request context, not VL source.

`lintPjt` is the normative **project-level tryParse validation service**. It MUST execute the full no-side-effect analysis required to determine whether a project can be parsed correctly. It MUST NOT create or modify cases, save case JSON, create remote tables or other resources, update service metadata, refresh preview, or generate download packages.

`parsePjt` MUST execute the same tryParse validation before any generation or persistence step and MUST reuse that result. Validation logic MUST NOT be reimplemented as a separate parse-only hidden path. If validation reports any `error`, `parsePjt` MUST stop before generating or updating parse artifacts and MUST return the validation `errList`, together with `summary` if available. Warnings may be returned together with successful parse output.

Implementations MAY additionally expose `tryParsePjt` as an alias action. Before any public API rename, `lintPjt` remains the compatibility entry name.

### 1.2 Error Object Schema

Each lint error is reported as an object in the `errList` array:

```typescript
{
  level: "error" | "warning";     // Severity
  type: string;                   // Rule identifier (see §2–§5)
  message: string;                // Human/AI-readable description
  lineNumber: number;             // Line number in source file
  lineVL: string;                 // Original VL source line
  path?: string;                  // Source file path (e.g. "Apps/Main.vx")
  suggestion?: string;            // Optional fix suggestion
}
```

### 1.3 Severity Definitions

| Level | Meaning |
|-------|---------|
| `error` | Must be fixed before `parsePjt` can produce correct output. |
| `warning` | May produce suboptimal output; recommended to fix but does not block parsing. |

### 1.4 Single Validation Source

- **type**: architectural requirement
- **level**: normative
- **rule**: Project semantic validation must have a single normative source. `lintPjt` / `tryParsePjt` and `parsePjt` MUST share the same project-level analysis result, or share the same validation pipeline.
- **intent**: Prevent a split where some errors are checked in `lint` while others are duplicated in a separate parse-only path.

### 1.5 Version-Gated Rules

VL Lint contains both:

1. **cross-version rules**
   - rules that apply to all supported VL projects because they describe structural invalid states or interface-invalid states
2. **version-gated rules**
   - rules that apply only when the project's declared version is at or above the rule family's minimum VL version

The following rule families are **VL 4.0+ only**:

1. `.sc/.cp` real root model and `containerType`
2. frontend public/internal method section-based semantics
3. `Config/env.json` environment binding validation
4. `FAILIF` / `GUARD` statement validation
5. API `send(...)` explicit param-location validation
6. closed CSS property constraints and container main-axis contract rules

The following rule families are **VL 4.1+ only**:

1. first-release `affordance` missing upgraded from warning to error
2. `Chart` removed from the VL core built-in component set
3. project-level theme + app-level theme scope validation

The following rule families are **VL 4.2+ only**:

1. scroll container stable size carrier validation (`overflowSizeCarrierError`)
2. scroll list item same-axis shrink conflict validation (`scrollListItemAxisShrinkConflictError`)
3. `UserStore` placement, configuration, and uniqueness validation (`userStoreBackendTreeOnlyError`, `userStoreSourceTableMissingError`, `userStoreSourceTableInvalidError`, `userStoreDuplicateError`)
4. `Table-AuthUsers` / `Table-AuthUserIdentities` co-declaration and required field validation (`authUsersTableMissingError`, `authUserIdentitiesTableMissingError`, `authUsersFieldDeclarationMissingError`, `authUserIdentitiesFieldDeclarationMissingError`)

The following rule families are **VL 4.2.9+ only**:

1. per-node-class property applicability (`typographyOnNonTextNodeError`, `textAlignScopeError`, `gapScopeError`, `flexAlignScopeError`, `flexWrapScopeError`, `overflowScopeError`, `gridTemplateScopeError`, `foregroundSkinScopeError`, `surfaceSkinOnDividerError`, `internalLayoutOnFactoryInstanceError`)
2. component external size consumption contract (`componentSizeModeContractShapeError`, `componentSourceFrameFillError`, `componentSourceFixedMainFrameError`, `componentExpandedSurfaceOverConstrainedError`, `componentExpandedSurfaceOverflowError`)
3. component preview meta removal and interface example/required shape (`componentPreviewMetaUnsupportedError`, `interfaceMetaExampleShapeError`, `interfaceRequiredFieldShapeError`)
4. App / Page / Modal special boundary transitional warning (`appPageModalSpecialBoundaryPendingWarning`)

The following rule families are **VL 4.2.11+ only**:

1. source-meta header-block placement and mandatory name locators for `@meta` (`publicInterfaceMetaError`)
2. component reference angle-bracket shape validation (`componentReferenceShapeError`)

The following rule families are **VL 4.3.1+ only**:

1. `BackendSecurityToolkit` placement validation (`backendSecurityToolkitBackendTreeOnlyError`)

The following rule families are **VL 4.3.2+ current-contract additions**:

1. `FAILIF` canonical fail-fast statement validation, with `GUARD` retained as a compatibility alias
2. expression method purity and internal DB / VirtualTable result accessor validation (`expressionImpureMethodCallError`, `internalResultAccessorError`)
3. VirtualTable public result field validation (`virtualTableResultFieldError`)
4. VirtualTable `insertMany(...)` result field contract (`success`, `message`, `dataIds`)

The following rule families are **VL 4.3.6+ only**:

1. bare variable executable statement guidance (`bareVariableStatementWarning`)

The following rule families are **VL 4.4+ only**:

1. backend secret declaration and access validation (`backendSecretSectionPlacementError`, `backendSecretDeclarationSyntaxError`, `backendSecretNameConflictError`, `backendSecretFrontendAccessError`)
2. project environment binding validation (`projectEnvSchemaError`, `projectEnvSecretLiteralError`, `projectEnvSecretPlacementError`)

The following rule families are **VL 4.4.3+ only**:

1. unsupported `Config/` file validation: `Config/env.json` is the only legal current-spec `Config/` file; `Config/project.state.json`, `Config/project.settings.json`, `Config/secrets.json`, and other `Config/*` files are errors
2. platform deployment request-context validation (`platformDeploymentContextMissingError`)

Projects whose declared version is `VL_VERSION:3.x` MUST continue to use the compatible pre-4.0 rule path for these rule families.

---

## 2. Syntax Rules

Rules that check lexical and line-level syntax correctness.

### 2.1 Version Declaration Required

- **type**: `versionDeclarationMissingError`
- **level**: error
- **rule**: Every VL source file (`.vx`, `.sc`, `.cp`, `.vs`, `.vdb`, `.vth`) MUST declare `// VL_VERSION:x.y` in the first line comment. Missing declaration, malformed declaration, or placing the declaration after line 1 is an error.
- **rationale**: The parser and lint rule set are versioned. Without an explicit first-line version declaration, the file's syntax contract is ambiguous and project-level version consistency cannot be determined reliably.

### 2.2 Forbidden JavaScript Keywords

- **type**: `forbiddenSyntaxError`
- **level**: error
- **rule**: VL identifiers that are translated into JavaScript identifiers MUST NOT equal JavaScript/TypeScript reserved words (`let`, `const`, `var`, `function`, `class`, `import`, `export`, `async`, `await`, `yield`, `typeof`, `instanceof`, `new`, `delete`, `throw`, `try`, `catch`, `finally`, `switch`, `case`, `default`, `break`, `continue`, `return`, `do`, `while`, `with`, `debugger`, `void`).
- **rationale**: VL is a domain-specific language; native JS constructs are not valid VL syntax.
- **detection**: Check concrete identifier positions such as local variable names, method names, service names, pipe names, and parameter names. Do not scan the whole source line as plain text. Component class/name segments, quoted component ids, string literals, and comments are not JavaScript identifiers for this rule; for example `<Button-ExportBtn "exportBtn"> value:"Export"` is valid.

### 2.3 Forbidden Responsive Design Patterns

- **type**: `responsiveDesignError`
- **level**: error
- **rule**: VL source MUST NOT contain `@media` queries or conditional checks on `SYSENV.deviceType` / `WINDOW.deviceType`.
- **rationale**: VL follows "one application, one target device" philosophy. Device adaptation is handled at the App level via `DEVICE_TARGET` in `# SysConfig`.

### 2.4 Invalid Chapter Names

- **type**: `invalidChapterError`
- **level**: error
- **rule**: Chapter annotations (`# ChapterName`) must be in the allowed list for the current VL file type. For example, `.vx` files allow `# SysConfig`, `# Frontend Global Vars`, `# Frontend Tree`, `# Frontend Event Handlers`, `# Frontend Internal Methods`, `# Frontend Pipeline Funcs`.
- **rationale**: Prevents misspelled or misplaced chapter headers that would cause parser misrouting.

### 2.5 Invalid Component Event Definition

- **type**: `invalidCompEventDefError`
- **level**: error
- **rule**: Component event definitions (`<CompType-Name "componentId">.@eventName(...)`) must use the standard component reference shape and must appear in `# Frontend Event Handlers` or `# Backend Event Handlers` sections. The quoted `componentId`, when present, must be a non-empty static locator string; it must not contain whitespace, dots, colons, quotes, or expression syntax. ComponentId naming convention is defined by the VL spec and is not a blocking parser/lint error here.
- **detection**: Regex match for `<...>.@...` pattern in component definition context. A listener line such as `<Button-NavOverview "navItemOverview">.@click()` is valid when the same quoted id appears on the matching component declaration in the tree.
- **message requirement**: The error message should mention valid event-handler sections and the quoted componentId shape when the listener line is malformed.

### 2.6 Component Declaration Must Be Single-Line

- **type**: `multilineComponentDeclarationError`
- **level**: error
- **rule**: A component start declaration MUST be completed on a single line. It is invalid to continue the same component declaration on following lines.
- **scope**: Applies to all VL source files that contain component declarations, including `.vx`, `.sc`, `.cp`, `.vs`, `.vdb`, and `.vth`.
- **note**: This includes `params:(...)` and `returns:(...)` when they are part of the same component declaration line.

---

## 3. Structure Rules

Rules that validate the hierarchical structure and nesting of VL constructs.

### 3.1 Top-Level Entry Uniqueness

- **type**: `topEntryError`
- **level**: error
- **rule**: Each VL file MUST have exactly one top-level root component (`<App-...>` for `.vx`, `<Section-...>` for `.sc`, `<Component-...>` for `.cp`, `<ServiceDomain-...>` for `.vs`). A second top-level definition is an error.

### 3.2 Top-Level Tag Position

- **type**: `topLevelError`
- **level**: error
- **rule**: Root-level component types (App, ServiceDomain, etc.) MUST NOT appear as nested children (level > 0). Only Section, Component, Theme, WebComponent, and ServiceDomain are allowed as nested references.

### 3.3 Indentation Level Jump

- **type**: `levelJumpError`
- **level**: error
- **rule**: Component nesting level MUST NOT increase by more than 1 at a time. Going from level N directly to level N+2 or deeper is an error.
- **example (bad)**:
  ```
  <Page-Home "home"> path:"home"
  ---<Text-Title "title">    // ERROR: jumped from level 0 to level 3
  ```

### 3.4 Block Level Mismatch

- **type**: `levelError`
- **level**: error
- **rule**: A child component's chapter annotation must be consistent with its parent's. A component defined under `# Frontend Tree` cannot have a child annotated as `# Backend Event Handlers`.

### 3.5 Section Nesting Prohibition

- **type**: `sectionNestError`
- **level**: error
- **rule**: Section (code fragment) files MUST NOT be nested inside other Section definitions. Sections are referenced by the App, not by other Sections.

### 3.6 Component Position Constraint

- **type**: `viewContainOtherCompError`
- **level**: error
- **rule**: In App definition mode, Section references are leaf nodes — they MUST NOT contain child component definitions inline. Style components cannot be placed inside For/If logic containers.

### 3.7 Page Must Be Direct Child of App (.vx only)

- **type**: `appStructureError`
- **level**: error
- **rule**: In `.vx` files, `<App-...>` is the real root in `# Frontend Tree` and `<Page-...>` components MUST be its direct children (one indentation level `-` under the App root). Pages nested under any intermediate wrapper component are an error.
- **rationale**: The VL spec requires Pages to be placed directly under the `<App>` real root in `# Frontend Tree`. Tags like `<FrontendApp-...>`, `<StageApp-...>`, or `<Stage-Root>` do not exist in the VL specification.
- **example (bad)**:
  ```
  # Frontend Tree
  <App-Main "app">
  -<FrontendApp-Wrapper "wrapper">        // ERROR: not a valid VL component
  --<Page-Home "home"> path:"home"        // ERROR: Page nested below an invalid wrapper
  ```
- **example (correct)**:
  ```
  # Frontend Tree
  <App-Main "app">
  -<Page-Home "home"> path:"home"
  --<Section-Main "main">
  ```

### 3.8 Internal Method Scope Mismatch

- **type**: `invalidInternalMethodScopeError`
- **level**: error
- **rule**: Server-scope internal methods (`METHOD_B`) can only be defined in `.vs` (ServiceDomain) files. Client-scope internal methods (`METHOD`) cannot be defined in `.vs` files.

### 3.9 Frontend Method Section Semantics (VL 4.0+)

- **type**: `invalidFrontendPublicMethodScopeError`
- **level**: error
- **rule**: In `.sc/.cp` files whose declared version is `VL_VERSION:4.0` or higher, frontend method visibility is determined by definition section:
  - `# Frontend Public Methods` → public method
  - `# Frontend Internal Methods` → internal method
- **rule**: `.vx` files MUST NOT define `# Frontend Public Methods`

- **type**: `deprecatedMethodPubWarning`
- **level**: warning
- **rule**: In `VL_VERSION:4.0+` projects, using `METHOD_PUB` produces a warning. `# Frontend Public Methods` must use `METHOD`.

- **type**: `frontendPublicMethodNameFormatError`
- **level**: error
- **rule**: In `VL_VERSION:4.0+` projects, methods under `# Frontend Public Methods` MUST use `PascalCase`.

- **type**: `frontendInternalMethodNameFormatError`
- **level**: error
- **rule**: In `VL_VERSION:4.0+` projects, methods under `# Frontend Internal Methods` MUST use `camelCase`.

- **type**: `methodSectionScopeError`
- **level**: error
- **rule**: Method definition sections and host file types MUST stay consistent:
  - frontend public methods may only be defined in `.sc/.cp` under `# Frontend Public Methods`
  - frontend internal methods may only be defined in allowed frontend-internal executable sections
  - backend internal methods may only be defined in backend / service execution scope
  - lint must reject any method whose definition section semantics conflict with its host file semantics

### 3.10 `.sc/.cp` Real Root Model (VL 4.0+)

- **type**: `invalidRootContainerTypeError`
- **level**: error
- **rule**: In `.sc/.cp` files whose declared version is `VL_VERSION:4.0` or higher, root `containerType` may only be `col`, `row`, or `grid`.

- **type**: `invalidRootContainerTypeScopeError`
- **level**: error
- **rule**: `containerType` may only be declared on `.sc/.cp` root components. It must not be used on `.vx` roots, non-root components, or non-frontend files.

- **type**: `rootExternalLayoutError`
- **level**: error in `strict` lint mode only; default lint mode does not report this diagnostic.
- **rule**: In `VL_VERSION:4.0+` `.sc/.cp` files, external main-axis / outer-spacing skeleton props such as `width`, `height`, `flex`, `margin`, `margin-top`, `margin-right`, `margin-bottom`, and `margin-left` should not be written directly on the internal root. These props belong to the host instance skeleton; when written on the internal root they may be ignored or fail to produce the intended outer layout, but they do not block parsing.

- **type**: `rootEventScopeError`
- **level**: error
- **rule**: In `VL_VERSION:4.0+` `.sc/.cp` files, root events may be declared directly on `<Section-... "root">` or `<Component-... "root">`. Lint must treat these bindings as valid root-event ownership and must not require them to be moved onto the first child node or any proxy container.

- **note**: In `VL_VERSION:4.0+`, `.sc/.cp` `# Frontend Tree` may contain multiple first-level child nodes under the real root. Lint must not reject this shape.

### 3.11 Declaration Sections Must Not Contain Executable Statements

- **type**: `declarationSectionExecutableStatementError`
- **level**: error
- **rule**: Declaration-only sections such as `# Frontend Tree`, `# Backend Tree`, `# Frontend Public Props`, `# Frontend Public Events`, `# Frontend Public Methods`, `# Frontend Global Vars`, `# Backend Environment Vars`, and `# Backend Secrets` MUST NOT contain executable statements or event-handler definitions.
- **section contract**: `# Frontend Tree` and `# Backend Tree` declare component instances and parent-child structure only. Component event-handler listener lines such as `<Component-X "id">.@click(...)` must be written in `# Frontend Event Handlers` or `# Backend Event Handlers`, with their handler body indented under the listener. Public interface event declarations such as `EVENT @selected(...)` belong only in `# Frontend Public Events`; they are not component-tree children. Inside `# Frontend Public Events` only, shorthand declarations such as `@sectionSelected(sectionKey:STRING)` and `@sectionSelected(sectionKey(STRING))` are compatibility-valid and must be treated as public event declarations, not executable event triggers.
- **forbidden examples**:
  - `<VirtualTable-Notes "notesTable">.select(...) -> _result`
  - `<Input-Name "nameInput">.@change(value)`
  - `-$local = ...`
  - `-IF ...`
  - `-FAILIF ...`
  - `-GUARD ...`
  - `-RETURN ...`
  - `-ROLLBACK ...`
- **message requirement**: When the offending statement is a component event-handler listener line, parser/lint must explicitly say that event handlers are only allowed in `# Frontend Event Handlers` / `# Backend Event Handlers`, and that the current declaration-only section only declares structure.

### 3.11.1 Backend Secret Declarations

- **type**: `backendSecretSectionPlacementError`
- **level**: error
- **rule**: `# Backend Secrets` is only valid in `.vs` files and must appear before `# Backend Tree`.

- **type**: `backendSecretDeclarationSyntaxError`
- **level**: error
- **rule**: A backend secret declaration must use `SECRET NAME "description"` with a valid identifier name and an optional quoted description. It must not include a type annotation, plaintext value, default value, or inline `secretRef`.

- **type**: `backendSecretNameConflictError`
- **level**: error
- **rule**: Within a ServiceDomain, backend `SECRET` names and backend `ENV` names share one runtime `SYSENV` namespace. Duplicate names or names that collide across `# Backend Environment Vars` and `# Backend Secrets` are invalid.

- **type**: `backendSecretFrontendAccessError`
- **level**: error
- **rule**: Frontend files and frontend sections must not declare backend secrets and must not reference `SYSENV.<NAME>` when `<NAME>` is declared as a backend secret.

### 3.12 Project File Version Must Be Consistent (PRJ-VR-001)

- **type**: `projectVersionMismatchError`
- **level**: error
- **rule**: All VL source files in the same project (`.vx`, `.sc`, `.cp`, `.vs`, `.vdb`, `.vth`) MUST declare the same `// VL_VERSION:x.y` major/minor version on the first line. Mixing file versions within one project is forbidden.
- **example (bad)**:
  ```
  // Apps/Main.vx
  // VL_VERSION:2.6

  // Theme/Project.vth
  // VL_VERSION:3.5
  ```
- **rationale**: Mixed-version projects combine incompatible authoring rules and often produce parse output that appears successful but renders incorrectly.
- **note**: Files missing a valid first-line version declaration are handled by §2.1 and do not exempt the project from version consistency checks.

### 3.13 `.sc/.cp` Component External Size Consumption Contract (VL 4.2.9+)

Rules in this subsection enforce a deterministic external-size contract for factory-authored `.sc/.cp` components: when a component is implemented, its real visible body — not just an empty outer placeholder — must consume the external `width` / `height` declared by the component instance. Lint only checks author-declared internal sizing contracts and the explicitly declared frame carrier; no heuristic visual judgement is performed.

#### 3.13.1 Node Vocabulary

1. **Real root**: the `<Section-...>` / `<Component-...>` root in a `.sc/.cp` file. The `rootExternalLayoutError` rule reports direct `width` / `height` on the real root only in strict lint mode.
2. **Frame carrier**: a direct visual child under the real root, explicitly designated by `@contract component sizeMode.frameCarrier`. Lint never guesses the "first visual child"; the carrier must be named.
3. **Layout optionality**: declaring `@contract component sizeMode` is optional; once declared, `mode` and `frameCarrier` become required. Core parser/lint MUST NOT emit an error only because a normal `.sc/.cp` source omits `sizeMode`; factory upload or group preflight MAY require it as a product-specific authoring policy.
4. **sizeMode visibility**: `@contract component sizeMode` is an internal source contract used by parser / lint / factory authoring checks. It is not a public `@meta` field, is not published to the online component registry's `metadataJson`, and must not surface in component search, download descriptions, or IDE public-prop panels.
5. **Two-state components**: when a component contains an expanded auxiliary surface (dropdown menu, popover, tooltip, in-component panel), the default-state body is the frame carrier and the expanded surface is described via `sizeMode.expandedSurface`. External `height` constrains the default-state body, not the expanded surface's content height.
6. **Anchor carrier**: `expandedSurface.anchorCarrier` is the layout container responsible for layer order and overflow; it must be a `Row` / `Col` / `Grid` / `Block`. `expandedSurface.trigger` is an optional interactive control id (often a `Button`). The two may differ; a `Button` must not serve as the anchor carrier.

#### 3.13.2 Component SizeMode Contract Shape Error

- **type**: `componentSizeModeContractShapeError`
- **level**: error
- **version gate**: `VL_VERSION:4.2.9+`
- **rule**: `@contract component sizeMode`, when present, must be an object. Once `sizeMode` is declared, `sizeMode.mode` and `sizeMode.frameCarrier` are required. `sizeMode.mode` may only be `"full-frame"` or `"content-height"`. `sizeMode.frameCarrier` must be a non-empty string id of a direct visual child under the real root. `sizeMode.responsiveAxes`, when present, must be a non-empty array containing only `"width"` and/or `"height"`; for `mode:"content-height"`, omitted `responsiveAxes` defaults to `["width"]`; for `mode:"full-frame"`, effective responsive axes are always `["width","height"]`. `sizeMode.expandedSurface`, when present, must be an object with non-empty string `anchorCarrier` and `surface`; `trigger` is optional and, when present, must be a non-empty string.
- **scope**: Only checks `@contract component sizeMode` in `.sc/.cp` source comments.
- **message**: `@contract component sizeMode must declare a stable internal sizing contract: mode and frameCarrier are required; responsiveAxes and expandedSurface must match the component sizing schema.`

#### 3.13.3 Component Source Frame Fill Error

- **type**: `componentSourceFrameFillError`
- **level**: error
- **version gate**: `VL_VERSION:4.2.9+`
- **rule**: In `.sc/.cp` component source, when `@contract component sizeMode:({mode:"full-frame",frameCarrier:"<id>"})` is declared, the referenced direct visual child under the real root MUST explicitly consume the component instance frame with `width:"100%"` and `height:"100%"`, or an equivalent resolvable full-frame strategy defined by the compiler.
- **scope**: Only checks `.sc/.cp` source that explicitly declares `sizeMode.mode:"full-frame"`. `.vx` use sites and content-height components do not trigger this rule.
- **message**: `.sc/.cp full-frame component source must expose frameCarrier "<id>" with width:"100%" height:"100%" so external width/height resize the visible component body.`

#### 3.13.4 Component Source Fixed Main Frame Error

- **type**: `componentSourceFixedMainFrameError`
- **level**: error
- **version gate**: `VL_VERSION:4.2.9+`
- **rule**: In `.sc/.cp` component source, a declared `sizeMode.frameCarrier` MUST NOT use fixed `width` / `height` values on axes covered by the declared or defaulted sizing contract. For `mode:"full-frame"`, both axes are covered. For `mode:"content-height"`, declared `responsiveAxes` are checked; if `responsiveAxes` is omitted, the default checked axis is `width`.
- **scope**: Only checks the direct visual child referenced by `@contract component sizeMode.frameCarrier`. Internal fixed-size icons, buttons, or decorative nodes are not checked.
- **message**: `.sc/.cp component source main frame carrier must not declare fixed "<propName>". External component width/height must resize the visible component body, not only an empty outer box.`

#### 3.13.5 Component Expanded Surface Over-Constrained Error

- **type**: `componentExpandedSurfaceOverConstrainedError`
- **level**: error
- **version gate**: `VL_VERSION:4.2.9+`
- **rule**: In `.sc/.cp` component source, an expanded auxiliary surface MUST NOT be constrained by the default-state frame height with `height:"100%"`. Expanded surfaces should follow the anchor width but use content height, max-height, viewport strategy, or another explicit expanded-state height strategy.
- **scope**: Only checks the expanded surface explicitly designated by `@contract component sizeMode.expandedSurface.surface`. Lint never identifies expanded surfaces by node type, id, or name keywords such as `Menu` / `Popover` / `Dropdown`. If `expandedSurface.surface` is not declared, this rule does not fire.
- **message**: `Expanded surface "<Type-Name>" must not declare height:"100%". External height applies to the default-state body; expanded menus/popovers follow anchor width but keep their own content height.`

#### 3.13.6 Component Expanded Surface Overflow Error

- **type**: `componentExpandedSurfaceOverflowError`
- **level**: error
- **version gate**: `VL_VERSION:4.2.9+`
- **rule**: In `.sc/.cp` component source, an expanded auxiliary surface and its declared source-level anchor carrier MUST allow overflow visibility unless the surface is rendered into a platform overlay layer. Direct in-component dropdown / popover implementations must declare `overflow:"visible"` on `sizeMode.expandedSurface.anchorCarrier` and on `sizeMode.expandedSurface.surface`.
- **scope**: Only checks expanded surfaces explicitly declared via `@contract component sizeMode:({expandedSurface:{anchorCarrier:"<id>",surface:"<id>"}})`. `sizeMode.expandedSurface.anchorCarrier` must point to a layout container that can legally declare `overflow` (`Row` / `Col` / `Grid` / `Block`); it must not point to `Button` / `Text` / `Input` / `Page` or any node excluded by `overflowScopeError` or by the App / Page / Modal special-boundary rules. Platform-native Modal / Toast / Drawer surfaces are out of scope.
- **message**: `Expanded surface "<Type-Name>" needs overflow:"visible" on the source anchor chain, otherwise it can be clipped by the default-state component frame.`

---

## 4. Component & Type Rules

Rules that validate component types, references, and naming.

### 4.1 Unknown Component Type

- **type**: `unknownCompTypeError`
- **level**: error
- **rule**: Every component tag `<Type-Name>` must have `Type` recognized by the platform — either as a VL special type (App, Section, Component, Page, etc.), a platform-supported built-in component type (Row, Col, Block [DEPRECATED], Text, Button, Input, etc.), or a valid module reference. If the type is not found in any supported component set, it is an error.
- **rationale**: Prevents AI-fabricated component types (e.g. `<FrontendApp-...>`, `<StageApp-...>`, `<AppContainer-...>`) from silently being treated as code fragment placeholders.
- **note**: When detected in `.vx` files, the error message explicitly warns against inventing wrapper components.

### 4.2 Component Definition Missing

- **type**: `compDefMissingError`
- **level**: error
- **rule**: Referenced component definitions (via Section/Component import) must exist in the project. Missing definitions produce an error.

### 4.2.1 Component Reference Angle Bracket Shape

- **type**: `componentReferenceShapeError`
- **level**: error
- **version gate**: Applies to files whose first-line declaration is `VL_VERSION:4.2.11` or higher.
- **rule**: A component reference's angle-bracket segment may contain only `ComponentClass-ComponentName` and optional `"componentId"`. `componentId` must be a non-empty quoted static locator string and must be unique within the current VL file's component tree / backend tree. Component functional props, `style`, `sk.*`, skeleton CSS props, control props, event bindings, and all other attributes must appear after the closing `>`.
- **examples**: `<Button-Submit "submit-btn"> style:"primary|filled" value:"提交"` is valid; `<Button-Submit style:"primary|filled"> value:"提交"` is invalid.
- **invalid id examples**: `<Button-Nav "nav.item">`, `<Button-Nav "$navId">`, and `<Button-Nav "nav item">` are invalid. Use a stable quoted id such as `"navItemOverview"`.

- **type**: `componentLineSyntaxError`
- **level**: error
- **rule**: A component declaration line MUST NOT end with an extra trailing `>` after its properties. For example, `<Modal-Create "modal"> show:$visible style:"overlay|soft">` is invalid; remove the final `>`.

### 4.3 Module Missing

- **type**: `modMissingError`
- **level**: error
- **rule**: Referenced Section/Component modules must exist as files in the project. If the `.sc`/`.cp` file is not found, an error is raised.

### 4.4 Service Missing

- **type**: `serviceMissingError`
- **level**: error
- **rule**: Referenced backend services must exist in a `.vs` ServiceDomain file.

### 4.5 Local Variable Name Conflict with JS Keywords

- **type**: `forbiddenSyntaxError`
- **level**: error
- **rule**: Local variable names (`_varName`) MUST NOT use JavaScript reserved words as identifiers.

### 4.6 Interface Existence Is Compile-Blocking

- **type**: `eventNotDefError`
- **level**: error
- **rule**: Referenced or listened events must exist in the target component or module interface.

- **type**: `methodNotDefError`
- **level**: error
- **rule**: Called methods must exist in the target component, module, or service interface.

- **type**: `paramSignatureMismatchError`
- **level**: error
- **rule**: Event, method, and service calls must match the target interface signature in parameter count, ordering, requiredness, and semantic binding.

- **type**: `requiredInterfaceFieldMissingError`
- **level**: error
- **rule**: Required props, required method params, and required event output references must not be omitted.

### 4.7 Config and External Platform Context Validation

#### 4.7.1 Environment Binding Schema

- **type**: `projectEnvSchemaError`
- **level**: error
- **rule**: In `VL_VERSION:4.4+` projects, when `Config/env.json` exists, it must be a top-level object keyed by deployment environment names. Each environment entry may contain `backend`; `backend.env` and `backend.secrets`, when present, must be objects.

- **type**: `projectEnvSecretLiteralError`
- **level**: error
- **rule**: In `VL_VERSION:4.4+` projects, `Config/env.json` `backend.secrets` entries must be objects with a non-empty string `secretRef`. Plain string, number, boolean, array, null, or any object without `secretRef` is invalid for a secret binding.

- **type**: `projectEnvSecretPlacementError`
- **level**: error
- **rule**: In `VL_VERSION:4.4+` projects, a key declared by `.vs` `# Backend Secrets` must not be configured under `backend.env`; it must be configured under `backend.secrets`. A key declared by `.vs` `# Backend Environment Vars` must not be configured under `backend.secrets`.

#### 4.7.2 Unsupported Config Files

- **type**: `projectConfigUnsupportedFileError`
- **level**: error
- **rule**: In `VL_VERSION:4.4.3+` projects, `Config/env.json` is the only legal file under `Config/`. Files such as `Config/project.state.json`, `Config/project.settings.json`, `Config/secrets.json`, or any other `Config/*` file are invalid current-spec project files. Parser and lint tooling MUST NOT read `gid`, `targetGid`, `nid`, `backend.nid`, or `frontends.*.nid` from those files as deployment context.
- **detection**: Report the unsupported `Config/` file path. Do not scan arbitrary source text, comments, string literals, business object fields, or environment variable names for substrings such as `gid` / `nid`.
- **message requirement**: `Config/env.json is the only supported Config file; remove <path> or move tool-owned deployment state outside the VL project.`
- **rationale**: The current project contract keeps source configuration limited to environment value bindings and secret references. Platform deployment identity belongs to parser request context or external tool-owned context, not project files.

#### 4.7.3 Deployment Request Context

- **type**: `platformDeploymentContextMissingError`
- **level**: error
- **rule**: For parser actions that perform online platform deployment or synchronization, if the selected target requires a platform group/work binding and the request does not provide the required external platform context, parser reports a request validation error before side effects.
- **scope**: This is a parser request validation error, not a VL source lint error. `lintPjt` and local-only parse/check flows must not require this context.
- **local target**: When `target:"local"` is requested, or when no deployment target is requested and local rustbase is available, absence of platform group ids and work/node ids is valid.

Examples:

Must report `projectConfigUnsupportedFileError` and must not use this file as deployment context:

```text
Config/project.state.json
{
  "gid": 123,
  "backend": { "nid": 456 },
  "frontends": { "Apps/AdminApp.vx": { "nid": 789 } }
}
```

Must report `projectConfigUnsupportedFileError` and must not use this file as deployment context:

```text
Config/project.settings.json
{
  "gid": 123,
  "backend": { "nid": 456 },
  "frontends": { "Apps/AdminApp.vx": { "nid": 789 } }
}
```

Must still validate `Config/env.json` under the environment binding rules:

```text
Config/env.json
{
  "local": {
    "backend": {
      "env": {
        "WECHAT_AGENT_ID": "1000019"
      },
      "secrets": {
        "WECHAT_SECRET": { "secretRef": "wechat.default.secret" }
      }
    }
  }
}
```

Must not report a platform deployment config error only because business code contains a normal identifier or string that happens to include the same letters as platform id names:

```vl
$campaignId(STRING) = ""
$candidateName(STRING) = ""
```

---

## 5. Affordance Rules

Rules that validate the new `affordance` static dimension, runtime-state boundary, and upgraded Theme contract.

### 5.1 Affordance Point Legality

- **type**: `affordancePointInvalidError`
- **level**: error
- **rule**: The `style` coordinate may only use the following `affordance` points: `passive`, `listitem`, `navitem`, `actionable`, `selectable`.

### 5.2 Unsupported Template Uses Affordance

- **type**: `affordanceTemplateUnsupportedError`
- **level**: error
- **rule**: Only first-release templates may declare effectful `affordance`: `Block`, `Row`, `Col`, `Grid`, `Button`, `ButtonContainer`. Other templates using non-passive `affordance` are an error. `Text` / `Icon` may include `passive` as a no-op compatibility point and MUST NOT report this error.

### 5.3 Passive Must Not Depend On Interaction States

- **type**: `passiveInteractionDependencyError`
- **level**: error
- **rule**: Components declared as `passive` must not declare static style or rule dependencies on runtime interaction states `hover`, `active`, `focus`, or `selected`.

### 5.4 Runtime States Forbidden In Style Coordinates

- **type**: `runtimeStateInStyleError`
- **level**: error
- **rule**: `hover`, `active`, `focus`, `selected`, `disabled`, `invalid`, and `rest` must not appear as static style points inside `style`.

### 5.5 Selected Is Runtime-Only

- **type**: `selectedUsedAsStaticPointError`
- **level**: error
- **rule**: `selected` is a runtime state only. It must not be used as a static dimension point, pseudo-static state point, or literal `style` coordinate value.

### 5.6 Theme Version And Structure Check

- **type**: `themeVersionMismatchError`
- **level**: error
- **rule**: A project using the upgraded affordance model must use a Theme file with `styleSpaceVersion:"2.0"`. Theme template `version:"x.y.z"` is not the rule-contract field and must not be treated as the compile-blocking compatibility key.

- **type**: `themeStateValuesForbiddenError`
- **level**: error
- **rule**: The Theme file must not contain any `state.*` point-slot values in the upgraded affordance model.

### 5.7 Default Affordance On First-Release Template

- **type**: none
- **level**: none
- **rule**: In `VL_VERSION:4.0+`, if a first-release template (`Block`, `Row`, `Col`, `Grid`, `Button`, `ButtonContainer`) declares `style` but omits `affordance`, parser/lint must not report a missing-affordance diagnostic. Parser applies the current component default: `Button` / `ButtonContainer` default to `actionable`; `Block` / `Row` / `Col` / `Grid` default to `passive`.

- **note**: If no `style` coordinate is declared at all, this rule does not require `affordance`.

### 5.8 Non-First-Release Template Still StateEnabled

- **type**: `legacyStateEnabledWarning`
- **level**: warning
- **rule**: Non-first-release templates that still declare `stateEnabled:true` under the upgraded affordance model produce a warning because they are outside the 2.0 runtime-state consumption set.

### 5.9 Theme Scope Validation (`VL 4.1+`)

- **type**: `projectThemeMultiplicityError`
- **level**: error
- **rule**: A VL project may declare at most one project-level theme file under `Theme/`.
- **scope**: Only `Theme/*.vth` participates as a project-level theme. Tooling/cache documentation paths such as `.vl-code/docs/**` and `.vth` files outside `Theme/` MUST NOT be counted as project themes.

- **type**: `appThemeMultiplicityError`
- **level**: error
- **rule**: Each App may declare at most one app-level theme file under `Theme/Apps/`.

- **type**: `unsupportedThemeScopeError`
- **level**: error
- **rule**: `VL_4.1` supports only project-level theme and app-level theme. Page-level, section-level, and component-level theme file scopes are not supported.

- **type**: `unsupportedThemeScopeError`
- **level**: error
- **rule**: In `VL_4.1+`, an app-level theme file under `Theme/Apps/` MUST declare `# Meta app:"<AppName>"`. Missing app binding or binding to a non-existent App is an error.

- **note**: Missing app-level theme is valid. The App must fall back to the project-level theme.

### 5.10 Chart Removed From Core Built-ins (`VL 4.1+`)

- **type**: `deprecatedBuiltinChartError`
- **level**: error
- **rule**: In `VL_VERSION:4.1+`, `Chart` is not a VL core built-in component. Direct use of `<Chart-...>` in standard VL code is not allowed.

## 6. Property & Expression Rules

Rules that validate component properties, expressions, and bindings.

### 6.1 Property Mapping Error

- **type**: `propError`
- **level**: error
- **rule**: Component property names must exist in the platform or project-defined interface for the given component type. Unmapped properties produce an error.
- **note**: `Icon.value` is the normative Font Awesome icon content property in VL 4.2.13+. It MUST NOT produce `propError`. `Icon.content` remains accepted as a compatibility alias.

### 6.1.1 Icon Content Prop Conflict

- **type**: `iconValueContentConflictError`
- **level**: error
- **rule**: `Icon` uses `value` as the normative Font Awesome content property. `content` is a compatibility alias for old source files. One `Icon` declaration MUST NOT include both `value` and `content`; keep `value` and remove `content`.
- **message**: `Icon must not declare both "value" and "content". Use "value" for Icon content; "content" is compatibility-only.`

### 6.2 Property Format Error

- **type**: `propFormatError`
- **level**: error
- **rule**: Component property definitions must follow the `key:"value"` or `key:expression` format.

### 6.3 Expression Parse Error

- **type**: `formulaError`
- **level**: error
- **rule**: All expressions (property values, conditions, assignments) must be parseable by the VL expression engine. Syntax errors, unmatched brackets, and invalid references produce errors.

### 6.4 sk.* Literal Value Constraint

- **type**: `formulaError`
- **level**: error
- **rule**: `sk.*` values may be a static string literal, a static number literal, or an expression whose runtime result is `string`, `number`, or `null`. Bare `boolean` / `null` literals are forbidden.
- **example**: `sk.opacity:0.5` is valid; `sk.bg:null` is invalid; `sk.bg:false` is invalid.

### 6.5 Unknown sk.* Property

- **type**: `formulaError`
- **level**: error
- **rule**: Only recognized `sk.*` property names are allowed: `sk.bg`, `sk.fg`, `sk.bgImage`, `sk.borderColor`, `sk.borderWidth`, `sk.borderTop`, `sk.borderRight`, `sk.borderBottom`, `sk.borderLeft`, `sk.shadow`, `sk.opacity`, `sk.radius`. Unknown `sk.*` names produce an error.

### 6.6 CSS Property Constraints In VL (VL 4.0+)

- **type**: `forbiddenCssPropertyError`
- **level**: error in `strict` lint mode only; default lint mode does not report this error for now.
- **rule**: In `VL_VERSION:4.0+` strict lint mode, the following CSS properties must not be written directly in VL component code: `display`, `flex-direction`, `flex-grow`, `flex-shrink`, `flex-basis`, `flex-flow`.

- **type**: `cssPropertyScopeError`
- **level**: error
- **rule**: `containerType` is a VL structure attribute, not a general style prop. It may only be declared on `.sc/.cp` root.

- **type**: `restrictedCssValueError`
- **level**: error
- **rule**: In `VL_VERSION:4.0+`, `flex` accepts positive numeric grow factors such as `flex:"1"`, `flex:1`, `flex:"2"`, and `flex:"0.5"`. CSS shorthand values such as `flex:"1 1 auto"`, `flex:"auto"`, `flex:"none"`, and `flex:"0 0 240px"` remain invalid. `flex-wrap` is restricted to `flex-wrap:"wrap"` or `flex-wrap:"nowrap"`; `wrap-reverse` and arbitrary CSS values are invalid.

- **type**: `containerChildMainAxisContractError`
- **level**: error in strict lint mode only
- **rule**: In `VL_VERSION:4.0+` strict lint mode, when a `Section` or `Component` instance is a direct child of parent `Row` or `Col`, it must declare exactly one main-axis contract:
  - under parent `Row`: exactly one of `width` or `flex`
  - under parent `Col`: exactly one of `height` or `flex`

- **type**: `containerFlexChildHostContractError`
- **level**: error in `strict` lint mode only; default lint mode does not report this diagnostic.
- **rule**: In `VL_VERSION:4.0+` strict lint mode, if a `Row` or `Col` has any direct child declaring positive numeric `flex`, the parent container itself should have an explicit host sizing intent for the axis consumed by that child:
  - parent `Row`: horizontal host contract is `width`; `flex` conflicts with `width` only when the parent direction makes `flex` same-axis
  - parent `Col`: vertical host contract is `height`; `flex` conflicts with `height` only when the parent direction makes `flex` same-axis
- **note**: Missing host sizing intent and same-axis duplicate contracts are layout stability diagnostics. `width:"100%"` / `height:"100%"` count as valid host main-axis contracts. A `Row` under a parent `Col` may declare both `width` and `flex`; a `Col` under a parent `Row` may declare both `height` and `flex`. This rule applies to all direct children that declare positive numeric `flex`, not only container-type children. It also applies to the first internal `Row` / `Col` under `.sc/.cp` root.

- **type**: `exclusiveCssPropertyFamilyError`
- **level**: error
- **rule**: In `VL_VERSION:4.0+`, the following property families cannot mix shorthand and split forms on the same component:
  - `padding` with any of `padding-top`, `padding-right`, `padding-bottom`, `padding-left`
  - `margin` with any of `margin-top`, `margin-right`, `margin-bottom`, `margin-left`

- **type**: `lintWarning`
- **level**: warning
- **rule**: In `VL_VERSION:3.x`, inline skin-oriented CSS properties written directly on component instances produce warning `SK-003`. This includes `color`, `background`, `background-color`, `background-image`, `background-repeat`, `background-position`, `background-size`, `border`, `border-top`, `border-right`, `border-bottom`, `border-left`, `border-color`, `border-width`, `border-style`, `box-shadow`, `opacity`, `border-radius`, `text-transform`, and `cursor`.

- **type**: `forbiddenCssPropertyError`
- **level**: error in `strict` lint mode only; default lint mode does not report this error for now.
- **rule**: In `VL_VERSION:4.0+` strict lint mode, the same skin-oriented CSS properties listed in `SK-003` must not be written directly on component instances. Use Theme style coordinates, legal `sk.*` props, or `affordance.cursor` instead.
- **note**: The closed direct-write skeleton whitelist includes size-constraint props `min-width`, `max-width`, `min-height`, and `max-height`, and text metric prop `font-style`. These props are legal direct-write skeleton CSS props in VL 4.0+ and must not be rejected as forbidden solely for being size constraints or text style.

- **note**: Automatic shrink correction for `flex:"1"` is a system behavior, not an authoring obligation:
  - under parent `Row`, the system injects `min-width:"0"`
  - under parent `Col`, the system injects `min-height:"0"`
  - if authors explicitly declare `min-width` or `min-height`, the explicit value wins

### 6.7 Per-Node-Class Property Applicability (VL 4.2.9+)

Rules in this subsection enforce a global property-applicability matrix keyed on node class. Each rule corresponds to one `❌` cell in that matrix; a single violating line emits exactly one error from this subsection (see §6.7.12 priority clause for the factory-instance carve-out).

#### 6.7.1 Node Classification

- **Layout containers / general layout containers**: `Row` / `Col` / `Grid` / `Block`
- **Flex/grid arrangement containers**: `Row` / `Col` / `Grid`; only `Row` accepts `flex-wrap`
- **Atomic / basic components**: `Text` / `Icon` / `Image` / `Video` / `Button` / `Input` / `Textarea` / `Divider`
- **Factory instances**: non-declaration-root use sites of `Section-*` / `Component-*` / `WebComponent-*`

`App` and `Page` in `.vx` are not factory instances; only non-declaration-root use sites of `Section-*` / `Component-*` / `WebComponent-*` in `.vx/.sc/.cp` enter the factory-instance row of the matrix.

`App` root, Page root, the `Page` node itself, and `Modal` are neither factory instances nor general layout containers nor flex/grid arrangement containers in this subsection. Their special boundaries are handled by §16 App / Page / Modal Special Boundaries and by their dedicated chapters when those land.

The `.sc/.cp` real root never enters the factory-instance row even when its tag begins with `Section-` / `Component-`; the real root is governed by §3.10 and §3.13.

#### 6.7.2 typographyOnNonTextNodeError

- **type**: `typographyOnNonTextNodeError`
- **level**: error
- **version gate**: `VL_VERSION:4.2.9+`
- **rule**: Common text metrics (`font-size`, `font-style`, `font-weight`, `line-height`, `letter-spacing`) MUST NOT be written on nodes other than `Text`, `Icon`, `Button`, `Input`, `Textarea`. Text display-flow properties (`white-space`, `text-overflow`, `word-spacing`, `word-break`, `text-indent`, `max-rows`) MUST only be written on `Text`.
- **scope**: Checks ordinary node declarations and factory-instance use sites in `.vx` / `.sc` / `.cp`.
- **message**: `<Type-Name>: typography property "<propName>" is not valid on this node.`

#### 6.7.3 textAlignScopeError

- **type**: `textAlignScopeError`
- **level**: error
- **version gate**: `VL_VERSION:4.2.9+`
- **rule**: `text-align` MUST only be written on `Text`, `Icon`, `Button`, `Input`, `Textarea`. `Icon` is allowed because icon-font content may need alignment inside the Icon's own box. `Button` is allowed because `text-align` controls the Button label horizontal alignment within the button content area.
- **scope**: Checks ordinary node declarations and factory-instance use sites in `.vx` / `.sc` / `.cp`.
- **message**: `<Type-Name>: text-align is only valid on Text/Icon/Button/Input/Textarea.`

#### 6.7.4 paddingOnAtomicError

- **type**: `paddingOnAtomicError`
- **level**: none
- **version gate**: `VL_VERSION:4.2.9+`
- **rule**: Core parser/lint MUST NOT emit `paddingOnAtomicError`. `padding`, `padding-top`, `padding-right`, `padding-bottom`, `padding-left` are standard box-model inset properties and MAY be written on all basic components (`Text`, `Icon`, `Image`, `Video`, `Button`, `Input`, `Textarea`, `Divider`) as well as layout containers.
- **scope**: Factory component instances remain covered by §6.7.12; `padding` on non-declaration-root `Section-*` / `Component-*` / `WebComponent-*` use sites is still invalid as `internalLayoutOnFactoryInstanceError`.
- **message**: none.

#### 6.7.5 gapScopeError

- **type**: `gapScopeError`
- **level**: error
- **version gate**: `VL_VERSION:4.2.9+`
- **rule**: `gap` MUST only be written on `Row`, `Col`, `Grid`, or `Button` (Button uses `gap` to express the spacing between its icon and label).
- **scope**: Checks ordinary node declarations and factory-instance use sites in `.vx` / `.sc` / `.cp`. Skips factory-instance use sites covered by §6.7.12 to avoid duplicate errors. `.sc/.cp` real roots are checked by their effective `containerType`: `containerType:row` acts as `Row`, `containerType:col` acts as `Col`, `containerType:grid` acts as `Grid`.
- **message**: `<Type-Name>: gap only applies to Row/Col/Grid (or Button child layout).`

#### 6.7.6 flexAlignScopeError

- **type**: `flexAlignScopeError`
- **level**: error
- **version gate**: `VL_VERSION:4.2.9+`
- **rule**: `align-items`, `justify-content` MUST only be written on flex/grid arrangement containers (`Row`, `Col`, `Grid`) or on `Button` for icon/text child alignment. `Block` is a general layout container but not a flex/grid arrangement container.
- **scope**: Checks ordinary node declarations and factory-instance use sites in `.vx` / `.sc` / `.cp`. Skips factory-instance use sites covered by §6.7.12 to avoid duplicate errors. `.sc/.cp` real roots are checked by their effective `containerType`: `containerType:row` acts as `Row`, `containerType:col` acts as `Col`, `containerType:grid` acts as `Grid`. `Page` / `Modal` are handled by §16.
- **message**: `<Type-Name>: "<propName>" only applies to Row/Col/Grid (or Button child layout).`

#### 6.7.6.1 flexAlignShorthandError

- **type**: `flexAlignShorthandError`
- **level**: error
- **version gate**: `VL_VERSION:4.2.9+`
- **rule**: The shorthand style props `align` and `justify` are NOT valid VL style properties. Flex/grid container alignment MUST be written with the full CSS property names `align-items` and `justify-content`. `align:` must be `align-items:`; `justify:` must be `justify-content:`.
- **why**: VL/parser/runtime do not translate `align`/`justify` to CSS. On flex containers they are silently dropped; on HTML-backed display components (Text/Input/Image/...) they are silently collected as stray HTML attributes. Either way the intended alignment never renders. This rule — together with the generic `propError` fallback below — turns that silent loss into an explicit error.
- **scope (flexAlignShorthandError)**: This dedicated error fires only on flex/grid arrangement containers where `align-items`/`justify-content` is the correct fix — `Row`, `Col`, `Grid`, `Button`, and `.sc/.cp` real roots. A root container always lays its children out as a flex/grid box, so it is covered whether its `containerType` is declared `row`/`col`/`grid` **or omitted (defaults to `col`)**.
- **scope (generic propError)**: On standard non-flex display/leaf components — `Text`, `Icon`, `Input`, `Textarea`, `Markdown`, `TableCell`, `Image` — `align`/`justify` are also rejected, but as the ordinary `propError` ("does not support property"), NOT this dedicated error. For these components the correct alignment is usually `text-align` (and `justify` has no `text-align`/flex equivalent), so emitting the `align-items` guidance would mislead. They are no longer silently swallowed.
- **not flagged**: custom / Web / extension component instances (a legal public `align`/`justify` prop is honored), SERVICE parameters named `align`/`justify`, and variable / object-field references such as `_payload.align` — none of these are standard component declaration style props.
- **message**: `"align" is not a valid VL style property; flex/grid container alignment uses "align-items". Change align:... to align-items:... on <Row-*>.` (and the parallel `justify` -> `justify-content` form). Standard non-flex display components instead receive the generic `propError` message.

#### 6.7.7 flexWrapScopeError

- **type**: `flexWrapScopeError`
- **level**: error
- **version gate**: `VL_VERSION:4.2.9+`
- **rule**: `flex-wrap` MUST only be written on `Row`. It is not valid on `Col`, `Grid`, `Block`, atomic components, or factory instances. Valid values are only `wrap` and `nowrap`; invalid values are reported by `restrictedCssValueError`.
- **scope**: Checks ordinary node declarations and factory-instance use sites in `.vx` / `.sc` / `.cp`. Skips factory-instance use sites covered by §6.7.12 to avoid duplicate errors. `.sc/.cp` real roots are checked by their effective `containerType`: `containerType:row` acts as `Row` and may use `flex-wrap`; `containerType:col` / `grid` may not.
- **message**: `<Type-Name>: flex-wrap only applies to Row.`

#### 6.7.8 overflowScopeError

- **type**: `overflowScopeError`
- **level**: error
- **version gate**: `VL_VERSION:4.2.9+`
- **rule**: `overflow` MUST only be written on general layout containers (`Row`, `Col`, `Grid`, `Block`), `Text`, or `Textarea`. `overflow` on `Text` only expresses text ellipsis / clipping semantics, not container clipping of children.
- **scope**: Checks ordinary node declarations and factory-instance use sites in `.vx` / `.sc` / `.cp`. Skips factory-instance use sites covered by §6.7.12 to avoid duplicate errors. `Page` / `Modal` are handled by §16.
- **message**: `<Type-Name>: overflow only applies to layout containers, Text ellipsis/clipping, or Textarea.`

#### 6.7.9 gridTemplateScopeError

- **type**: `gridTemplateScopeError`
- **level**: error
- **version gate**: `VL_VERSION:4.2.9+`
- **rule**: `grid-template-columns` MUST only be written on `Grid`.
- **scope**: Checks ordinary node declarations and factory-instance use sites in `.vx` / `.sc` / `.cp`.
- **message**: `<Type-Name>: grid-template-columns only applies to Grid.`

#### 6.7.10 foregroundSkinScopeError

- **type**: `foregroundSkinScopeError`
- **level**: error in `strict` lint mode only; default lint mode does not report this diagnostic.
- **version gate**: `VL_VERSION:4.2.9+`
- **rule**: `sk.fg` should be written on direct text/icon-rendering nodes (`Text`, `Icon`, `Button`, `Input`, `Textarea`). It does not propagate stably through layout containers, `Image`, `Video`, `Divider`, or factory instances; when written elsewhere it may simply have no useful effect.
- **scope**: Checks ordinary node declarations and factory-instance use sites in `.vx` / `.sc` / `.cp`.
- **message**: `<Type-Name>: sk.fg only applies to text/icon-rendering nodes (Text/Icon/Button/Input/Textarea).`

#### 6.7.11 surfaceSkinOnDividerError

- **type**: `surfaceSkinOnDividerError`
- **level**: error
- **version gate**: `VL_VERSION:4.2.9+`
- **rule**: `sk.bg`, `sk.bgImage`, `sk.shadow`, `sk.radius`, `sk.opacity` MUST NOT be written on `Divider`. Divider's visual body is a single border; it has no fillable surface.
- **scope**: Checks `Divider` declarations in `.vx` / `.sc` / `.cp`.
- **message**: `<Type-Name>: "<propName>" is not applicable on Divider; only border-related sk.* (sk.borderColor / sk.borderWidth / sk.border*) apply to Divider.`

#### 6.7.12 internalLayoutOnFactoryInstanceError

- **type**: `internalLayoutOnFactoryInstanceError`
- **level**: error
- **version gate**: `VL_VERSION:4.2.9+`
- **rule**: `padding`, `padding-top`, `padding-right`, `padding-bottom`, `padding-left`, `gap`, `align-items`, `justify-content`, `flex-wrap`, `overflow` MUST NOT be written on non-declaration-root use sites of `Section-*` / `Component-*` / `WebComponent-*`. These properties express internal child layout, internal spacing, wrapping, and internal clipping, all of which are owned by the component implementation.
- **scope**: Checks `.vx` / `.sc` / `.cp` factory-instance use sites. Does not check `.sc/.cp` real roots — real roots remain governed by §3.10 `.sc/.cp` Real Root Model.
- **message**: `Component instance "<Type-Name>" must not declare "<propName>". Internal layout is owned by the component; expose a semantic public prop or implement it inside.`
- **priority**: When a factory instance violates `padding` / `padding-*` / `gap` / `align-items` / `justify-content` / `flex-wrap` / `overflow`, this rule emits exactly one error for that line. §6.7.5 (`gapScopeError`), §6.7.6 (`flexAlignScopeError`), §6.7.7 (`flexWrapScopeError`), and §6.7.8 (`overflowScopeError`) MUST skip `Section-*` / `Component-*` / `WebComponent-*` non-declaration-root use sites so the same violation is never reported twice.

### 6.8 sk.* Runtime Type Validation (SK-004)

- **type**: runtime warning
- **level**: warning
- **rule**: `sk.*` values must resolve to a valid CSS string value, CSS number value, or `null` at runtime. This is a runtime type constraint, not a compile-time blocking lint rule.

### 6.9 sk.* Override Scope Clarification

`sk.*` is a standardized component-instance override channel. A valid `sk.*` property MUST NOT produce a warning solely because the corresponding CSS property is not listed in a component's internal StyleSpace baseline consumption set. StyleSpace constraints apply to `style` coordinates, not to valid `sk.*` overrides.

### 6.10 Pipe External Dependency

- **type**: `pipeRefExtDepError`
- **level**: error
- **rule**: PIPE function definitions must be pure — they MUST NOT reference external variables, methods, or component calls.

### 6.11 Event Parameter Not Defined

- **type**: `eventParamNotDefError`
- **level**: error
- **rule**: When referencing a module's event parameters, each parameter name must match the module's declared `outParams`. Undefined parameters produce an error.

### 6.12 Undeclared Skeleton Token Forbidden

- **type**: `legacySkeletonTokenError`
- **level**: error
- **rule**: In files whose declared version is `VL_VERSION:3.5` or higher, skeleton property values MUST NOT use undeclared token syntax such as `--spacing6`, `--spacing3`, or similar `--tokenName` forms. Use explicit CSS literal values for skeleton properties, or Theme `size` dimension where applicable.
- **example (bad)**:
  ```
  <Section-Home "root"> padding:--spacing6
  <Row-Toolbar> gap:--spacing3
  ```
- **rationale**: Undeclared token-style skeleton values frequently cause spacing and sizing regressions and must be surfaced at lint time.

### 6.13 FAILIF / GUARD Statement Validation (VL 4.3.2+ current contract)

- **type**: `failifSyntaxError`
- **level**: error
- **rule**: In the `VL_VERSION:4.3.2+` current contract, `FAILIF` is the canonical fail-fast statement and must follow the `FAILIF condition message` form. `condition` is a failure condition; when it evaluates to true, the fail-fast branch is triggered.

- **type**: `guardSyntaxError`
- **level**: error
- **rule**: `GUARD` remains a compatibility alias for `FAILIF` and must follow the `GUARD condition message` form. It has the same failure-condition semantics as `FAILIF`.

- **type**: `guardScopeError`
- **level**: error
- **rule**: `FAILIF` / `GUARD` may only appear in executable logic blocks such as events, methods, services, and transactions. They must not appear in declaration-only sections.

- **type**: `guardDefaultExitMismatchError`
- **level**: error
- **rule**: `FAILIF` / `GUARD` default-exit semantics must match the current host block:
  - `METHOD` / `SERVICE` → `RETURN`
  - `TRANSACTION` → `ROLLBACK`

- **authoring rule**: New authored VL should use `FAILIF`. `GUARD` is accepted for compatibility and must not be interpreted as a positive assertion.

### 6.14 API `send(...)` Param Location Rules (VL 4.0+)

- **type**: `apiParamLocationSyntaxError`
- **level**: error
- **rule**: In `FrontendApi / ServerApi`, when `params:(...)` uses explicit transport-location declarations, only `@path`, `@query`, and `@body` are allowed.

- **type**: `apiParamLocationOrderError`
- **level**: error
- **rule**: Once explicit param locations are used, declaration order must be `@path -> @query -> @body`.

- **type**: `apiParamLocationMixedModeError`
- **level**: error
- **rule**: Within one API component's `params:(...)`, explicit-location mode must be used consistently. Mixed declarations such as `id(INT) @path, page(INT), name(STRING) @body` are invalid.

- **type**: `apiPathParamBindingError`
- **level**: error
- **rule**: URL `{param}` placeholders and `@path` declarations must match one-to-one.

- **type**: `apiBodyParamOnReadMethodError`
- **level**: error
- **rule**: `GET` and `DELETE` API requests must not declare `@body` params.

- **type**: `apiSendArgCountMismatchError`
- **level**: error
- **rule**: `send(...)` argument count must match the declared `params:(...)` count.

- **type**: `apiCustomSendOveruseWarning`
- **level**: warning
- **rule**: If `customSend(...)` does not actually override `headers`, `url`, `timeout`, or `method`, and is only used to split normal business params into query/body, it should warn and recommend `send(...)`.

### 6.15 Local Variable Out-of-Scope Reference

- **type**: `localVarOutOfScopeError`
- **level**: error
- **rule**: If a local variable is first defined inside an inner child block and is later referenced outside that block without a prior declaration in the shared outer block, lint reports `localVarOutOfScopeError`.
- **child blocks**: `IF`, `ELSE IF`, `ELSE`, `FOR`, `WHILE`, and other executable nested block bodies.
- **detected definitions**: Local variable declarations such as `_varName(TYPE) = ...`, `_varName({}) = {}`, `_varName([]) = []`, and action result receivers such as `-> _varName`.
- **message**: `Local variable(_varName) is defined only inside an inner block and cannot be referenced here. Declare it in the outer block first, then assign inside each branch.`
- **boundary**: This rule only detects the deterministic structure error "defined only in an inner block, then referenced outside." It does not perform cross-branch definite-assignment analysis. If a local variable is declared in the shared outer block first, assigning to the same variable inside branches is valid.
- **indentation boundary**: Indentation defines scope. A line with the same indentation as a `FOR` / `IF` statement is a sibling of that block, not a child. Loop variables such as `_item0` / `_index0` are available only inside the loop body and nested child blocks under that body.
- **example (bad)**: `SERVICE GetBoard(keyword(STRING));RETURN {success:BOOL,rows:[{}]}`; `-IF keyword == ""`; `--<VirtualTable-Requirements "requirementTable">.select(null,[["_create","desc"]],[0,500],null) -> _listResult`; `-ELSE`; `--<VirtualTable-Requirements "requirementTable">.select([["searchVec","l2str",keyword,0.85]],[["searchVec",keyword]],[0,500],null) -> _listResult`; `-_rows([{}]) = (_listResult.dataArray ? _listResult.dataArray : [])`.
- **example (good)**: `SERVICE GetBoard(keyword(STRING));RETURN {success:BOOL,rows:[{}]}`; `-_listResult({}) = {}`; `-IF keyword == ""`; `--<VirtualTable-Requirements "requirementTable">.select(null,[["_create","desc"]],[0,500],null) -> _listResult`; `-ELSE`; `--<VirtualTable-Requirements "requirementTable">.select([["searchVec","l2str",keyword,0.85]],[["searchVec",keyword]],[0,500],null) -> _listResult`; `-_rows([{}]) = (_listResult.dataArray ? _listResult.dataArray : [])`.
- **example (bad loop indentation)**: `-FOR (_item0,_index0) IN rows`; `-IF mode == "day"`; `--_label = _item0.createdAt.format("YYYY-MM-DD")`. The `IF` is a sibling of `FOR`, so `_item0` is out of scope.
- **example (good loop indentation)**: `-FOR (_item0,_index0) IN rows`; `--IF mode == "day"`; `---_label = _item0.createdAt.format("YYYY-MM-DD")`; `--_bucket[_label] = _item0.count`.

### 6.16 Missing Variable Definition

- **type**: `varDefMissingError`
- **level**: error
- **rule**: Any variable reference or assignment target that requires an existing variable definition must resolve to a declared variable in the current scope. Missing variable definitions are errors because VL type inference cannot proceed safely without a declared variable shape.
- **message**: `Variable(<varName>)definition missing error`

### 6.17 Implicit Global Variable Reference

- **type**: `implicitGlobalVarWarning`
- **level**: error
- **rule**: VL is a strict typed language. A global variable must be declared before it is referenced or assigned. Referencing an undeclared global variable is an error because the compiler cannot reliably infer its type for later backend parsing.
- **message**: `Implicit global variable(<varName>) detected`

### 6.17.1 Bare Variable Statement Warning

- **type**: `bareVariableStatementWarning`
- **level**: warning
- **version gate**: Applies to files whose first-line declaration is `VL_VERSION:4.3.6` or higher.
- **rule**: In executable VL bodies, a line whose effective statement is only a variable reference (`$name`, `_name`, `$object.field`, or `_object.field`) has no executable effect and is usually an unfinished AI-generated intent. A valid executable statement should perform an explicit action such as assignment, method call, component/system method call, public event trigger, control flow, `RETURN`, `CUSTOM_RETURN`, `ROLLBACK`, or `FAILIF`.
- **scope**: Applies to frontend/backend event handler bodies, frontend/backend method bodies, service bodies, transaction bodies, and nested executable bodies under `IF`, `ELSE`, `FOR`, `WHILE`, and `FAILIF`.
- **not in scope**: Property value expressions, `IF` / `FOR` conditions, object literal values, array literal values, public prop declarations, global var declarations, derived var declarations, and method/service parameter declarations.
- **message**: `Bare variable statement "<name>" has no executable effect. If this should record child event state, use assignment such as <assignmentSuggestion>; if it should run logic, call a method such as <methodSuggestion>; if it should notify the parent, trigger a public event such as <eventSuggestion>.`
- **examples (bad)**: `-$onToolbarAction`; `--_result`; `-$formState.value`; `-_payload.id`
- **examples (good)**: `-$onToolbarAction = id`; `-_result = {success:true}`; `-HandleToolbarAction(id)`; `-@toolbarAction(id)`; `-IF $onToolbarAction != ""`; `<Text-Label "label"> value:$onToolbarAction`
- **suggestion requirement**: This warning must always include concrete repair suggestions, not only report the problem. If the bare variable name starts with `$on` and the enclosing event listener declares an `id` parameter, lint should prefer assignment-oriented suggestions. For `STRING` targets, suggest `-$onToolbarAction = id`; for `OBJECT` targets, suggest `-$onFormSubmit = {id:id}`. If the target type cannot be resolved, suggest choosing assignment, METHOD call, or public event trigger with examples derived from the variable and handler name.
- **diagnostic priority**: This rule has priority over generic unknown-statement diagnostics. A naked `$variable` / `_variable` line should be reported as `bareVariableStatementWarning` so the author sees the likely missing action and the concrete repair options.

### 6.18 Expression Method Purity and Internal Result Accessors

Expression-level method calls are only valid for public VL pure computation paths: PIPE functions, documented variable built-in immutable functions/properties, and documented pure system functions. Lint MUST NOT reject all expression method calls, because valid expressions such as `_item0.createdAt.format("YYYY-MM-DD")`, `$items.filter(_item0 => _item0.enabled)`, and `$name.trim()` are part of the VL authoring contract.

- **type**: `expressionImpureMethodCallError`
- **level**: error
- **rule**: Mutable or side-effecting methods MUST NOT appear inside expressions, conditions, property bindings, assignment right-hand sides, `RETURN` object values, `FAILIF` / `GUARD` conditions, `For.sourceArray`, `If.conditions`, or chained calls. Mutable operations may only appear as standalone executable statements inside method/event/service bodies where the receiver is writable.
- **mutable method examples**: `push`, `pop`, `shift`, `unshift`, `splice`, `sort`, `reverse`, `delete`.
- **message**: `Mutable method "<methodName>" cannot be used inside an expression. Use it as a standalone statement on a writable variable, or use an immutable function.`
- **example (bad)**: `-_result = $items.push(_item0)`
- **example (good)**: `-$items.push(_item0)`
- **example (good immutable expression)**: `-_activeItems = $items.filter(_item0 => _item0.enabled)`

- **type**: `internalResultAccessorError`
- **level**: error
- **rule**: VL source MUST NOT call internal runtime / ivxMap result accessor methods on database or VirtualTable action results. These names are implementation-layer accessors and must be exposed to VL authors as public result fields.
- **forbidden accessor names**: `getDataObjLocArr`, `getDataObjArr`, `getDataObj`, `getDataObjJsonArr`, `getDataIds`, `getLength`, `getColumns`, `getStructure`, `isSuccess`, `failReason`, `count` when used as a zero-argument method call on a result object.
- **public field replacements**:
  - `VirtualTable.select(...) -> _result`: use `_result.dataArray`, `_result.structure`, `_result.success`, `_result.message`
  - `VirtualTable.count(...) -> _result`: use `_result.count`, `_result.success`, `_result.message`
  - `VirtualTable.insert(...) -> _result`: use `_result.dataId`, `_result.dataObj`, `_result.success`, `_result.message`
  - `VirtualTable.insertMany(...) -> _result`: use `_result.dataIds`, `_result.success`, `_result.message`
  - `VirtualTable.update(...) -> _result` / `delete(...) -> _result` / `batchUpdateById(...) -> _result`: use `_result.affect`, `_result.success`, `_result.message`
- **message**: `Internal database result accessor "<methodName>()" is not valid VL source syntax. Use the public result field "<fieldName>" instead.`
- **example (bad)**: `-_rows = _selectResult.getDataObjLocArr()`
- **example (good)**: `-_rows = _selectResult.dataArray`
- **example (bad)**: `-_count = _countResult.count()`
- **example (good)**: `-_count = _countResult.count`
- **detection boundary**: This rule targets method-call syntax on result-like receiver expressions. It MUST NOT reject ordinary property reads such as `_result.dataArray.length`, nor valid immutable calls on those public fields such as `_result.dataArray.filter(_item0 => _item0.enabled)`.

### 6.19 VirtualTable Result Field Validation

- **type**: `virtualTableResultFieldError`
- **level**: error
- **rule**: A variable directly assigned by `<VirtualTable-... "...">.<method>(...) -> _result` may only read fields declared in that method's public return contract.
- **field whitelist**:
  - `select`: `success`, `message`, `dataArray`, `structure`
  - `count`: `success`, `message`, `count`
  - `insert`: `success`, `message`, `dataId`, `dataObj`
  - `insertMany`: `success`, `message`, `dataIds`
  - `update`: `success`, `message`, `affect`
  - `delete`: `success`, `message`, `affect`
  - `batchUpdateById`: `success`, `message`, `affect`
- **message**: `VirtualTable.<method> result has no field "<field>"; use "<fieldName>" instead.`
- **example (bad)**: `-<VirtualTable-Users "userTable">.select(null,null,[0,20],null) -> _result`; `-_rows([{}]) = _result.list`
- **example (good)**: `-<VirtualTable-Users "userTable">.select(null,null,[0,20],null) -> _result`; `-_rows([{}]) = _result.dataArray`
- **detected invalid reads**: `_result.list`, `_result.list.length`, `_result.list[0]`, and `FOR (_item0,_index0) IN _result.list`.
- **allowed reads**: `_result.dataArray.length`, `_result.dataArray[0]`, `_result.dataArray[0].roleCode`, `_result.success`, `_result.message`.
- **detection boundary**: This rule checks only the first field segment after the VirtualTable result variable. Once the first field is legal, downstream fields belong to table row data or built-in array/object properties and are not validated by this rule.
- **scope boundary**: This rule applies only to variables directly bound by a VirtualTable method result. It must not reject ordinary object variables such as `_other.list`. The rule is order-sensitive within each executable body: reads are checked against the latest active VirtualTable result binding at that statement, ordinary reassignment clears the binding, and bindings created inside child blocks do not flow back to following sibling statements.

---

## 7. Style Coordinate Compile Rules

Rules that validate the `style:"..."` coordinate system against the platform style-dimension specification.

`style` shorthand assumes that each static point name maps to exactly one platform dimension. Static point-name uniqueness is therefore a platform-dictionary prerequisite, not an author-facing ambiguity branch that projects are expected to resolve locally.

### 7.1 [StyleRule-2] Dimension Must Be Supported by the Component

- **type**: `styleCompileError`
- **level**: error; the unsupported `size` dimension branch of this rule is strict-only for now
- **rule**: Each dimension name in a component's `style` coordinate must belong to that component's supported static style-dimension set. For example, if a Button supports `[intent, emphasis, shape, size]`, writing `style:"danger|ghost|flat"` where `flat` maps to `surface` is a violation.
- **default-mode exception**: If the only unsupported dimension is `size`, default lint suppresses this rule so generated VL can use common size words like `sm`, `md`, and `lg` while the container/component size model is still being polished. Strict lint still reports it.
- **passive no-op exception**: If `Text` / `Icon` includes `passive` in `style`, parser treats it as a no-op compatibility point and lint MUST NOT report `StyleRule-2` for unsupported `affordance`.

### 7.2 [StyleRule-3] Dimension Point Must Exist in Platform Dictionary

- **type**: `styleCompileError`
- **level**: error
- **rule**: Each dimension point value must be a valid point in the platform's dimension dictionary. For example, `intent` allows `neutral`, `primary`, `success`, `warning`, `danger`; using `intent:"critical"` is invalid.

### 7.3 [StyleRule-6] Structural Components Forbid Style Coordinates

- **type**: `styleCompileError`
- **level**: error
- **rule**: Pure structural components (For, If, Block [DEPRECATED], etc.) that do not support static style dimensions MUST NOT have `style` coordinates. Their appearance is determined by structure, not by theme dimensions. Note: Row, Col, Grid support style dimensions (intent, emphasis, shape, surface) and are NOT subject to this rule.

### 7.4 [StyleRule-8] State Dimension Forbidden in Static Style

- **type**: `styleCompileError`
- **level**: error
- **rule**: Runtime interaction states are dynamic and MUST NOT appear in the static `style:"..."` coordinate. Interaction-state styling is handled automatically by the platform runtime-state model.

### 7.5 [StyleRule-10] Required Dimensions Missing

- **type**: `styleCompileError`
- **level**: error
- **rule**: Components with `required_dims_static` must have those dimensions present in their `style` coordinate. For example, if Divider requires `[surface]`, omitting it produces an error.

### 7.6 [StyleRule-11] style Must Be Static String Literal (STY-001)

- **type**: `styleCompileError`
- **level**: error
- **rule**: The `style` property MUST be a static string literal. Variables, ternary expressions, function/method calls, or any other non-literal style value are forbidden.
- **message**: `style must be a static string literal such as style:"danger|ghost|pill". For conditional visual switching, use a direct-child StateStyle with conditions: and a static style:"..." coordinate patch. Do not replace ordinary conditional style switching with many conditional sk.* bindings.`
- **suggestion**: Replace `style:($cond ? "a" : "b")` with a base static `style:"..."` on the component and one or more direct-child `<StateStyle-...> conditions:$cond style:"..."` coordinate patches.

---

## 8. Database Rules

### 8.1 Vector Field Missing vecSource

- **type**: `vecSourceError`
- **level**: error
- **rule**: In `.vdb` database definition files, fields of type `VECTOR` MUST include a `vecSource` property specifying the embedding source.

### 8.2 Relation Table Missing

- **type**: `relationTableMissingError`
- **level**: warning
- **rule**: Table names referenced in relation definitions must exist as defined tables in the same `.vdb` file.

---

## 9. Component Usage Strict Diagnostics

Rules that detect component usages that are currently reported only by strict lint.

### 9.1 Block Component Strict Diagnostic (BLK-001)

- **type**: `deprecatedCompWarning`
- **level**: error in `strict` lint mode only; default lint mode does not report this diagnostic.
- **rule**: `Block` uses `display:block`, so `alignItems`, `justifyContent`, and `gap` have no effect. Use `Row` or `Col` when flex layout behavior is required.

### 9.2 ButtonContainer Strict Diagnostic (BT-002)

- **type**: `deprecatedCompWarning`
- **level**: error in `strict` lint mode only; default lint mode does not report this diagnostic.
- **rule**: Prefer `Button` with UI child components (`Icon`, `Text`, `Row`, etc.) over `ButtonContainer`.

---

## 10. Button Child Component Rules

### 10.1 Button Value and UI Children Mutually Exclusive (BT-001)

- **type**: `buttonChildError`
- **level**: warning
- **rule**: When a Button declares both `value` and at least one UI child component, `value` takes priority and UI child components are ignored. UI child components include: Icon, Text, Row, Col, Grid, Image, Video, Divider, etc. Widgets (StateStyle, Animation) are NOT considered UI children and do not trigger this rule.

---

## 11. Size Dimension Rules

### 11.1 Missing Size on Interactive Component (BT-003)

- **type**: `sizeMissingWarning`
- **level**: warning
- **rule**: Button, Input, or Textarea without `size` dimension in style coordinate AND without explicit `padding` AND without explicit `font-size`. All three must be absent to trigger. If any one of size, padding, or font-size is present, no warning is produced.

### 11.2 Invalid Size Point (SZ-001)

- **type**: `sizePointError`
- **level**: error
- **rule**: The `size` dimension point in a style coordinate must be one of: `sm`, `md`, `lg`. Any other value is invalid.

### 11.3 Size on Unsupported Component (SZ-002)

- **type**: `sizeUnsupportedError`
- **level**: error in strict lint mode only
- **rule**: The `size` dimension is only supported on Button, Input, and Textarea in the current strict model. Declaring a size point on any other component type is reported only in strict lint mode; default lint currently allows it.

---

## 12. Style Governance Rules

### 12.1 Fake Divider Pattern

- **type**: `lintWarning`
- **level**: warning
- **rule**: An empty `Row` or `Col` that uses tiny `height` (`<= 3px`) together with `background-color` to simulate a divider produces a warning. Use `<Divider>` with a surface style coordinate instead.

### 12.2 StateStyle Style Coordinate Validation

- **type**: same as the matched normal `style` validation result
- **level**: same as the matched normal `style` validation severity
- **rule**: `StateStyle conditions + style:"..."` is the preferred authoring path for business/data-condition visual switching. The `style` value must obey the same static style-coordinate validation rules as component `style`: static string literal only, legal static points only, no runtime-state points, and only dimensions supported by the parent component.
- **ai guidance**: When lint rejects a non-literal component `style` value, tools should rewrite it as base component `style:"..."` plus direct-child `StateStyle conditions` coordinate patches before considering `sk.*`.

### 12.3 StateStyle Trigger Warning for Interaction Skin States

- **type**: `lintWarning`
- **level**: warning
- **rule**: `StateStyle trigger:"hover|active|focus|disabled|invalid"` produces a warning for interaction skin authoring. These interaction states should be expressed via the runtime-state model.

### 12.4 StateStyle Mixed trigger + conditions

- **type**: `lintWarning`
- **level**: warning
- **rule**: A single `StateStyle` node that mixes `trigger` and `conditions` produces a warning. Split interaction skin states into the runtime-state model and keep `StateStyle conditions` for business-condition styling.

### 12.5 StateStyle Skin Literal Warning

- **type**: `lintWarning`
- **level**: warning
- **rule**: `StateStyle conditions` that write raw skin literal properties (`color`, `background*`, `border*`, `box-shadow`, `opacity`, `text-transform`) produce a warning. Theme coordinates should carry reusable skin values; `StateStyle conditions + style:"..."` is the normal business-condition skin path. Legal `StateStyle style:"..."` coordinate patches are not part of this rule. Legal `StateStyle sk.*` remains an escape hatch for narrow values that the style space cannot express.

### 12.6 StateStyle Theme Token Error

- **type**: `stateStyleThemeTokenInvalidError`
- **level**: error
- **rule**: `StateStyle style` must be a legal static style coordinate and must not directly use Theme token syntax such as `@dimension.slot`.

### 12.7 Theme Overrides Warning (THM-OVR-001)

- **type**: `lintWarning`
- **level**: warning
- **rule**: Theme files containing a `# Overrides` section produce a warning. Instance-specific visual changes should be authored on the target component itself via `style` and/or `sk.*`.

### 12.8 Source Comment Public Interface Meta

- **type**: `publicInterfaceMetaError`
- **level**: error
- **rule**: Structured `// @meta ...` comments must obey the formal source-meta authoring contract. Public interface declarations must have complete source meta. All violations in this section are deterministic structural errors and therefore use `error`, not `warning`.
- **version gate**: The strict completeness requirements in §12.8.5, §12.8.7, and §12.8.8 apply only to files whose first-line declaration is `VL_VERSION:4.2.8` or higher. The `componentPreviewMetaUnsupportedError`, `interfaceMetaExampleShapeError`, and `interfaceRequiredFieldShapeError` rules in §12.8.10, §12.8.12, and §12.8.13 apply only to files whose first-line declaration is `VL_VERSION:4.2.9` or higher. The source-meta header-block placement and mandatory `name:"..."` locator rules in §12.8.1-§12.8.3 apply only to files whose first-line declaration is `VL_VERSION:4.2.11` or higher. Files below the corresponding version gates may omit the gated details; deterministic structure checks such as parse errors, unknown fields, duplicate fields, invalid target names, and duplicate target names still apply.

#### 12.8.1 Legal Placement

- All `@meta` comments for one source file must appear in one contiguous source-meta header block near the top of the file.
- In `.cp`, `.sc`, and `.vs`, the source-meta header block must appear after the root declaration line and before the first `#` section.
- In `.wc`, the source-meta header block must appear in the existing top header comment area before implementation code.
- `@meta` comments must not appear inside `# Frontend Public Props`, `# Frontend Public Events`, `# Frontend Public Methods`, `# Services`, tree sections, style sections, event handlers, method bodies, service bodies, or any other implementation body section.
- A `@meta` line must not contain a public declaration, `SERVICE`, `METHOD`, `EVENT`, tree component, or any other VL statement on the same physical line.

#### 12.8.2 Scope and Target Matching

- `@meta component` targets the current file root component. A component file must not declare multiple `component` meta groups for the same root target.
- `@meta prop`, `@meta event`, `@meta method`, and `@meta service` must use `name:"..."` as a locator. The locator is not runtime metadata; it identifies the public declaration described by the meta line.
- `@meta prop name:"..."` must match a public prop declaration.
- `@meta event name:"..."` must match a public event declaration.
- `@meta method name:"..."` must match a public method declaration.
- `@meta service name:"..."` must match a `SERVICE` or `PUBLIC_SERVICE` declaration.
- A missing `name`, duplicate target `name`, wrong-scope target, or locator that does not match any public declaration is an error.

#### 12.8.2.1 Public Prop Reserved Style Name Error

- **type**: `publicPropReservedNameError`
- **level**: error
- **rule**: Public prop declarations in `.cp`, `.sc`, and `.wc` must not use a name that collides with the reserved VL component-instance property namespace.
- **reserved namespace**: allowed direct-write skeleton CSS properties, restricted CSS properties, forbidden CSS skin properties, VL structure/runtime attributes such as `containerType`, `show`, the `style` coordinate attribute, legal `sk.*` skin override props, and the forbidden visibility alias `visible`.
- **matching**: Normalize both the declared public prop name and the reserved name by lowercasing and removing `-`, `_`, and `.` separators. Therefore `backgroundColor`, `background-color`, and `background_color` collide with reserved `background-color`; `borderRadius`, `border-radius`, and `border_radius` collide with reserved `border-radius`; `skBg`, `sk.bg`, and `sk_bg` collide with reserved `sk.bg`; `width` collides with reserved `width`; `style` collides with reserved `style`; `visible` is invalid because component visibility must use the standard instance `show` attribute instead of a custom public prop.
- **scope**: In `.cp` and `.sc`, lint checks the declared `$propName`. In `.wc`, lint checks the public entries listed in the header `Props:` declaration; matching `@meta prop name:"..."` entries inherit the same validation through their target prop.
- **message**: `Public prop "<name>" conflicts with reserved component-instance property "<reservedName>". Rename the public prop to a semantic component API name.`
- **examples**: `$backgroundColor(STRING) = ""` is invalid; `$skBg(STRING) = ""` is invalid; `$width(STRING) = "100%"` is invalid; `$visible(BOOL) = true` is invalid; `$chartPalette([STRING]) = []` is valid; `$accentColor(STRING) = "#2563EB"` is valid.

#### 12.8.3 Header Block Integrity

- The source-meta header block may contain multiple `@meta` lines, but no VL executable statement or public declaration.
- Ordinary comments may appear before or after the source-meta header block, but must not split one target's multi-line metadata group.
- `@meta` binds to public declarations only through `name:"..."` locators. Lint must resolve declaration-level meta through `name:"..."`.
- An `@meta` line outside the source-meta header block is an error.
- An `@meta` line with no resolvable target declaration is an error.

#### 12.8.4 Allowed Fields Only

- `component` only allows `summary`, `keywords`, `useCases`, `notFor`, `dependsOn`.
- `prop` only allows `description`, `enum`, `enumLabels`, `control`, `nullable`, `required`, `example`.
- `event` only allows `description` and `params`.
- `method` only allows `description`, `params`, `returns`, and `effects`.
- `service` only allows `description`, `params`, `returns`, `effects`, and `auth`.
- Unknown fields are errors.
- Repeating the same field on the same target is an error, even if the repeated value is identical.

#### 12.8.5 Required Public Interface Meta

- Every public prop in `.cp/.sc` must have matching name-anchored `@meta prop`.
- Every public event in `.cp/.sc` must have matching name-anchored `@meta event`.
- Every public method in `.cp/.sc` must have matching name-anchored `@meta method`.
- Every public prop, event, and method declared in `.wc` header comments must have a matching name-anchored `@meta prop`, `@meta event`, or `@meta method`.
- Every `SERVICE` and `PUBLIC_SERVICE` in `.vs` must have matching name-anchored `@meta service`.
- Public prop meta must include non-empty `description`.
- Public event meta must include non-empty `description`.
- Public method meta must include non-empty `description`.
- Public service meta must include non-empty `description`.
- Parameter-level meta must include non-empty `description`.

#### 12.8.6 Enum and Control Rules

- `enum` must be a non-empty array.
- Duplicate values inside `enum` are errors.
- `enumLabels` must be an object.
- `enumLabels` must cover every `enum` value and must not contain keys outside `enum`.
- `control` is optional metadata. Omitting `control` is valid; consumer tools may infer default editors from declared type, `enum`, enum count, and runtime shape.
- Current standardized `control` values are only `textarea`, `json`, and `color`.
- Any other `control` value is an error.
- `nullable`, when present, must be a boolean.
- These same rules also apply inside parameter-level meta objects under `params`.

#### 12.8.7 Params Rules

- `event.params` and `method.params` must be objects keyed by declared parameter name.
- `service.params` must be an object keyed by declared service parameter name.
- A `params` entry that references an undeclared parameter name is an error.
- If a public event, method, service, or public service declares parameters, `params` must cover every declared parameter.
- Each `params.<paramName>` value must itself be an object.
- Parameter-level fields continue to follow the corresponding property-level validation rules where applicable.

#### 12.8.8 Returns Rules

- `method.returns` and `service.returns` must be objects.
- If a public method, service, or public service returns a non-empty object shape, `returns` must cover every declared return field.
- A `returns` entry that references an undeclared object return field is an error.
- Each object-return `returns.<fieldName>` value must itself be an object with non-empty `description`.
- If a public method, service, or public service returns a scalar value, `returns` must include non-empty top-level `description`.
- Empty object returns may omit `returns`.

#### 12.8.9 Effects and Auth Rules

- `effects`, when present, must be a non-empty array of non-empty strings.
- `auth`, when present, must be an object.
- Missing `effects` and missing `auth` are not errors by themselves.

#### 12.8.10 Component Preview Meta Unsupported Error

- **type**: `componentPreviewMetaUnsupportedError`
- **level**: error
- **version gate**: `VL_VERSION:4.2.9+`
- **rule**: Source `@meta component` MUST NOT contain the top-level field `preview`. Component preview frame size is owned by the shell / platform `previewFrameJson`; preview input examples belong to public interface metadata `example` fields.
- **scope**: Only checks `@meta component preview` top-level fields in `.cp/.sc/.wc` source comments. Does not check the preview shell's external configuration tables, and does not check ordinary component instance `width` / `height` values written in business projects.
- **message**: `@meta component preview is not a standard public metadata field in VL_VERSION:4.2.9+. Put preview frame in previewFrameJson and put sample input values on interface metadata example fields.`

#### 12.8.11 dependsOn Rules

- `component.dependsOn` must be an array of non-empty strings.
- Duplicate `dependsOn` items are errors.

#### 12.8.12 Interface Meta Example Shape Error

- **type**: `interfaceMetaExampleShapeError`
- **level**: error
- **version gate**: `VL_VERSION:4.2.9+`
- **rule**: Public interface metadata `example`, when present on prop metadata or param metadata, MUST be parseable as a metadata value and MUST match the declared interface type when the type can be statically checked. Primitive mismatches (`string` vs number/boolean, number vs string/boolean, boolean vs string/number), array/object literal mismatches, and invalid metadata value syntax are errors.
- **scope**: Checks `example` on public prop metadata, method param metadata, event param metadata, and service param metadata. Does not check component-internal local variables, non-public helper parameters, or runtime business data.
- **message**: `Interface metadata example for "<name>" must be a parseable sample value compatible with the declared public interface type.`

#### 12.8.13 Interface Required Field Shape Error

- **type**: `interfaceRequiredFieldShapeError`
- **level**: error
- **version gate**: `VL_VERSION:4.2.9+`
- **rule**: Public prop metadata and public param metadata MUST declare requiredness with `required:true` or `required:false`. `required` must be a boolean literal. Other spellings such as `optional`, `mandatory`, `isRequired`, or string values like `"true"` are not accepted as standard requiredness metadata.
- **scope**: Checks public prop metadata, method param metadata, event param metadata, and service param metadata. Does not change the type or default-value semantics of the underlying interface declaration itself.
- **message**: `Public interface metadata must declare boolean required:true or required:false for requiredness.`

---

## 13. Scroll Container Rules (`VL 4.2+`)

Rules that validate scroll container sizing stability and scroll-axis layout conflicts.

### 13.1 Scroll Container Missing Stable Size Carrier

- **type**: `overflowSizeCarrierError`
- **level**: error in `strict` lint mode only; default lint mode does not report this diagnostic.
- **rule**: When a `Col` or `Row` declares `overflow:"auto"` or `overflow:"scroll"`, the node should have a stable size carrier on the scroll axis. If it has neither an explicit size, nor a resolvable `flex:"1"` chain to a stable ancestor, nor a resolvable percentage size backed by an ancestor with an explicit size, strict lint reports an error because scroll behavior may be lost or unstable.

Acceptable stable size carriers include:

1. Explicit size (e.g. `height:"400px"`, `height:"100vh"`, `width:"320px"`)
2. Explicit scroll cap on the scroll axis (e.g. `max-height:"160px"` for a vertical `Col` scroll list, `max-width:"320px"` for a horizontal `Row` scroll list)
3. `flex:"1"` where the parent container already provides a stable main-axis carrier
4. `flex:"1"` with `min-height:"0"` / `min-width:"0"` under a `.sc/.cp` real root whose `containerType` provides the corresponding main-axis container (`containerType:col` for vertical, `containerType:row` for horizontal)
5. Resolvable percentage size (e.g. `height:"100%"`) where the parent node has an explicit size

- **note**: A percentage size whose parent lacks a resolvable explicit size is NOT a stable carrier and must still report an error.

### 13.2 Scroll List Item Same-Axis Shrink Conflict

- **type**: `scrollListItemAxisShrinkConflictError`
- **level**: error
- **rule**: When a scroll container (`Col` or `Row` with `overflow:"auto"` or `overflow:"scroll"`) contains a `For` loop that renders repeated list items, the list item root node must not declare `flex:"1"` on the same axis as the scroll direction. Scroll intent is to allow real overflow on that axis; same-axis `flex:"1"` participates in remaining-space distribution and compression, directly conflicting with the scroll purpose.

At minimum, the following scenarios must be detected:

1. Parent `Col` with `overflow:"auto"` or `overflow:"scroll"` — list item root declares `flex:"1"` (vertical axis conflict)
2. Parent `Row` with `overflow:"auto"` or `overflow:"scroll"` — list item root declares `flex:"1"` (horizontal axis conflict)

- **note**: The recommended fix is to let the scroll container handle overflow, remove same-axis `flex:"1"` from list items, and use `min-height` / `min-width`, explicit sizes, or natural non-compressible content to maintain readable item dimensions.

---

## 14. Input Writeback Rules (`VL 4.2+`)

Editable input components use controlled-value semantics. Lint MUST NOT report an error solely because an editable component binds `value:$var` and explicitly writes back to `$var` through `@input`, `@change`, `@blur`, or `@confirm`.

This same-variable explicit writeback is the standard controlled-input pattern. Lint may still validate ordinary structural issues such as invalid event names, invalid event parameters, assignment to a non-writable target, assignment to component instance properties, or expression syntax errors.

---

## 15. UserStore & Auth Tables Rules (`VL 4.2+`)

Rules that validate `UserStore` component placement, configuration, uniqueness, and the required `Table-AuthUsers` / `Table-AuthUserIdentities` resource declarations. These rules operate at project-level lint scope because several constraints are inherently cross-file.

### 15.1 UserStore Must Be in Backend Tree

- **type**: `userStoreBackendTreeOnlyError`
- **level**: error
- **rule**: `UserStore` is a backend component and may only be declared in the `# Backend Tree` section of a `.vs` file. Declaring `UserStore` in `.vx`, `.sc`, `.cp`, or any non-Backend-Tree section of `.vs` is an error.

### 15.2 UserStore Must Declare sourceTable and identitiesTable

- **type**: `userStoreSourceTableMissingError`
- **level**: error
- **rule**: A `UserStore` component declaration must explicitly include the `sourceTable` property. Omitting `sourceTable` is an error.
- **type**: `userStoreIdentitiesTableMissingError`
- **level**: error
- **rule**: A `UserStore` component declaration must explicitly include the `identitiesTable` property. Omitting `identitiesTable` is an error.

### 15.3 UserStore Table Bindings Must Be Fixed Auth Tables

- **type**: `userStoreSourceTableInvalidError`
- **level**: error
- **rule**: In `VL_VERSION:4.2+`, `UserStore.sourceTable` must be set to `AuthUsers`. Binding to any other table name (ordinary business tables, other system resource names, or undeclared resource names) is an error.
- **type**: `userStoreIdentitiesTableInvalidError`
- **level**: error
- **rule**: In `VL_VERSION:4.2+`, `UserStore.identitiesTable` must be set to `AuthUserIdentities`. Binding to any other table name is an error.

### 15.4 UserStore Must Be Unique Per Project

- **type**: `userStoreDuplicateError`
- **level**: error
- **rule**: A project may declare at most one `UserStore`. If a second `UserStore` appears in the same file or across files, lint reports an error.

### 15.5 UserStore Requires Table-AuthUsers

- **type**: `authUsersTableMissingError`
- **level**: error
- **rule**: When a project declares a `UserStore`, the project's `.vdb` file must also contain a `Table-AuthUsers` resource declaration. If `Table-AuthUsers` is missing, lint reports an error.

### 15.6 UserStore Requires Table-AuthUserIdentities

- **type**: `authUserIdentitiesTableMissingError`
- **level**: error
- **rule**: When a project declares a `UserStore`, the project's `.vdb` file must also contain a `Table-AuthUserIdentities` resource declaration. If `Table-AuthUserIdentities` is missing, lint reports an error.

### 15.7 Table-AuthUsers Must Declare Required User Principal Fields

- **type**: `authUsersFieldDeclarationMissingError`
- **level**: error
- **rule**: When a project declares a `UserStore`, `Table-AuthUsers` must declare the required user principal fields defined by the VL syntax specification with matching field types. Omitting all `Field-*` declarations, omitting any required user principal field, or declaring a required field with an incompatible type is an error.

Required fields:

- `nickname(STRING)`
- `display_name(STRING)`
- `avatar(STRING)`
- `status(STRING)`
- `primary_email(STRING)`
- `primary_phone(STRING)`
- `last_login_at(TIMESTAMP)`
- `extra_json(JSON)`

### 15.8 Table-AuthUserIdentities Must Declare Required Identity Fields

- **type**: `authUserIdentitiesFieldDeclarationMissingError`
- **level**: error
- **rule**: When a project declares a `UserStore`, `Table-AuthUserIdentities` must declare the required identity credential fields defined by the VL syntax specification with matching field types. Omitting all `Field-*` declarations, omitting any required identity credential field, or declaring a required field with an incompatible type is an error.

Required fields:

- `user_id(INT)`
- `identity_type(STRING)`
- `identifier(STRING)`
- `identifier_norm(STRING)`
- `credential_hash(STRING)`
- `provider(STRING)`
- `provider_user_id(STRING)`
- `provider_union_id(STRING)`
- `verified_at(TIMESTAMP)`
- `is_primary(BOOL)`
- `extra_json(JSON)`

---

## 16. BackendSecurityToolkit Rules (`VL 4.3.1+`)

Rules that validate `BackendSecurityToolkit` component placement. The component is a backend functional component and has no frontend declaration form.

### 16.1 BackendSecurityToolkit Must Be in Backend Tree

- **type**: `backendSecurityToolkitBackendTreeOnlyError`
- **level**: error
- **version gate**: `VL_VERSION:4.3.1+`
- **rule**: `BackendSecurityToolkit` may only be declared in the `# Backend Tree` section of a `.vs` file. Declaring `BackendSecurityToolkit` in `.vx`, `.sc`, `.cp`, `.vdb`, `.vth`, or any non-Backend-Tree section of `.vs` is an error.

---

## 17. App / Page / Modal Special Boundaries (`VL 4.2.9+`)

Rules that diagnose direct writes on `App`, `Page`, and `Modal` boundaries while their dedicated closed property surface is still pending.

### 17.1 App Page Modal Special Boundary Pending Warning

- **type**: `appPageModalSpecialBoundaryPendingWarning`
- **level**: warning
- **version gate**: `VL_VERSION:4.2.9+`
- **rule**: Direct skeleton CSS or `sk.*` declarations on `App` root, `Page` root, standalone `Page` nodes, or `Modal` nodes SHOULD be reported as a non-blocking warning unless the property is explicitly allowed by the App / Page / Modal special-boundary allow-list. `Modal` `width` and `height` are explicitly allowed because they map to the inner panel size and MUST NOT trigger this warning.
- **scope**: Only checks `App-*`, `Page-*`, and `Modal-*` nodes in `.vx/.sc/.cp` source. `Section-*` / `Component-*` / `WebComponent-*` factory instances continue to be handled by §6.7 and §3.13 and do not enter this rule.
- **message**: `<Type-Name> is a special App/Page/Modal boundary. Its skeleton CSS and sk.* surface is pending a dedicated chapter; do not treat it as a normal layout container.`

---
