# Year-Long Composable Schedule System - REVISION
**Author:** Resource Linking Architect (Schedule System Designer)
**Date:** 2026-02-12
**Status:** Revised based on User Feedback
**Version:** 0.2
**Supersedes:** year-long-schedule-system.md v0.1

---

## Changes from v0.1

This revision addresses Sienna's feedback:

1. ✅ **Simplified composition** - Keep only `modifies` and `override`, remove `remove`/`append`/`replace all`
2. ✅ **User-configurable calendars** - Define seasons/days as enums in schema, not hardcoded
3. ✅ **Behavior references** - Blocks reference behaviors/actions, not string activity names
4. ✅ **Required block names** - All blocks must be named for override system
5. ✅ **Time overlap detection** - Validator warns on overlapping blocks
6. ✅ **Explicit time ranges** - No default durations, must specify start/end
7. ✅ **Recurrence keyword** - Named recurring patterns instead of `every`

---

## Executive Summary

This document proposes a **year-long, composable schedule system** for the Storybook DSL that:

- **User-defined calendars**: Seasons, days, months defined as enums (8 seasons? 5-day weeks? You decide!)
- **Simple composition**: Only `modifies` and `override` (no complex operators)
- **Behavior integration**: Schedule blocks reference behaviors, not string activities
- **Temporal patterns**: Day-specific, seasonal, and recurring event patterns
- **Type-safe**: Validator ensures calendar references are valid
- **Backward compatible**: Current simple schedules still work

---

## 1. User-Configurable Calendar System

### 1.1 The Problem

**Original design** hardcoded Euro-centric calendar:
- 4 seasons (Spring, Summer, Fall, Winter)
- 7-day week (Monday-Sunday)
- 12 Gregorian months

**User need:** Lonni wants 8 seasons, fantasy day names, custom time systems.

### 1.2 The Solution: Calendar Enums

**Define calendar in schema files** using existing enum system:

```storybook
// In schema/calendar.sb

enum Season {
    EarlySpring
    LateSpring
    EarlySummer
    LateSummer
    EarlyFall
    LateFall
    EarlyWinter
    LateWinter
}

enum DayOfWeek {
    Fireday
    Waterday
    Earthday
    Airday
    Spiritday
}

enum Month {
    FirstMonth
    SecondMonth
    ThirdMonth
    FourthMonth
    FifthMonth
    SixthMonth
    SeventhMonth
    EighthMonth
    NinthMonth
    TenthMonth
    EleventhMonth
    TwelfthMonth
}
```

**Benefits:**
- ✅ Uses existing enum system (no new concepts)
- ✅ Type-safe (validator checks references)
- ✅ Version-controlled with content
- ✅ Infinitely flexible (any calendar system)
- ✅ Self-documenting (enum values show available options)

### 1.3 Using Calendar Enums in Schedules

```storybook
schedule FarmSchedule {
    season (EarlySpring, LateSpring) {
        block planting { 5:00 - 18:00, action: PlantCrops }
    }

    season (EarlySummer, LateSummer) {
        block tending { 6:00 - 16:00, action: TendFields }
    }

    on Fireday {
        block ritual { 6:00 - 7:00, action: FireRitual }
    }
}
```

**Validator checks:**
- `EarlySpring` exists in `Season` enum? ✓
- `Fireday` exists in `DayOfWeek` enum? ✓
- Clear error if user typos: "Unknown season 'EarlySrping'. Did you mean 'EarlySpring'?"

### 1.4 Standard Calendar (Convenience)

**For users who want standard calendar**, we ship a default schema:

```storybook
// In schema/standard_calendar.sb

enum Season {
    Spring
    Summer
    Fall
    Winter
}

enum DayOfWeek {
    Monday
    Tuesday
    Wednesday
    Thursday
    Friday
    Saturday
    Sunday
}

enum Month {
    January
    February
    March
    April
    May
    June
    July
    August
    September
    October
    November
    December
}
```

Users can `use schema::standard_calendar::*` or define their own!

---

## 2. Simplified Composition System

### 2.1 Only Two Operators

**Keep:**
- `modifies` - Inherit from base schedule
- `override` - Replace specific blocks

**Remove:**
- ~~`remove`~~ - Too complex, just override with empty/different block
- ~~`append`~~ - Just define new blocks directly
- ~~`replace all`~~ - Just don't extend if you want fresh start

### 2.2 Composition Examples

**Basic Extension:**
```storybook
schedule BaseWorkday {
    block sleep { 0:00 - 6:00, action: Sleep }
    block work { 9:00 - 17:00, action: Work }
    block leisure { 17:00 - 22:00, action: Leisure }
    block sleep_late { 22:00 - 24:00, action: Sleep }
}

schedule BakerSchedule modifies BaseWorkday {
    override work { 5:00 - 13:00, action: BakeryWork }
    block baking { 3:00 - 5:00, action: PrepBread }  // New block, not override
}
```

**Result:**
- `sleep` (0:00-6:00) - inherited
- `baking` (3:00-5:00) - new
- `work` (5:00-13:00) - overridden
- `leisure` (17:00-22:00) - inherited
- `sleep_late` (22:00-24:00) - inherited

### 2.3 Override Semantics

**Override by block name**, not by time:

```storybook
schedule Base {
    block work { 9:00 - 17:00, action: GenericWork }
}

schedule Baker modifies Base {
    override work { 5:00 - 13:00, action: BakeryWork }
}
// Baker's 'work' block replaces Base's 'work' block entirely
// Time changed from 9:00-17:00 to 5:00-13:00
// Action changed from GenericWork to BakeryWork
```

**Partial override** (only change some fields):

```storybook
schedule Base {
    block work { 9:00 - 17:00, action: GenericWork, location: Office }
}

schedule Remote modifies Base {
    override work { location: Home }  // Only change location
}
// Result: work { 9:00 - 17:00, action: GenericWork, location: Home }
```

---

## 3. Behavior References (Not String Activities)

### 3.1 The Change

**Old (v0.1):**
```storybook
block work { 9:00 - 17:00, activity: "work" }  // String
```

**New (v0.2):**
```storybook
block work { 9:00 - 17:00, action: WorkBehavior }  // Behavior reference
```

### 3.2 Rationale

**Benefits:**
- Type-safe: Validator ensures `WorkBehavior` exists
- Flexible: Different schedules can use different behaviors for same time
- Composable: Behaviors are already defined elsewhere
- Clear: No ambiguity about what "work" means

**Example:**
```storybook
behavior BakeryWork {
    > {
        check_oven
        serve_customers
        clean_workspace
    }
}

behavior OfficeWork {
    > {
        check_email
        attend_meetings
        write_reports
    }
}

schedule BakerSchedule {
    block work { 5:00 - 13:00, action: BakeryWork }
}

schedule OfficeSchedule {
    block work { 9:00 - 17:00, action: OfficeWork }
}
```

Both schedules have a `work` block, but they reference different behaviors!

### 3.3 Optional Fields

Blocks can still have additional fields for context:

```storybook
block work {
    time: 9:00 - 17:00,
    action: BakeryWork,
    location: Bakery,
    priority: high,
    notes: "Must arrive early to prep dough"
}
```

---

## 4. Temporal Patterns

### 4.1 Day-Specific Patterns

```storybook
schedule WeeklyRoutine {
    on Fireday {
        block ritual { 6:00 - 7:00, action: FireRitual }
        block work { 8:00 - 16:00, action: CraftWork }
    }

    on Waterday {
        block meditation { 6:00 - 7:00, action: WaterMeditation }
        block work { 8:00 - 16:00, action: CraftWork }
    }

    on Spiritday {
        block rest { 0:00 - 24:00, action: Rest }
    }
}
```

**Can extend base schedule per day:**
```storybook
schedule WeeklyRoutine {
    on Fireday modifies BaseWorkday {
        override work { action: FireWork }
        block ritual { 6:00 - 7:00, action: FireRitual }
    }
}
```

### 4.2 Seasonal Patterns

```storybook
schedule FarmSchedule {
    season (EarlySpring, LateSpring) {
        block planting { 5:00 - 18:00, action: PlantCrops }
    }

    season (EarlySummer, LateSummer) {
        block tending { 6:00 - 16:00, action: TendFields }
    }

    season (EarlyFall, LateFall) {
        block harvest { 5:00 - 19:00, action: HarvestCrops }
    }

    season (EarlyWinter, LateWinter) {
        block planning { 9:00 - 15:00, action: PlanNextYear }
    }
}
```

**Multiple seasons in one pattern:**
```storybook
season (Bloom, Growth) {  // Both use same schedule
    block outdoor_work { 5:00 - 18:00, action: FarmWork }
}
```

### 4.3 Recurrence Patterns

**Named recurring events:**

```storybook
schedule AnnualPattern modifies BaseWorkday {
    recurrence MarketDay on Earthday {
        block market { 8:00 - 13:00, action: SellAtMarket }
    }

    recurrence GuildMeeting on FirstFiredayOfMonth {
        block meeting { 19:00 - 21:00, action: GuildBusiness }
    }

    recurrence Festival on MidsummerDay {
        block celebration { 0:00 - 24:00, action: Celebrate }
    }
}
```

**Recurrence types:**
- `on <DayOfWeek>` - Every week on that day
- `on First<DayOfWeek>OfMonth` - First occurrence each month
- `on Last<DayOfWeek>OfMonth` - Last occurrence each month
- `on <SpecificDate>` - Specific calendar date (e.g., Midsummer Day 15)

**Why `recurrence` keyword:**
- More explicit than `every`
- Can be named (useful for override/reference)
- Clear that it's a repeating pattern
- Consistent with other constructs (behavior, character, etc.)

---

## 5. Required Block Names

### 5.1 All Blocks Must Be Named

**Old (v0.1):**
```storybook
block { 9:00 - 17:00, activity: work }  // Anonymous
```

**New (v0.2):**
```storybook
block work { 9:00 - 17:00, action: Work }  // Named
```

### 5.2 Rationale

**Why required:**
- Override system needs names to identify blocks
- Better error messages ("overlap in 'work' block")
- Self-documenting code
- Enables referencing blocks

**Syntax:**
```storybook
block <name> { <fields> }
block <name> { <time>, <fields> }
```

**Time specification:**
```storybook
block work { 9:00 - 17:00, action: Work }
// OR
block work {
    time: 9:00 - 17:00,
    action: Work,
    location: Office
}
```

---

## 6. Time Overlap Detection

### 6.1 Validation Rule

**Validator warns** when blocks overlap in same schedule:

```storybook
schedule Broken {
    block work { 9:00 - 17:00, action: Work }
    block lunch { 12:00 - 13:00, action: Eat }  // Overlaps work!
}
```

**Warning:**
```
warning: schedule blocks overlap
  ┌─ schedules/daily.sb:12:5
  │
12 │     block lunch { 12:00 - 13:00, action: Eat }
  │     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  │
  = note: 'lunch' (12:00-13:00) overlaps with 'work' (9:00-17:00)
  = help: consider adjusting time ranges or removing one block
```

### 6.2 When Overlaps Are OK

**Different days/seasons:**
```storybook
schedule Valid {
    on Fireday {
        block work { 9:00 - 17:00, action: Work }
    }
    on Waterday {
        block work { 9:00 - 17:00, action: Work }  // OK, different day
    }
}
```

**Validator only checks overlaps within same temporal context.**

---

## 7. Explicit Time Ranges Required

### 7.1 No Default Durations

**Error if time not specified:**

```storybook
block work { action: Work }  // ERROR: missing time range
```

**Error message:**
```
error: missing time range for schedule block
  ┌─ schedules/daily.sb:5:5
  │
 5 │     block work { action: Work }
  │     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  │
  = note: all schedule blocks must specify a time range
  = help: add time field: block work { 9:00 - 17:00, action: Work }
```

### 7.2 Time Syntax

**Short form (preferred):**
```storybook
block work { 9:00 - 17:00, action: Work }
```

**Long form:**
```storybook
block work {
    time: 9:00 - 17:00,
    action: Work
}
```

**Both valid, same result.**

---

## 8. AST Design

### 8.1 Simplified Schedule Structure

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

#[derive(Debug, Clone, PartialEq)]
pub struct Schedule {
    pub name: String,
    pub modifies: Option<Vec<String>>,     // modifies BaseSchedule
    pub items: Vec<ScheduleItem>,         // blocks and patterns
    pub span: Span,
}

#[derive(Debug, Clone, PartialEq)]
pub enum ScheduleItem {
    Block(ScheduleBlock),           // Direct block definition
    Override(ScheduleOverride),     // override block_name { ... }
    DayPattern(DayPattern),         // on Fireday { ... }
    SeasonPattern(SeasonPattern),   // season (Bloom, Growth) { ... }
    Recurrence(RecurrencePattern),  // recurrence Name on ... { ... }
}

#[derive(Debug, Clone, PartialEq)]
pub struct ScheduleBlock {
    pub name: String,                     // REQUIRED (no Option)
    pub time: TimeRange,                  // REQUIRED
    pub action: Vec<String>,              // Behavior reference (qualified path)
    pub fields: Vec<Field>,               // Additional fields
    pub span: Span,
}

#[derive(Debug, Clone, PartialEq)]
pub struct TimeRange {
    pub start: Time,  // HH:MM
    pub end: Time,    // HH:MM
    pub span: Span,
}

#[derive(Debug, Clone, PartialEq)]
pub struct ScheduleOverride {
    pub block_name: String,
    pub fields: Vec<Field>,  // Can override time, action, location, etc.
    pub span: Span,
}

#[derive(Debug, Clone, PartialEq)]
pub struct DayPattern {
    pub day: String,                      // Reference to DayOfWeek enum value
    pub modifies: Option<Vec<String>>,    // Optional base schedule
    pub blocks: Vec<ScheduleBlock>,
    pub span: Span,
}

#[derive(Debug, Clone, PartialEq)]
pub struct SeasonPattern {
    pub seasons: Vec<String>,             // References to Season enum values
    pub blocks: Vec<ScheduleBlock>,
    pub span: Span,
}

#[derive(Debug, Clone, PartialEq)]
pub struct RecurrencePattern {
    pub name: String,                     // MarketDay, GuildMeeting
    pub spec: RecurrenceSpec,             // on Earthday, on FirstFiredayOfMonth
    pub blocks: Vec<ScheduleBlock>,
    pub span: Span,
}

#[derive(Debug, Clone, PartialEq)]
pub enum RecurrenceSpec {
    Weekly(String),                       // on Earthday
    MonthlyFirst(String),                 // on FirstFiredayOfMonth
    MonthlyLast(String),                  // on LastFiredayOfMonth
    Yearly(String, u8),                   // on MidsummerDay 15 (month, day)
}
```

---

## 9. Grammar Design (LALRPOP)

### 9.1 Schedule Productions

```lalrpop
pub Schedule: Schedule = {
    "schedule" <name:Ident> <modifies:ModifiesClause?> "{"
        <items:ScheduleItem*>
    "}" => Schedule { name, modifies, items, span }
};

ModifiesClause: Vec<String> = {
    "modifies" <QualifiedPath>
};

ScheduleItem: ScheduleItem = {
    "block" <ScheduleBlock> => ScheduleItem::Block(<>),
    "override" <ScheduleOverride> => ScheduleItem::Override(<>),
    "on" <DayPattern> => ScheduleItem::DayPattern(<>),
    "season" <SeasonPattern> => ScheduleItem::SeasonPattern(<>),
    "recurrence" <RecurrencePattern> => ScheduleItem::Recurrence(<>),
};

// Block: block work { 9:00 - 17:00, action: Work }
ScheduleBlock: ScheduleBlock = {
    <name:Ident> "{" <fields:Comma<BlockField>> "}" => {
        let mut time = None;
        let mut action = None;
        let mut extra_fields = vec![];

        for field in fields {
            match field {
                BlockField::Time(t) => time = Some(t),
                BlockField::Action(a) => action = Some(a),
                BlockField::Other(f) => extra_fields.push(f),
            }
        }

        ScheduleBlock {
            name,
            time: time.expect("time range required"),
            action: action.expect("action required"),
            fields: extra_fields,
            span
        }
    }
};

BlockField = {
    <TimeRange> => BlockField::Time(<>),
    "action" ":" <QualifiedPath> => BlockField::Action(<>),
    <Field> => BlockField::Other(<>),
};

TimeRange: TimeRange = {
    <start:Time> "-" <end:Time> => TimeRange { start, end, span }
};

// Override: override work { time: 5:00 - 13:00 }
ScheduleOverride: ScheduleOverride = {
    <name:Ident> "{" <fields:Comma<Field>> "}" =>
        ScheduleOverride { block_name: name, fields, span }
};

// Day pattern: on Fireday { blocks }
DayPattern: DayPattern = {
    <day:Ident> <modifies:ModifiesClause?> "{" <blocks:ScheduleBlock*> "}" =>
        DayPattern { day, modifies, blocks, span }
};

// Season pattern: season (Bloom, Growth) { blocks }
SeasonPattern: SeasonPattern = {
    "(" <seasons:Comma<Ident>> ")" "{" <blocks:ScheduleBlock*> "}" =>
        SeasonPattern { seasons, blocks, span }
};

// Recurrence: recurrence MarketDay on Earthday { blocks }
RecurrencePattern: RecurrencePattern = {
    <name:Ident> "on" <spec:RecurrenceSpec> "{" <blocks:ScheduleBlock*> "}" =>
        RecurrencePattern { name, spec, blocks, span }
};

RecurrenceSpec: RecurrenceSpec = {
    <Ident> => RecurrenceSpec::Weekly(<>),  // on Earthday
    "First" <Ident> "OfMonth" => RecurrenceSpec::MonthlyFirst(<>),
    "Last" <Ident> "OfMonth" => RecurrenceSpec::MonthlyLast(<>),
    <month:Ident> <day:Integer> => RecurrenceSpec::Yearly(month, day),
};
```

---

## 10. Resolution & Validation

### 10.1 Calendar Enum Validation

**Validator checks** that calendar references are valid enum values:

```storybook
// schema/calendar.sb defines:
enum Season { Bloom, Heat, Harvest, Frost }

// In schedule:
season (Bloom, Heat) { ... }  // ✓ Valid

season (Spring) { ... }  // ✗ Error: 'Spring' not in Season enum
```

**Error message:**
```
error: unknown season
  ┌─ schedules/farm.sb:8:13
  │
 8 │     season (Spring) {
  │             ^^^^^^ season 'Spring' not defined
  │
  = note: available seasons: Bloom, Heat, Harvest, Frost
  = help: did you mean 'Bloom'?
```

### 10.2 Behavior Reference Validation

```storybook
block work { 9:00 - 17:00, action: BakeryWork }
```

**Validator checks:**
1. Does `BakeryWork` exist? (is it defined as a behavior?)
2. Is it in scope? (needs `use` statement if cross-directory)

**Error if missing:**
```
error: unresolved behavior reference
  ┌─ schedules/baker.sb:5:32
  │
 5 │     block work { 9:00 - 17:00, action: BakeryWork }
  │                                ^^^^^^^^^^^^^^^^^^^^^^
  │
  = note: no behavior named 'BakeryWork' found
  = help: did you mean 'BakeryBehavior'? (in behaviors/baker.sb)
```

### 10.3 Time Overlap Detection

**Validator walks blocks** in same temporal context:

```rust
fn check_overlaps(blocks: &[ScheduleBlock]) -> Vec<OverlapWarning> {
    let mut warnings = vec![];

    for i in 0..blocks.len() {
        for j in (i+1)..blocks.len() {
            if blocks[i].time.overlaps(&blocks[j].time) {
                warnings.push(OverlapWarning {
                    block1: blocks[i].name.clone(),
                    block2: blocks[j].name.clone(),
                    time1: blocks[i].time,
                    time2: blocks[j].time,
                });
            }
        }
    }

    warnings
}
```

**Handles midnight wraparound:**
```storybook
block evening { 22:00 - 24:00, action: Sleep }
block morning { 0:00 - 6:00, action: Sleep }
// No overlap - different calendar days
```

---

## 11. Examples

### Example 1: Simple Daily Schedule (Backward Compatible)

```storybook
schedule SimpleDay {
    block sleep { 0:00 - 6:00, action: Sleep }
    block work { 9:00 - 17:00, action: Work }
    block leisure { 17:00 - 22:00, action: Leisure }
    block sleep_late { 22:00 - 24:00, action: Sleep }
}
```

### Example 2: Schedule with Extension and Override

```storybook
schedule BaseWorkday {
    block sleep { 0:00 - 6:00, action: Sleep }
    block work { 9:00 - 17:00, action: GenericWork }
    block leisure { 17:00 - 22:00, action: Leisure }
    block sleep_late { 22:00 - 24:00, action: Sleep }
}

schedule BakerSchedule modifies BaseWorkday {
    override work { 5:00 - 13:00, action: BakeryWork }
    block prep { 3:00 - 5:00, action: PrepBread }
}

// Result for Baker:
// sleep (0:00-6:00) - inherited
// prep (3:00-5:00) - new
// work (5:00-13:00) - overridden (was 9:00-17:00)
// leisure (17:00-22:00) - inherited
// sleep_late (22:00-24:00) - inherited
```

### Example 3: Custom 8-Season Calendar

```storybook
// schema/calendar.sb
enum Season {
    EarlySpring
    LateSpring
    EarlySummer
    LateSummer
    EarlyFall
    LateFall
    EarlyWinter
    LateWinter
}

// schedules/farm.sb
schedule FarmSchedule {
    season (EarlySpring) {
        block soil_prep { 5:00 - 18:00, action: PrepareSoil }
    }

    season (LateSpring) {
        block planting { 5:00 - 18:00, action: PlantSeeds }
    }

    season (EarlySummer, LateSummer) {
        block tending { 6:00 - 16:00, action: TendCrops }
    }

    season (EarlyFall) {
        block early_harvest { 5:00 - 19:00, action: HarvestEarlyCrops }
    }

    season (LateFall) {
        block late_harvest { 6:00 - 18:00, action: HarvestLateCrops }
    }

    season (EarlyWinter, LateWinter) {
        block planning { 9:00 - 15:00, action: PlanNextYear }
    }
}
```

### Example 4: Fantasy 5-Day Week

```storybook
// schema/calendar.sb
enum DayOfWeek {
    Fireday
    Waterday
    Earthday
    Airday
    Spiritday
}

// schedules/weekly.sb
schedule MageSchedule {
    on Fireday {
        block fire_ritual { 6:00 - 7:00, action: FireMagic }
        block research { 8:00 - 16:00, action: Research }
    }

    on Waterday {
        block water_ritual { 6:00 - 7:00, action: WaterMagic }
        block research { 8:00 - 16:00, action: Research }
    }

    on Earthday {
        block earth_ritual { 6:00 - 7:00, action: EarthMagic }
        block market { 8:00 - 13:00, action: SellPotions }
    }

    on Airday {
        block air_ritual { 6:00 - 7:00, action: AirMagic }
        block research { 8:00 - 16:00, action: Research }
    }

    on Spiritday {
        block meditation { 0:00 - 24:00, action: SpiritMeditation }
    }
}
```

### Example 5: Recurring Market Days

```storybook
schedule BakerAnnual modifies BaseWorkday {
    recurrence MarketDay on Earthday {
        block market { 8:00 - 13:00, action: SellBread }
    }

    recurrence GuildMeeting on FirstFiredayOfMonth {
        block meeting { 19:00 - 21:00, action: BakersGuild }
    }

    recurrence MidsummerFestival on Midsummer 15 {
        block celebration { 0:00 - 24:00, action: Celebrate }
    }
}
```

### Example 6: Multi-Level Inheritance

```storybook
schedule BaseHuman {
    block sleep { 0:00 - 6:00, action: Sleep }
    block breakfast { 6:00 - 7:00, action: Eat }
    block dinner { 18:00 - 19:00, action: Eat }
    block sleep_late { 22:00 - 24:00, action: Sleep }
}

schedule Worker modifies BaseHuman {
    block work { 9:00 - 17:00, action: GenericWork }
}

schedule Baker modifies Worker {
    override work { 5:00 - 13:00, action: BakeryWork }
    override breakfast { 13:30 - 14:00, action: Eat }  // Late breakfast after work
    block prep { 3:00 - 5:00, action: PrepBread }
}

// Result for Baker:
// sleep (0:00-6:00) from BaseHuman
// prep (3:00-5:00) from Baker
// work (5:00-13:00) from Baker (overridden)
// breakfast (13:30-14:00) from Baker (overridden)
// dinner (18:00-19:00) from BaseHuman
// sleep_late (22:00-24:00) from BaseHuman
```

---

## 12. Integration with Resource Linking

### 12.1 Simple Case

```storybook
schedule BakerSchedule {
    block work { 5:00 - 13:00, action: BakeryWork }
    block lunch { 13:00 - 14:00, action: Eat }
    block rest { 14:00 - 22:00, action: Rest }
}

character Martha: Human {
    uses schedule: BakerSchedule
}
```

### 12.2 Conditional Schedule Linking

```storybook
character Martha: Human {
    uses schedules: [
        { schedule: WorkdaySchedule, when: day_of_week is workday }
        { schedule: WeekendSchedule, when: day_of_week is restday }
    ]
}
```

**Note:** `workday` and `restday` would need to be defined as enum values or predicates.

### 12.3 Seasonal Institution Hours

```storybook
institution Bakery {
    uses schedules: [
        { schedule: SummerHours, when: season is EarlySummer or season is LateSummer }
        { schedule: WinterHours, when: season is EarlyWinter or season is LateWinter }
        { schedule: StandardHours, default: true }
    ]
}
```

---

## 13. SBIR Representation

### 13.1 SCHEDULES Section

```
SCHEDULES Section:
  - count: u32
  - schedules: [Schedule...]

Schedule:
  - name: String
  - parent_schedule_id: Option<u32>     // modifies reference
  - blocks: [ScheduleBlock...]
  - patterns: [SchedulePattern...]

ScheduleBlock:
  - name: String                        // REQUIRED
  - start: u16                          // Minutes since midnight (0-1439)
  - end: u16                            // Minutes since midnight (0-1439)
  - action_id: u32                      // Index into BEHAVIORS section
  - fields: Map<String, Value>

SchedulePattern:
  - kind: PatternKind
  - specification: bytes
  - blocks: [ScheduleBlock...]

PatternKind:
  - Day(day_enum_value: String)
  - Season(season_enum_values: Vec<String>)
  - Recurrence(spec: RecurrenceSpec)
```

### 13.2 Runtime Evaluation

**At runtime**, engine:
1. Resolves character's schedule links (conditional selection from resource linking)
2. Merges inherited schedules (parent → child)
3. Evaluates patterns for current day/season
4. Produces final 24-hour schedule for today
5. Returns ordered list of (time, action) pairs

**Example:**
```
Character: Martha
  uses schedule: BakerSchedule

BakerSchedule modifies BaseWorkday

Merge result for today (Fireday, EarlySummer):
  03:00-05:00 → PrepBread
  05:00-13:00 → BakeryWork
  13:30-14:00 → Eat
  14:00-22:00 → Rest
  22:00-24:00 → Sleep
  00:00-06:00 → Sleep
```

---

## 14. Implementation Plan

### Phase 1: AST Extension (Week 1)
1. Simplify ScheduleItem enum (Block, Override, patterns only)
2. Make ScheduleBlock.name required (String, not Option<String>)
3. Add TimeRange struct with required start/end
4. Add action field as behavior reference (Vec<String> for qualified path)
5. Add DayPattern, SeasonPattern, RecurrencePattern
6. Update parser to require block names and time ranges

### Phase 2: Calendar Enum System (Week 1)
1. Document how to define Season/DayOfWeek/Month enums
2. Create standard_calendar.sb schema
3. Update validator to check enum references in patterns
4. Add fuzzy matching for calendar terms
5. Write tests for custom calendars

### Phase 3: Parser Implementation (Week 1-2)
1. Implement simplified `modifies`/`override` parsing
2. Implement `on <Day>` patterns
3. Implement `season (<Seasons>)` patterns
4. Implement `recurrence <Name> on <Spec>` patterns
5. Add time range validation (error if missing)
6. Write parser tests

### Phase 4: Resolution & Validation (Week 2)
1. Implement schedule inheritance resolution
2. Implement merge algorithm (same as behavior merging)
3. Implement behavior reference validation
4. Implement calendar enum validation
5. Implement time overlap detection (warnings)
6. Write resolution tests

### Phase 5: Integration (Week 2-3)
1. Update schedule linking in resource linking system
2. Implement runtime schedule evaluation
3. Update SBIR format
4. Write integration tests
5. Test with custom calendars (8 seasons, 5-day week)

### Phase 6: Documentation & Examples (Week 3)
1. Document calendar enum system
2. Create examples for standard calendar
3. Create examples for fantasy calendars
4. Update language documentation
5. Create migration guide

**Total Estimate:** 3 weeks

---

## 15. Success Criteria

### Must Have
- [x] User-defined calendars via enums
- [x] Simplified composition (`modifies`, `override` only)
- [x] Behavior references (not string activities)
- [x] Required block names
- [x] Required time ranges
- [x] Time overlap detection (warnings)
- [x] Day-specific patterns
- [x] Seasonal patterns
- [x] Recurrence patterns with `recurrence` keyword
- [x] Multi-level inheritance
- [x] Integration with resource linking

### Should Have
- [ ] Standard calendar schema (convenience)
- [ ] Clear calendar documentation
- [ ] Examples with 8-season calendar
- [ ] Examples with fantasy day names
- [ ] Comprehensive validator error messages

### Nice to Have
- [ ] Month-based patterns
- [ ] Year-long pattern visualization
- [ ] Schedule conflict resolution helpers
- [ ] Visual schedule editor design

---

## 16. Open Questions (Answered)

### Q1: Block Naming
**Answer:** ✅ Yes - all blocks must have names

### Q2: Time Overlap Detection
**Answer:** ✅ Yes - add warnings (not errors)

### Q3: Default Block Duration
**Answer:** ✅ Must throw error - require explicit times

### Q4: Seasonal Calendar
**Answer:** ✅ Configurable per world via enums

### Q5: Recurrence Syntax
**Answer:** ✅ Use `recurrence` keyword (more explicit than `every`)

---

**End of Revised Design Document**

**Status:** Ready for implementation after user approval
**Next Step:** Proceed to Task #12 (implementation)
