# Resource Linking System Design
**Author:** Resource Linking Architect
**Date:** 2026-02-12
**Status:** Ready for Checkpoint 1 Review
**Version:** 0.2
**Keyword Decision:** `uses` (approved by Sienna)

---

## Executive Summary

This document proposes a unified `uses` keyword system for associating behaviors and schedules with characters and institutions in the Storybook DSL. The design enables:

- Characters using one or more behaviors
- Characters using one or more schedules
- Institutions using behaviors (for institutional operations)
- Institutions using schedules (operating hours, seasonal variations)
- Conditional/contextual selection of linked resources
- Priority-based behavior selection at runtime

---

## 1. Design Goals

### Primary Goals
1. **Unified Syntax**: Single `uses` keyword for both behaviors and schedules
2. **Simple Default Case**: Most common use case should be simple one-liner
3. **Powerful When Needed**: Support complex multi-link scenarios with conditions
4. **Clear Semantics**: Unambiguous about which behavior/schedule applies when
5. **Backward Compatible**: Existing .sb files continue to parse and work

### Non-Goals
1. **Not for Relationships**: Relationship linking remains separate (already exists)
2. **Not Inline Definitions**: Can only link to named behaviors/schedules, not define inline
3. **Not Dynamic Composition**: Links are static at author-time, selection is runtime

---

## 2. Syntax Design

### 2.1 Simple Single Link

The most common case: a character has one primary behavior and one schedule.

```storybook
character Martha: Human {
    age: 34

    uses behavior: WorkAtBakery
    uses schedule: BakerSchedule
}
```

**AST Representation:**
```rust
// Add to Character struct in ast.rs
pub struct Character {
    pub name: String,
    pub species: Option<String>,
    pub fields: Vec<Field>,
    pub template: Option<Vec<String>>,
    pub behavior_links: Vec<BehaviorLink>,  // NEW
    pub schedule_links: Vec<ScheduleLink>,  // NEW
    pub span: Span,
}
```

### 2.2 Multiple Links with Priorities

Characters may have multiple behaviors that activate based on context:

```storybook
character Alice: Human {
    age: 7

    uses behaviors: [
        { tree: HandleUrgentNeeds, priority: critical }
        { tree: CuriousExplorer, priority: normal }
        { tree: Idle, priority: low }
    ]
}
```

**Semantics:**
- Higher priority behaviors preempt lower priority ones
- Within same priority, declaration order determines evaluation
- `critical` > `high` > `normal` > `low`

### 2.3 Conditional Links

Links can have `when` conditions for context-based selection:

```storybook
character Alice: Human {
    uses behaviors: [
        { tree: HandleUrgentNeeds, priority: critical }
        { tree: GiantBehavior, when: current_size == huge }
        { tree: TinyBehavior, when: current_size == tiny }
        { tree: NormalExploring, default: true }
    ]

    uses schedules: [
        { schedule: SleepSchedule, when: emotional_state == exhausted }
        { schedule: AdventureSchedule, default: true }
    ]
}
```

**Condition Evaluation:**
- Conditions use the existing expression language (see design.md §5)
- `default: true` means "use this if no condition matches"
- Only one `default` allowed per link type
- Runtime evaluates conditions top-to-bottom

### 2.4 Institution Links

Institutions can link to behaviors and schedules:

```storybook
institution Bakery {
    type: commercial

    uses behavior: BakeryOperations
    uses schedule: BakeryHours
}
```

**Multiple Schedules for Seasons:**
```storybook
institution Bakery {
    uses schedules: [
        { schedule: SummerHours, when: season == summer }
        { schedule: WinterHours, when: season == winter }
        { schedule: StandardHours, default: true }
    ]
}
```

### 2.5 Template Inheritance

Templates can define default links that characters inherit:

```storybook
template WonderlandCreature {
    uses behavior: WonderlandBehavior
    uses schedule: WonderlandSchedule
}

character CheshireCat: Cat from WonderlandCreature {
    // Inherits WonderlandBehavior and WonderlandSchedule
    // Can override:
    uses behavior: CheshireBehavior  // Replaces WonderlandBehavior
}
```

**Override Semantics:**
- If character defines `uses behavior:`, it replaces template's behavior link entirely
- If character defines `uses behaviors: [...]`, it replaces template's behavior links
- No merging—it's full replacement (consistent with current template override system)

---

## 3. AST Design

### 3.1 New AST Types

```rust
// In src/syntax/ast.rs

/// A link to a behavior tree
#[derive(Debug, Clone, PartialEq)]
pub struct BehaviorLink {
    pub tree: Vec<String>,        // Qualified path to behavior
    pub priority: Option<String>, // critical, high, normal, low
    pub condition: Option<Expr>,  // when clause
    pub is_default: bool,         // default: true
    pub span: Span,
}

/// A link to a schedule
#[derive(Debug, Clone, PartialEq)]
pub struct ScheduleLink {
    pub schedule: Vec<String>,    // Qualified path to schedule
    pub condition: Option<Expr>,  // when clause
    pub is_default: bool,         // default: true
    pub span: Span,
}

// Priority levels (could be enum or validated string)
pub enum Priority {
    Critical,
    High,
    Normal,
    Low,
}
```

### 3.2 Modified AST Structs

```rust
// Character gains link fields
pub struct Character {
    pub name: String,
    pub species: Option<String>,
    pub fields: Vec<Field>,
    pub template: Option<Vec<String>>,
    pub behavior_links: Vec<BehaviorLink>,  // NEW
    pub schedule_links: Vec<ScheduleLink>,  // NEW
    pub span: Span,
}

// Institution gains link fields
pub struct Institution {
    pub name: String,
    pub fields: Vec<Field>,
    pub behavior_links: Vec<BehaviorLink>,  // NEW
    pub schedule_links: Vec<ScheduleLink>,  // NEW
    pub span: Span,
}

// Template can also have links
pub struct Template {
    pub name: String,
    pub fields: Vec<Field>,
    pub includes: Vec<Vec<String>>,
    pub behavior_links: Vec<BehaviorLink>,  // NEW
    pub schedule_links: Vec<ScheduleLink>,  // NEW
    pub span: Span,
}
```

---

## 4. Parser Design (LALRPOP)

### 4.1 Grammar Productions

```lalrpop
// In parser.lalrpop

// Character definition with optional links
pub Character: Character = {
    "character" <name:Ident> <species:SpeciesClause?> <template:TemplateClause?> "{"
        <items:CharacterItem*>
    "}" => {
        let mut fields = vec![];
        let mut behavior_links = vec![];
        let mut schedule_links = vec![];

        for item in items {
            match item {
                CharacterItem::Field(f) => fields.push(f),
                CharacterItem::BehaviorLink(bl) => behavior_links.extend(bl),
                CharacterItem::ScheduleLink(sl) => schedule_links.extend(sl),
            }
        }

        Character { name, species, fields, template, behavior_links, schedule_links, span }
    }
};

CharacterItem: CharacterItem = {
    <Field> => CharacterItem::Field(<>),
    <BehaviorLinkStmt> => CharacterItem::BehaviorLink(<>),
    <ScheduleLinkStmt> => CharacterItem::ScheduleLink(<>),
};

// Behavior link statement
BehaviorLinkStmt: Vec<BehaviorLink> = {
    // Single link: uses behavior: BehaviorName
    "uses" "behavior" ":" <path:QualifiedPath> => {
        vec![BehaviorLink {
            tree: path,
            priority: None,
            condition: None,
            is_default: false,
            span,
        }]
    },

    // Multiple links: uses behaviors: [...]
    "uses" "behaviors" ":" "[" <links:Comma<BehaviorLinkSpec>> "]" => links,
};

BehaviorLinkSpec: BehaviorLink = {
    // { tree: Name, priority: normal, when: condition, default: true }
    "{" <fields:Comma<BehaviorLinkField>> "}" => {
        let mut tree = None;
        let mut priority = None;
        let mut condition = None;
        let mut is_default = false;

        for field in fields {
            match field {
                BehaviorLinkField::Tree(path) => tree = Some(path),
                BehaviorLinkField::Priority(p) => priority = Some(p),
                BehaviorLinkField::Condition(c) => condition = Some(c),
                BehaviorLinkField::Default => is_default = true,
            }
        }

        BehaviorLink {
            tree: tree.expect("tree field required"),
            priority,
            condition,
            is_default,
            span,
        }
    },
};

BehaviorLinkField: BehaviorLinkField = {
    "tree" ":" <QualifiedPath> => BehaviorLinkField::Tree(<>),
    "priority" ":" <Ident> => BehaviorLinkField::Priority(<>),
    "when" ":" <Expr> => BehaviorLinkField::Condition(<>),
    "default" ":" "true" => BehaviorLinkField::Default,
};

// Schedule link statement (parallel structure)
ScheduleLinkStmt: Vec<ScheduleLink> = {
    "uses" "schedule" ":" <path:QualifiedPath> => {
        vec![ScheduleLink {
            schedule: path,
            condition: None,
            is_default: false,
            span,
        }]
    },

    "uses" "schedules" ":" "[" <links:Comma<ScheduleLinkSpec>> "]" => links,
};

ScheduleLinkSpec: ScheduleLink = {
    "{" <fields:Comma<ScheduleLinkField>> "}" => {
        let mut schedule = None;
        let mut condition = None;
        let mut is_default = false;

        for field in fields {
            match field {
                ScheduleLinkField::Schedule(path) => schedule = Some(path),
                ScheduleLinkField::Condition(c) => condition = Some(c),
                ScheduleLinkField::Default => is_default = true,
            }
        }

        ScheduleLink {
            schedule: schedule.expect("schedule field required"),
            condition,
            is_default,
            span,
        }
    },
};

ScheduleLinkField: ScheduleLinkField = {
    "schedule" ":" <QualifiedPath> => ScheduleLinkField::Schedule(<>),
    "when" ":" <Expr> => ScheduleLinkField::Condition(<>),
    "default" ":" "true" => ScheduleLinkField::Default,
};
```

---

## 5. Resolution & Validation

### 5.1 Name Resolution

During the resolution pass (Pass 3 in design.md §4.7), the resolver must:

1. **Resolve Behavior Paths**: Each `tree: BehaviorName` must reference a valid `behavior` declaration
2. **Resolve Schedule Paths**: Each `schedule: ScheduleName` must reference a valid `schedule` declaration
3. **Validate Priorities**: Priority values must be one of {critical, high, normal, low}
4. **Validate Conditions**: Expressions in `when` clauses must be valid and type-check

**Error Examples:**
```
error: unresolved behavior reference
  ┌─ characters/alice.sb:12:23
  │
12 │     uses behavior: CuriousExporer
  │                     ^^^^^^^^^^^^^^ no behavior named `CuriousExporer` exists
  │
  = help: did you mean `CuriousExplorer`? (defined in behaviors/alice_behaviors.sb)
```

### 5.2 Semantic Validation

1. **At Most One Default**: Each link array can have at most one `default: true`
2. **Priority + Default Conflicts**: If `default: true`, priority should be `low` or omitted
3. **Condition Completeness**: Warn if conditions are not exhaustive (no default + gaps in conditions)

**Warning Example:**
```
warning: conditions may not cover all cases
  ┌─ characters/alice.sb:8:5
  │
 8 │     uses behaviors: [
 9 │         { tree: GiantBehavior, when: current_size == huge }
10 │         { tree: TinyBehavior, when: current_size == tiny }
11 │     ]
  │
  = note: no default behavior specified and conditions don't cover all size values
  = help: add a default behavior: { tree: NormalBehavior, default: true }
```

### 5.3 Template Merge Logic

When a character uses `from Template`, behavior and schedule links are merged:

```rust
// Pseudocode for merge logic
fn merge_character_with_template(char: Character, template: Template) -> ResolvedCharacter {
    let behavior_links = if !char.behavior_links.is_empty() {
        char.behavior_links  // Character overrides completely
    } else {
        template.behavior_links  // Inherit from template
    };

    let schedule_links = if !char.schedule_links.is_empty() {
        char.schedule_links
    } else {
        template.schedule_links
    };

    // ... merge fields, etc.
}
```

**Key Rule**: If character defines ANY behavior links, template's behavior links are ignored entirely. Same for schedules. This is all-or-nothing replacement, not merging. (no, i like merging. idk how we'll handle conflicts, but i want to support that kinda composition)

---

## 6. Resolved Type Representation

### 6.1 Resolved Link Types

```rust
// In src/types.rs

/// Resolved behavior link with all references resolved
#[derive(Debug, Clone, PartialEq)]
pub struct ResolvedBehaviorLink {
    pub tree_name: String,              // Fully qualified behavior name
    pub priority: Priority,             // Resolved to enum
    pub condition: Option<Expr>,        // Validated expression
    pub is_default: bool,
}

/// Resolved schedule link
#[derive(Debug, Clone, PartialEq)]
pub struct ResolvedScheduleLink {
    pub schedule_name: String,          // Fully qualified schedule name
    pub condition: Option<Expr>,
    pub is_default: bool,
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum Priority {
    Critical = 3,
    High = 2,
    Normal = 1,
    Low = 0,
}
```

### 6.2 Updated Resolved Structs

```rust
pub struct ResolvedCharacter {
    pub name: String,
    pub species: Option<String>,
    pub fields: HashMap<String, Value>,
    pub prose_blocks: HashMap<String, ProseBlock>,
    pub behavior_links: Vec<ResolvedBehaviorLink>,  // NEW
    pub schedule_links: Vec<ResolvedScheduleLink>,  // NEW
    pub span: Span,
}

pub struct ResolvedInstitution {
    pub name: String,
    pub fields: HashMap<String, Value>,
    pub behavior_links: Vec<ResolvedBehaviorLink>,  // NEW
    pub schedule_links: Vec<ResolvedScheduleLink>,  // NEW
    pub span: Span,
}
```

---

## 7. SBIR Representation Proposal

### 7.1 CHARACTERS Section Extension

Currently, the CHARACTERS section (called ENTITIES in some specs) stores character data. We extend it:

```
CHARACTERS Section:
  - count: u32
  - characters: [Character...]

Character:
  - name: String
  - species: Option<String>
  - fields: Map<String, Value>
  - behavior_links: [BehaviorLink...]  <-- NEW
  - schedule_links: [ScheduleLink...]  <-- NEW

BehaviorLink:
  - behavior_id: u32                   (index into BEHAVIORS section)
  - priority: u8                       (0=low, 1=normal, 2=high, 3=critical)
  - condition: Option<Expression>
  - is_default: bool

ScheduleLink:
  - schedule_id: u32                   (index into SCHEDULES section)
  - condition: Option<Expression>
  - is_default: bool

Expression:
  - (Existing expression bytecode format from design.md §5)
```

### 7.2 INSTITUTIONS Section Extension

```
INSTITUTIONS Section:
  - count: u32
  - institutions: [Institution...]

Institution:
  - name: String
  - fields: Map<String, Value>
  - behavior_links: [BehaviorLink...]  <-- NEW
  - schedule_links: [ScheduleLink...]  <-- NEW
```

### 7.3 BEHAVIORS and SCHEDULES Sections

These sections remain unchanged—they define the behavior trees and schedules. Links reference them by index.

**Index Resolution:**
- During compilation, behavior/schedule names are resolved to their index in the respective section
- At runtime, the engine uses the index to look up the behavior/schedule definition

---

## 8. Runtime Link Resolution Algorithm

### 8.1 Behavior Selection

When the engine needs to select a behavior for a character:

```rust
fn select_behavior(character: &Character, context: &RuntimeContext) -> Option<&Behavior> {
    let mut candidates: Vec<_> = character.behavior_links
        .iter()
        .filter(|link| {
            // Evaluate condition if present
            link.condition.is_none() || evaluate_condition(&link.condition, context)
        })
        .collect();

    if candidates.is_empty() {
        return None;
    }

    // Sort by priority (descending)
    candidates.sort_by(|a, b| b.priority.cmp(&a.priority));

    // Return highest priority candidate
    // (If multiple same priority, declaration order is preserved by stable sort)
    let selected = candidates[0];
    Some(get_behavior_by_id(selected.behavior_id))
}
```

**Key Properties:**
- Priority-based selection: higher priority wins
- Conditions filter candidates before priority sorting
- `default: true` only matters if no conditions match (it's implicitly `when: true`)
- Deterministic: same context always yields same behavior

### 8.2 Schedule Selection

```rust
fn select_schedule(entity: &Entity, context: &RuntimeContext) -> Option<&Schedule> {
    for link in &entity.schedule_links {
        if link.is_default {
            continue;  // Skip default, check it last
        }

        if link.condition.is_none() || evaluate_condition(&link.condition, context) {
            return Some(get_schedule_by_id(link.schedule_id));
        }
    }

    // No conditions matched, use default if present
    entity.schedule_links
        .iter()
        .find(|link| link.is_default)
        .map(|link| get_schedule_by_id(link.schedule_id))
}
```

**Key Properties:**
- First-match semantics: first condition that evaluates to true wins
- Default is fallback: only used if no condition matches
- Order matters: earlier links are checked first

---

## 9. Examples

### 9.1 Simple Character with Behavior and Schedule

```storybook
behavior BakerBehavior {
    > {
        check_oven
        serve_customers
        clean_workspace
    }
}

schedule BakerSchedule {
    block work { 5:00 - 13:00 }
    block lunch { 13:00 - 14:00 }
    block home { 14:00 - 22:00 }
    block sleep { 22:00 - 5:00 }
}

character Martha: Human {
    age: 34
    occupation: baker

    uses behavior: BakerBehavior
    uses schedule: BakerSchedule
}
```

### 9.2 Character with Multiple Context-Dependent Behaviors

```storybook
character Alice: Human {
    age: 7
    current_size: normal
    emotional_state: curious

    uses behaviors: [
        { tree: PanicBehavior, priority: critical, when: emotional_state == frightened }
        { tree: GiantBehavior, when: current_size == huge }
        { tree: TinyBehavior, when: current_size == tiny }
        { tree: BraveBehavior, when: emotional_state == brave }
        { tree: CuriousExplorer, default: true }
    ]

    uses schedules: [
        { schedule: SleepingSchedule, when: emotional_state == exhausted }
        { schedule: AdventureSchedule, default: true }
    ]
}
```

### 9.3 Institution with Seasonal Schedules

```storybook
schedule SummerHours {
    block open { 6:00 - 20:00 }
    block closed { 20:00 - 6:00 }
}

schedule WinterHours {
    block open { 7:00 - 18:00 }
    block closed { 18:00 - 7:00 }
}

institution Bakery {
    type: commercial

    uses behavior: BakeryOperations
    uses schedules: [
        { schedule: SummerHours, when: season == summer }
        { schedule: WinterHours, when: season == winter }
    ]
}
```

### 9.4 Template with Default Links

```storybook
behavior WonderlandBehavior {
    > {
        speak_nonsense
        violate_logic
    }
}

schedule WonderlandSchedule {
    block awake { 0:00 - 24:00 }  // Always awake in dreams
}

template WonderlandCreature {
    uses behavior: WonderlandBehavior
    uses schedule: WonderlandSchedule
}

character CheshireCat: Cat from WonderlandCreature {
    // Inherits WonderlandBehavior and WonderlandSchedule
    can_vanish: true
}

character Alice: Human from WonderlandCreature {
    // Overrides behavior but keeps schedule
    uses behavior: CuriousExplorer
}
```

---

## 10. Open Questions for User Review (Checkpoint 1)

### Question 1: Priority vs. Declaration Order

**Current Design:** Priority determines order, then declaration order breaks ties.

**Alternative:** Remove priority, use only declaration order (simpler but less expressive).

**Recommendation:** Keep priority. It's more explicit and handles common use cases like "urgent needs always trump routine activities." (i guess priority is fine)

### Question 2: Condition Syntax Sugar

**Current Design:** Full condition expressions.

**Alternative:** Add syntactic sugar for common patterns:
```storybook
uses behaviors: [
    { tree: GiantBehavior, when: current_size == huge }
    // vs.
    { tree: GiantBehavior, when current_size: huge }  // shorter
]
```

**Recommendation:** Start with full expressions, add sugar if usage reveals patterns. (use `==` or `is`, support both like python does.)

### Question 3: Schedule-Behavior Integration

**Current Design:** Behaviors and schedules are separate links. Schedule determines WHEN, behavior determines WHAT.

**Alternative:** Allow schedules to specify behaviors inline:
```storybook
schedule WorkSchedule {
    block work { 9:00 - 17:00, behavior: WorkBehavior }
}
```

**Recommendation:** Defer inline behaviors to schedule system design (Task #8). Keep linking separate for now. (yeah that's fine)

### Question 4: Link Override Semantics

**Current Design:** If character defines any behavior links, template's links are completely replaced.

**Alternative:** Merge character and template links (character links come first, then template links).

**Recommendation:** Keep replacement semantics. It's clearer and matches existing override system. (sure? i don't remember the nuances tbh)

### Question 5: Multiple Defaults

**Current Design:** At most one `default: true` per link type.

**Alternative:** Allow multiple defaults with priority order.

**Recommendation:** Keep single default. Multiple defaults creates ambiguity. (single default makes sense?)

---

## 11. Implementation Plan (for Task #6)

### Phase 1: AST Extension (Week 1)
1. Add `BehaviorLink` and `ScheduleLink` structs to `ast.rs`
2. Add link fields to `Character`, `Institution`, `Template`
3. Update `Declaration` enum if needed

### Phase 2: Parser Implementation (Week 1-2)
1. Implement `BehaviorLinkStmt` and `ScheduleLinkStmt` grammar
2. Implement `BehaviorLinkSpec` and `ScheduleLinkSpec` parsing
3. Add link parsing to character, institution, template productions
4. Write parser tests for all link variations

### Phase 3: Resolution (Week 2)
1. Implement behavior/schedule name resolution in `resolve/names.rs`
2. Add priority validation
3. Add condition expression validation
4. Implement template merge logic for links in `resolve/merge.rs`
5. Write resolution tests

### Phase 4: Resolved Types (Week 2)
1. Add `ResolvedBehaviorLink` and `ResolvedScheduleLink` to `types.rs`
2. Update `ResolvedCharacter` and `ResolvedInstitution`
3. Implement conversion in `resolve/convert.rs`
4. Write conversion tests

### Phase 5: Validation & Diagnostics (Week 3)
1. Implement semantic validation (single default, etc.)
2. Add helpful error messages with fuzzy matching
3. Add warnings for incomplete condition coverage
4. Write validation tests

### Phase 6: Integration & Documentation (Week 3)
1. Update examples to use new linking syntax
2. Update language documentation
3. Run full test suite
4. Create migration examples (if backward compatibility breaks)

**Total Estimate:** 3 weeks implementation after design approval.

---

## 12. Success Criteria

### Must Have
- [x] Unified `uses` keyword for behaviors and schedules
- [x] Single-link syntax works (`uses behavior: Name`)
- [x] Multi-link syntax works (`uses behaviors: [...]`)
- [x] Conditions supported (`when: expression`)
- [x] Priorities supported for behaviors
- [x] Default fallback supported (`default: true`)
- [x] Template inheritance works
- [x] Character linking works
- [x] Institution linking works
- [x] Parser produces correct AST
- [x] Resolver validates references
- [x] Clear error messages
- [x] SBIR format defined

### Should Have
- [ ] Warning for incomplete condition coverage
- [ ] Examples for all use cases
- [ ] Migration guide if needed
- [ ] Runtime selection algorithm specification
- [ ] Performance characteristics documented

### Nice to Have
- [ ] Visual editor support design
- [ ] Auto-completion for behavior/schedule names
- [ ] Link refactoring tools

---

## 13. Risks & Mitigation

| Risk | Likelihood | Impact | Mitigation |
|------|-----------|--------|------------|
| Syntax conflicts with relationship linking | Low | Medium | Different syntax context—parser can disambiguate |
| Complex condition expressions hard to debug | Medium | Medium | Good error messages, warnings for non-exhaustive conditions |
| Priority system confusing for users | Medium | Low | Clear documentation, examples, default priority=normal |
| Template override semantics unclear | Medium | Medium | Explicit documentation, validation warnings |
| SBIR encoding inefficient | Low | Low | Use indices for references, compress expressions |
| Runtime selection too slow | Low | Medium | Profile early, cache selections if needed |

---

## Appendix A: Comparison with Relationship Linking

**Relationship Linking** (existing):
- Top-level `relationship` declarations
- Participants within relationships
- Bidirectional by nature
- `self`/`other` blocks for asymmetry

**Resource Linking** (this design):
- Links within character/institution definitions
- References to external behaviors/schedules
- Unidirectional (character → behavior)
- Conditions/priorities for selection

These are complementary systems serving different purposes. No conflict.

---

## Appendix B: Grammar Sketch (Full)

```lalrpop
// Simplified grammar showing link integration

Character: Character = {
    "character" <name:Ident> <species:SpeciesClause?> <template:TemplateClause?>
    "{" <items:CharacterItem*> "}" => // ... construct Character
};

CharacterItem = {
    Field,
    BehaviorLinkStmt,
    ScheduleLinkStmt,
    ProseBlock,
};

BehaviorLinkStmt: Vec<BehaviorLink> = {
    "uses" "behavior" ":" <QualifiedPath> => // single link
    "uses" "behaviors" ":" "[" <Comma<BehaviorLinkSpec>> "]" => // multi link
};

BehaviorLinkSpec: BehaviorLink = {
    "{" <Comma<BehaviorLinkField>> "}" => // parse fields into BehaviorLink
};

BehaviorLinkField = {
    "tree" ":" QualifiedPath,
    "priority" ":" Ident,
    "when" ":" Expr,
    "default" ":" "true",
};

// Parallel structure for schedules...
```

---

**End of Design Document**

**Next Step:** Present to user (Sienna) for Checkpoint 1 review and approval.
