This commit completes the migration started in the previous commit, updating all remaining files: - Lexer: Changed token from Extends to Modifies - Parser: Updated lalrpop grammar rules and AST field names - AST: Renamed Schedule.extends field to modifies - Grammar: Updated tree-sitter grammar.js - Tree-sitter: Regenerated parser.c and node-types.json - Examples: Updated baker-family work schedules - Tests: Updated schedule composition tests and corpus - Docs: Updated all reference documentation and tutorials - Validation: Updated error messages and validation logic - Package: Bumped version to 0.3.1 in all package manifests All 554 tests pass.
378 lines
12 KiB
Markdown
378 lines
12 KiB
Markdown
# Validation Rules
|
|
|
|
The Storybook compiler performs multi-layered validation to catch errors before runtime. This chapter documents all validation rules, organized by declaration type, along with the error messages you can expect and how to fix them.
|
|
|
|
## Validation Layers
|
|
|
|
Storybook validation happens in four stages:
|
|
|
|
1. **Lexical**: Tokenization of raw text (invalid characters, malformed literals)
|
|
2. **Syntactic**: Grammar structure (missing braces, wrong keyword order)
|
|
3. **Semantic**: Cross-reference resolution, type checking, field merging
|
|
4. **Domain**: Narrative-specific constraints (bond ranges, schedule overlaps)
|
|
|
|
Errors at earlier stages prevent later stages from running.
|
|
|
|
## Character Validation
|
|
|
|
### Required Rules
|
|
|
|
| Rule | Description | Severity |
|
|
|------|-------------|----------|
|
|
| Unique name | Character names must be unique within their module | Error |
|
|
| Species exists | If `: Species` is used, the species must be defined | Error |
|
|
| Templates exist | All templates in `from` clause must be defined | Error |
|
|
| No circular inheritance | Template chains cannot form cycles | Error |
|
|
| Field type consistency | Field values must match expected types | Error |
|
|
| Behavior trees exist | All `uses behaviors` references must resolve | Error |
|
|
| Schedules exist | All `uses schedule` references must resolve | Error |
|
|
| Prose tag uniqueness | Each prose tag can appear at most once per character | Error |
|
|
|
|
### Examples
|
|
|
|
**Species not found:**
|
|
```storybook
|
|
character Martha: Hobbit { // Error: species 'Hobbit' not defined
|
|
age: 34
|
|
}
|
|
```
|
|
|
|
**Fix:** Define the species or correct the reference:
|
|
```storybook
|
|
species Hobbit {
|
|
lifespan: 130
|
|
}
|
|
|
|
character Martha: Hobbit {
|
|
age: 34
|
|
}
|
|
```
|
|
|
|
**Duplicate character name:**
|
|
```storybook
|
|
character Martha { age: 34 }
|
|
character Martha { age: 36 } // Error: duplicate character name 'Martha'
|
|
```
|
|
|
|
## Template Validation
|
|
|
|
| Rule | Description | Severity |
|
|
|------|-------------|----------|
|
|
| Unique name | Template names must be unique within their module | Error |
|
|
| Includes exist | All included templates must be defined | Error |
|
|
| No circular includes | Include chains cannot form cycles | Error |
|
|
| Range validity | Range bounds must satisfy min <= max | Error |
|
|
| Range type match | Both bounds of a range must be the same type | Error |
|
|
| Strict enforcement | Characters using strict templates cannot add extra fields | Error |
|
|
| Resource links valid | Behavior/schedule references must resolve | Error |
|
|
|
|
### Examples
|
|
|
|
**Invalid range:**
|
|
```storybook
|
|
template BadRange {
|
|
age: 65..18 // Error: range min (65) must be <= max (18)
|
|
}
|
|
```
|
|
|
|
**Strict template violation:**
|
|
```storybook
|
|
template Rigid strict {
|
|
required_stat: 10
|
|
}
|
|
|
|
character Constrained from Rigid {
|
|
required_stat: 15
|
|
extra_field: 42 // Error: field 'extra_field' not allowed by strict template 'Rigid'
|
|
}
|
|
```
|
|
|
|
## Behavior Tree Validation
|
|
|
|
| Rule | Description | Severity |
|
|
|------|-------------|----------|
|
|
| At least one node | Behavior body must contain at least one node | Error |
|
|
| Composite children | `choose` and `then` require at least one child | Error |
|
|
| Decorator child | Decorators require exactly one child | Error |
|
|
| Subtree exists | `include` must reference a defined behavior | Error |
|
|
| Expression validity | Condition expressions must be well-formed | Error |
|
|
| Duration format | Decorator durations must be valid (e.g., `5s`, `10m`) | Error |
|
|
| Repeat count valid | `repeat N` requires N >= 0 | Error |
|
|
| Repeat range valid | `repeat min..max` requires 0 <= min <= max | Error |
|
|
| Retry count valid | `retry N` requires N >= 1 | Error |
|
|
|
|
### Examples
|
|
|
|
**Empty composite:**
|
|
```storybook
|
|
behavior Empty {
|
|
choose options {
|
|
// Error: 'choose' requires at least one child
|
|
}
|
|
}
|
|
```
|
|
|
|
**Invalid subtree reference:**
|
|
```storybook
|
|
behavior Main {
|
|
include NonExistentBehavior // Error: behavior 'NonExistentBehavior' not defined
|
|
}
|
|
```
|
|
|
|
## Life Arc Validation
|
|
|
|
| Rule | Description | Severity |
|
|
|------|-------------|----------|
|
|
| At least one state | Life arc must contain at least one state | Error |
|
|
| Unique state names | State names must be unique within the life arc | Error |
|
|
| Valid transitions | Transition targets must reference defined states | Error |
|
|
| Expression validity | Transition conditions must be well-formed | Error |
|
|
| Field targets valid | On-enter field references must resolve | Error |
|
|
| Reachable states | All states should be reachable from initial state | Warning |
|
|
|
|
### Examples
|
|
|
|
**Invalid transition target:**
|
|
```storybook
|
|
life_arc Broken {
|
|
state active {
|
|
on timer_expired -> nonexistent // Error: state 'nonexistent' not defined
|
|
}
|
|
}
|
|
```
|
|
|
|
**Unreachable state (warning):**
|
|
```storybook
|
|
life_arc HasOrphan {
|
|
state start {
|
|
on ready -> middle
|
|
}
|
|
|
|
state middle {
|
|
on done -> end
|
|
}
|
|
|
|
state orphan {} // Warning: state 'orphan' is not reachable
|
|
|
|
state end {}
|
|
}
|
|
```
|
|
|
|
## Schedule Validation
|
|
|
|
| Rule | Description | Severity |
|
|
|------|-------------|----------|
|
|
| Time format | Times must be valid HH:MM or HH:MM:SS | Error |
|
|
| Modifies exists | Base schedule must be defined | Error |
|
|
| No circular modifies | Schedule chains cannot form cycles | Error |
|
|
| Named blocks unique | Block names must be unique within a schedule | Error |
|
|
| Action references valid | Action references must resolve to defined behaviors | Error |
|
|
| Constraint values valid | Temporal constraint values must reference defined enums | Error |
|
|
| Recurrence names unique | Recurrence names must be unique within a schedule | Error |
|
|
|
|
### Examples
|
|
|
|
**Invalid time format:**
|
|
```storybook
|
|
schedule Bad {
|
|
block work {
|
|
25:00 - 17:00 // Error: invalid hour '25'
|
|
action: work
|
|
}
|
|
}
|
|
```
|
|
|
|
**Circular modifies:**
|
|
```storybook
|
|
schedule A modifies B { }
|
|
schedule B modifies A { } // Error: circular schedule extension detected
|
|
```
|
|
|
|
## Relationship Validation
|
|
|
|
| Rule | Description | Severity |
|
|
|------|-------------|----------|
|
|
| At least two participants | Relationships require >= 2 participants | Error |
|
|
| Participants exist | All participant names must reference defined entities | Error |
|
|
| Unique participants | Each participant appears at most once | Error |
|
|
| Field type consistency | Fields must have valid value types | Error |
|
|
|
|
### Examples
|
|
|
|
**Too few participants:**
|
|
```storybook
|
|
relationship Lonely {
|
|
Martha // Error: relationship requires at least 2 participants
|
|
bond: 0.5
|
|
}
|
|
```
|
|
|
|
## Species Validation
|
|
|
|
| Rule | Description | Severity |
|
|
|------|-------------|----------|
|
|
| Unique name | Species names must be unique within their module | Error |
|
|
| No circular includes | Include chains cannot form cycles | Error |
|
|
| Includes exist | All included species must be defined | Error |
|
|
| Field type consistency | Fields must have valid values | Error |
|
|
| Prose tag uniqueness | Each prose tag can appear at most once | Error |
|
|
|
|
## Enum Validation
|
|
|
|
| Rule | Description | Severity |
|
|
|------|-------------|----------|
|
|
| Unique enum name | Enum names must be unique within their module | Error |
|
|
| Unique variants | Variant names must be unique within the enum | Error |
|
|
| Non-empty | Enums must have at least one variant | Error |
|
|
| Valid identifiers | Variants must follow identifier rules | Error |
|
|
|
|
### Examples
|
|
|
|
**Duplicate variant:**
|
|
```storybook
|
|
enum Size {
|
|
tiny,
|
|
small,
|
|
small, // Error: duplicate variant 'small' in enum 'Size'
|
|
large
|
|
}
|
|
```
|
|
|
|
## Institution and Location Validation
|
|
|
|
| Rule | Description | Severity |
|
|
|------|-------------|----------|
|
|
| Unique name | Names must be unique within their module | Error |
|
|
| Resource links valid | Behavior/schedule references must resolve | Error |
|
|
| Field type consistency | Fields must have valid values | Error |
|
|
|
|
## Expression Validation
|
|
|
|
Expressions are validated wherever they appear (life arc transitions, behavior tree conditions, if decorators).
|
|
|
|
| Rule | Description | Severity |
|
|
|------|-------------|----------|
|
|
| Type consistency | Both sides of comparison must have compatible types | Error |
|
|
| Boolean context | Logical operators require boolean operands | Error |
|
|
| Field existence | Referenced fields must exist on the entity | Error |
|
|
| Collection validity | Quantifiers require collection-typed expressions | Error |
|
|
| Variable scope | Quantifier variables only valid within their predicate | Error |
|
|
| Enum validity | Enum comparisons must reference defined values | Error |
|
|
|
|
### Examples
|
|
|
|
**Type mismatch:**
|
|
```storybook
|
|
life_arc TypeError {
|
|
state checking {
|
|
on count == "five" -> done // Error: cannot compare int with string
|
|
}
|
|
|
|
state done {}
|
|
}
|
|
```
|
|
|
|
## Use Statement Validation
|
|
|
|
| Rule | Description | Severity |
|
|
|------|-------------|----------|
|
|
| Path exists | Imported paths must reference defined modules/items | Error |
|
|
| No circular imports | Modules cannot form circular dependency chains | Error |
|
|
| Valid identifiers | All path segments must be valid identifiers | Error |
|
|
| Grouped import validity | All items in `{}` must exist in the target module | Error |
|
|
|
|
### Examples
|
|
|
|
**Missing import:**
|
|
```storybook
|
|
use schema::nonexistent::Thing; // Error: module 'schema::nonexistent' not found
|
|
```
|
|
|
|
## Cross-File Validation
|
|
|
|
When resolving across multiple `.sb` files, the compiler performs additional checks:
|
|
|
|
| Rule | Description | Severity |
|
|
|------|-------------|----------|
|
|
| All references resolve | Cross-file references must find their targets | Error |
|
|
| No naming conflicts | Declarations must not collide across files in the same module | Error |
|
|
| Import visibility | Only public declarations can be imported | Error |
|
|
|
|
## Common Error Patterns
|
|
|
|
### Missing Definitions
|
|
|
|
The most common error is referencing something that does not exist:
|
|
|
|
```storybook
|
|
character Martha: Human from Baker {
|
|
specialty: sourdough
|
|
}
|
|
```
|
|
|
|
If `Human`, `Baker`, or the `sourdough` enum variant are not defined or imported, the compiler will report an error. Fix by adding the appropriate `use` statements:
|
|
|
|
```storybook
|
|
use schema::core_enums::{SkillLevel, Specialty};
|
|
use schema::templates::Baker;
|
|
use schema::beings::Human;
|
|
|
|
character Martha: Human from Baker {
|
|
specialty: sourdough
|
|
}
|
|
```
|
|
|
|
### Circular Dependencies
|
|
|
|
Circular references are rejected at every level:
|
|
|
|
- Templates including each other
|
|
- Species including each other
|
|
- Schedules extending each other
|
|
- Modules importing each other
|
|
|
|
Break cycles by restructuring into a hierarchy or extracting shared parts into a common module.
|
|
|
|
### Type Mismatches
|
|
|
|
Storybook has no implicit type coercion. Ensure values match their expected types:
|
|
|
|
```storybook
|
|
// Wrong:
|
|
character Bad {
|
|
age: "twenty" // Error: expected int, got string
|
|
is_ready: 1 // Error: expected bool, got int
|
|
}
|
|
|
|
// Correct:
|
|
character Good {
|
|
age: 20
|
|
is_ready: true
|
|
}
|
|
```
|
|
|
|
## Validation Summary
|
|
|
|
| Declaration | Key Constraints |
|
|
|-------------|----------------|
|
|
| Character | Unique name, valid species/templates, no circular inheritance |
|
|
| Template | Unique name, valid includes, valid ranges, strict enforcement |
|
|
| Behavior | Non-empty, valid composites, valid decorators, valid subtrees |
|
|
| Life Arc | Non-empty, unique states, valid transitions, reachable states |
|
|
| Schedule | Valid times, valid modifies chain, unique block names |
|
|
| Relationship | >= 2 participants, valid references |
|
|
| Species | Unique name, valid includes, no cycles |
|
|
| Enum | Unique name, unique variants, non-empty |
|
|
| Institution | Unique name, valid resource links |
|
|
| Location | Unique name, valid field types |
|
|
| Use | Valid paths, no circular imports |
|
|
|
|
## Cross-References
|
|
|
|
- [Characters](./10-characters.md) - Character-specific validation
|
|
- [Behavior Trees](./11-behavior-trees.md) - Behavior validation
|
|
- [Life Arcs](./13-life-arcs.md) - Life arc validation
|
|
- [Schedules](./14-schedules.md) - Schedule validation
|
|
- [Expression Language](./17-expressions.md) - Expression validation
|
|
- [Value Types](./18-value-types.md) - Type system constraints
|