Files
storybook/design/year-long-schedule-system.md
Sienna Meridian Satterwhite 16deb5d237 release: Storybook v0.2.0 - Major syntax and features update
BREAKING CHANGES:
- Relationship syntax now requires blocks for all participants
- Removed self/other perspective blocks from relationships
- Replaced 'guard' keyword with 'if' for behavior tree decorators

Language Features:
- Add tree-sitter grammar with improved if/condition disambiguation
- Add comprehensive tutorial and reference documentation
- Add SBIR v0.2.0 binary format specification
- Add resource linking system for behaviors and schedules
- Add year-long schedule patterns (day, season, recurrence)
- Add behavior tree enhancements (named nodes, decorators)

Documentation:
- Complete tutorial series (9 chapters) with baker family examples
- Complete reference documentation for all language features
- SBIR v0.2.0 specification with binary format details
- Added locations and institutions documentation

Examples:
- Convert all examples to baker family scenario
- Add comprehensive working examples

Tooling:
- Zed extension with LSP integration
- Tree-sitter grammar for syntax highlighting
- Build scripts and development tools

Version Updates:
- Main package: 0.1.0 → 0.2.0
- Tree-sitter grammar: 0.1.0 → 0.2.0
- Zed extension: 0.1.0 → 0.2.0
- Storybook editor: 0.1.0 → 0.2.0
2026-02-13 21:52:03 +00:00

26 KiB

Year-Long Composable Schedule System Design

Author: Resource Linking Architect (Schedule System Designer) Date: 2026-02-12 Status: Draft for Review Version: 0.1 Related: Resource Linking System Design (Task #8)


Executive Summary

This document proposes a year-long, composable schedule system for the Storybook DSL that extends the current simple daily schedules to support:

  • Temporal composition: Days → Weeks → Months → Seasons → Year
  • Template inheritance: Schedules extend and override like behavior templates
  • Seasonal variations: Winter/summer hours, holiday schedules
  • Event overrides: Special occasions, one-off modifications
  • Integration with resource linking: Works seamlessly with uses schedule: syntax

The design enables both simple daily routines and complex year-long patterns while maintaining readability and composability.


1. Current State & Limitations

1.1 Existing Schedule Syntax

Current (Simple Daily Schedule):

schedule MadTeaPartyRotation {
    18:00 -> 18:01: TeaRound {
        ---narrative
        Begin a new rotation...
        ---
    }
    18:01 -> 18:02: RiddlePhase { ... }
    18:02 -> 18:03: ContradictionPhase { ... }
}

Current AST:

pub struct Schedule {
    pub name: String,
    pub blocks: Vec<ScheduleBlock>,  // Flat list
    pub span: Span,
}

pub struct ScheduleBlock {
    pub start: Time,      // HH:MM
    pub end: Time,        // HH:MM
    pub activity: String,
    pub fields: Vec<Field>,
    pub span: Span,
}

1.2 Limitations

  1. No composition: Can't build a weekly schedule from daily templates
  2. No inheritance: Can't extend a base schedule and customize
  3. No temporal hierarchy: Can't express "weekday vs weekend" patterns
  4. No seasonal variation: Can't say "summer hours vs winter hours"
  5. No override system: Can't modify specific blocks while keeping others
  6. No year-long support: Limited to repeating daily patterns

1.3 Use Cases Not Supported

Use Case 1: Seasonal Business Hours

Bakery is open 6:00-20:00 in summer, 7:00-18:00 in winter

Use Case 2: Weekday vs Weekend

Martha works Monday-Friday, rests Saturday-Sunday

Use Case 3: Holiday Override

Martha follows BakerSchedule normally, but FullRest on Christmas

Use Case 4: Life Arc Changes

Martha's schedule changes when she becomes Elder (retires)

2. Design Goals

2.1 Primary Goals

  1. Hierarchical Composition: Build complex schedules from simple parts
  2. Template Inheritance: Extend and customize like behavior templates
  3. Temporal Flexibility: Express daily, weekly, seasonal, yearly patterns
  4. Override System: Modify specific aspects while keeping others
  5. Backward Compatible: Current simple schedules still work
  6. Integration: Seamless with uses schedule: linking

2.2 Non-Goals

  1. Real-time scheduling: Schedules are static patterns, not dynamic
  2. Calendar systems: Focus on patterns, not specific date handling
  3. Time zones: All times are game-world local
  4. Procedural generation: Schedules are authored, not generated

3. Proposed Architecture

3.1 Time Hierarchy (yes, but i want to make this user-composable so they're not locked into gregorian, euro-centric calendars. idk how we would do that, but like Lonni wants 8 seasons... maybe the schedule constants (years/months/days/weeks/seasons/etc) can be configured in the storybook.toml? idk how to handle this)

Year (365 days)
├─ Season (Winter, Spring, Summer, Fall)
│   └─ Month (Jan, Feb, ..., Dec)
│       └─ Week (7-day cycle)
│           └─ Day (24-hour period)
│               └─ Block (time range + activity)

3.2 Schedule Types

Daily Schedule - Single 24-hour pattern:

schedule SimpleDay {
    block sleep { 0:00 - 6:00, activity: sleep }
    block work { 9:00 - 17:00, activity: work }
    block leisure { 17:00 - 22:00, activity: leisure }
    block sleep { 22:00 - 24:00, activity: sleep }
}

Weekly Schedule - 7-day pattern with day variations:

schedule WorkWeek {
    weekday (mon, tue, wed, thu, fri) {
        block work { 9:00 - 17:00, activity: work }
        block leisure { 17:00 - 22:00, activity: leisure }
    }

    weekend (sat, sun) {
        block leisure { 10:00 - 22:00, activity: leisure }
    }
}

Seasonal Schedule - Patterns that change by season:

schedule BakeryHours {
    season summer {
        block open { 6:00 - 20:00, activity: work }
    }

    season winter {
        block open { 7:00 - 18:00, activity: work }
    }
}

Yearly Schedule - Full year with events and overrides:

schedule AnnualPattern extends WorkWeek {
    event Christmas on Dec 25 {
        block rest { 0:00 - 24:00, activity: rest }
    }

    event NewYear on Jan 1 {
        block celebration { 0:00 - 24:00, activity: celebrate }
    }
}

4. Composition System (i just want override support, we can yank remove and append and remove all, but extends is good)

4.1 Template Inheritance with extends

Base Schedule:

schedule BaseWorkday {
    block sleep { 0:00 - 6:00, activity: sleep }
    block work { 9:00 - 17:00, activity: work }
    block leisure { 17:00 - 22:00, activity: leisure }
    block sleep { 22:00 - 24:00, activity: sleep }
}

Extended Schedule:

schedule BakerSchedule extends BaseWorkday {
    override work { 5:00 - 13:00 }  // Earlier hours
    append baking { 3:00 - 5:00, activity: prepare }
}

Result:

Block baking: 3:00 - 5:00 (prepare)
Block work: 5:00 - 13:00 (work)       ← overridden
Block leisure: 17:00 - 22:00 (leisure) ← inherited
Block sleep: 22:00 - 24:00 + 0:00 - 6:00 (sleep) ← inherited

4.2 Override Operators

override <block> { fields } - Replace specific block properties:

schedule BakerSchedule extends BaseWorkday {
    override work {
        time: 5:00 - 13:00,
        location: Bakery
    }
}

remove <block> - Delete inherited block:

schedule RetiredSchedule extends BaseWorkday {
    remove work  // No more work!
}

append <block> { fields } - Add new block:

schedule ExtendedDay extends BaseWorkday {
    append meditation { 5:00 - 5:30, activity: meditate }
}

replace all - Complete replacement (no inheritance):

schedule FullRest {
    replace all
    block rest { 0:00 - 24:00, activity: rest }
}

4.3 Multi-Level Inheritance

schedule Base {
    block work { 9:00 - 17:00, activity: work }
}

schedule WorkerSchedule extends Base {
    override work { 8:00 - 16:00 }
}

schedule SeniorWorkerSchedule extends WorkerSchedule {
    override work { 9:00 - 15:00 }  // Shorter hours
}

// Result: work is 9:00 - 15:00 (SeniorWorker's version wins)

Merge Rules (Same as Behavior Linking):

  • Character schedules override template schedules by block name
  • Most specific schedule wins
  • Concatenation + override-by-name

5. Temporal Patterns

5.1 Day-of-Week Patterns (not activity but action or behavior references)

Simple Weekday/Weekend Split:

schedule WorkWeek {
    weekday (mon, tue, wed, thu, fri) extends BaseWorkday {
        // Monday-Friday use BaseWorkday
    }

    weekend (sat, sun) {
        block leisure { 8:00 - 22:00, activity: leisure }
        block sleep { 22:00 - 8:00, activity: sleep }
    }
}

Day-Specific Customization:

schedule DetailedWeek {
    on monday extends WorkdaySchedule {
        append meeting { 9:00 - 10:00, activity: meeting }
    }

    on friday extends WorkdaySchedule {
        override work { 9:00 - 15:00 }  // Early finish!
    }

    on saturday {
        block market { 8:00 - 12:00, activity: shopping }
        block leisure { 12:00 - 22:00, activity: leisure }
    }

    on sunday {
        block church { 10:00 - 11:00, activity: worship }
        block family { 11:00 - 18:00, activity: social }
    }
}

5.2 Seasonal Patterns

Basic Seasonal Split:

schedule SeasonalWork {
    season (spring, summer) {
        block work { 6:00 - 14:00, activity: outdoor_work }
    }

    season (fall, winter) {
        block work { 8:00 - 16:00, activity: indoor_work }
    }
}

Season-Specific Schedules:

schedule FarmerSchedule {
    season spring {
        on weekday { block planting { 5:00 - 18:00, activity: plant } }
    }

    season summer {
        on weekday { block tending { 6:00 - 16:00, activity: tend } }
    }

    season fall {
        on weekday { block harvest { 5:00 - 19:00, activity: harvest } }
    }

    season winter {
        on weekday { block planning { 9:00 - 15:00, activity: plan } }
    }
}

5.3 Event Overrides (event is interesting)

Holiday Definitions:

schedule AnnualSchedule extends WorkWeek {
    event Christmas on Dec 25 {
        block family { 0:00 - 24:00, activity: family_time }
    }

    event NewYear on Jan 1 {
        block celebration { 0:00 - 24:00, activity: celebrate }
    }

    event Birthday on Jun 15 {
        block party { 18:00 - 22:00, activity: celebrate }
    }
}

Recurring Events: (hmmmmmmmmmm sell me on this one.)

schedule MarketSchedule extends BaseSchedule {
    every saturday {
        block market { 8:00 - 13:00, activity: sell_at_market }
    }

    every first_monday_of_month {
        block guild_meeting { 19:00 - 21:00, activity: meeting }
    }
}

6. AST Design

6.1 Extended Schedule Structure

// In src/syntax/ast.rs

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

#[derive(Debug, Clone, PartialEq)]
pub enum ScheduleItem {
    Block(ScheduleBlock),                 // Direct block definition
    Override(ScheduleOverride),           // override block_name { ... }
    Remove(String),                       // remove block_name
    Append(ScheduleBlock),                // append new_block { ... }
    ReplaceAll,                           // replace all
    WeekdayPattern(WeekdayPattern),       // weekday (...) { ... }
    DayPattern(DayPattern),               // on monday { ... }
    SeasonPattern(SeasonPattern),         // season summer { ... }
    EventPattern(EventPattern),           // event Name on Date { ... }
}

#[derive(Debug, Clone, PartialEq)]
pub struct ScheduleBlock {
    pub name: Option<String>,             // Optional block name
    pub start: Time,
    pub end: Time,
    pub activity: String,
    pub fields: Vec<Field>,
    pub span: Span,
}

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

#[derive(Debug, Clone, PartialEq)]
pub struct WeekdayPattern {
    pub days: Vec<DayOfWeek>,             // [mon, tue, wed]
    pub extends: Option<Vec<String>>,     // Optional base schedule
    pub blocks: Vec<ScheduleBlock>,
    pub span: Span,
}

#[derive(Debug, Clone, PartialEq)]
pub struct DayPattern {
    pub day: DayOfWeek,                   // monday
    pub extends: Option<Vec<String>>,
    pub blocks: Vec<ScheduleBlock>,
    pub span: Span,
}

#[derive(Debug, Clone, PartialEq)]
pub struct SeasonPattern {
    pub seasons: Vec<Season>,             // [spring, summer]
    pub blocks: Vec<ScheduleBlock>,
    pub span: Span,
}

#[derive(Debug, Clone, PartialEq)]
pub struct EventPattern {
    pub name: String,                     // "Christmas"
    pub date: DateSpec,                   // Dec 25 or every saturday
    pub blocks: Vec<ScheduleBlock>,
    pub span: Span,
}

#[derive(Debug, Clone, PartialEq)]
pub enum DayOfWeek {
    Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday,
}

#[derive(Debug, Clone, PartialEq)]
pub enum Season {
    Spring, Summer, Fall, Winter,
}

#[derive(Debug, Clone, PartialEq)]
pub enum DateSpec {
    SpecificDate { month: u8, day: u8 },  // Dec 25
    Recurring(RecurringPattern),          // every saturday
}

#[derive(Debug, Clone, PartialEq)]
pub enum RecurringPattern {
    EveryWeekday(DayOfWeek),              // every saturday
    FirstDayOfMonth(DayOfWeek),           // first monday of month
    LastDayOfMonth(DayOfWeek),            // last friday of month
}

7. Grammar Design (LALRPOP)

7.1 Schedule Productions

// In parser.lalrpop

pub Schedule: Schedule = {
    "schedule" <name:Ident> <extends:ExtendsClause?> "{"
        <items:ScheduleItem*>
    "}" => Schedule { name, extends, items, span }
};

ExtendsClause: Vec<String> = {
    "extends" <QualifiedPath>
};

ScheduleItem: ScheduleItem = {
    <ScheduleBlock> => ScheduleItem::Block(<>),
    <ScheduleOverride> => ScheduleItem::Override(<>),
    <RemoveStmt> => ScheduleItem::Remove(<>),
    <AppendStmt> => ScheduleItem::Append(<>),
    <ReplaceAllStmt> => ScheduleItem::ReplaceAll,
    <WeekdayPattern> => ScheduleItem::WeekdayPattern(<>),
    <DayPattern> => ScheduleItem::DayPattern(<>),
    <SeasonPattern> => ScheduleItem::SeasonPattern(<>),
    <EventPattern> => ScheduleItem::EventPattern(<>),
};

// Basic block: 9:00 - 17:00: Work { activity: work }
ScheduleBlock: ScheduleBlock = {
    <start:Time> "-" <end:Time> ":" <name:Ident?> "{"
        <fields:Field*>
    "}" => ScheduleBlock { name, start, end, fields, span }
};

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

// Remove: remove block_name
RemoveStmt: String = {
    "remove" <Ident>
};

// Append: append new_block { 5:00 - 6:00, activity: meditate }
AppendStmt: ScheduleBlock = {
    "append" <ScheduleBlock>
};

// Replace all blocks
ReplaceAllStmt = {
    "replace" "all"
};

// Weekday pattern: weekday (mon, tue, wed) { blocks }
WeekdayPattern: WeekdayPattern = {
    "weekday" "(" <days:Comma<DayOfWeek>> ")" <extends:ExtendsClause?> "{"
        <blocks:ScheduleBlock*>
    "}" => WeekdayPattern { days, extends, blocks, span }
};

// Day pattern: on monday { blocks }
DayPattern: DayPattern = {
    "on" <day:DayOfWeek> <extends:ExtendsClause?> "{"
        <blocks:ScheduleBlock*>
    "}" => DayPattern { day, extends, blocks, span }
};

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

// Event pattern: event Christmas on Dec 25 { blocks }
EventPattern: EventPattern = {
    "event" <name:Ident> "on" <date:DateSpec> "{"
        <blocks:ScheduleBlock*>
    "}" => EventPattern { name, date, blocks, span }
};

DayOfWeek: DayOfWeek = {
    "monday" => DayOfWeek::Monday,
    "tuesday" => DayOfWeek::Tuesday,
    "wednesday" => DayOfWeek::Wednesday,
    "thursday" => DayOfWeek::Thursday,
    "friday" => DayOfWeek::Friday,
    "saturday" => DayOfWeek::Saturday,
    "sunday" => DayOfWeek::Sunday,
    "mon" => DayOfWeek::Monday,  // Short forms
    "tue" => DayOfWeek::Tuesday,
    "wed" => DayOfWeek::Wednesday,
    "thu" => DayOfWeek::Thursday,
    "fri" => DayOfWeek::Friday,
    "sat" => DayOfWeek::Saturday,
    "sun" => DayOfWeek::Sunday,
};

Season: Season = {
    "spring" => Season::Spring,
    "summer" => Season::Summer,
    "fall" => Season::Fall,
    "winter" => Season::Winter,
};

DateSpec: DateSpec = {
    <month:Month> <day:Integer> => DateSpec::SpecificDate { month, day },
    "every" <DayOfWeek> => DateSpec::Recurring(RecurringPattern::EveryWeekday(<>)),
    "every" "first" <DayOfWeek> "of" "month" =>
        DateSpec::Recurring(RecurringPattern::FirstDayOfMonth(<>)),
};

8. Resolution & Merging

8.1 Schedule Merge Algorithm

Same as Behavior Merging:

  1. Resolve extends reference to base schedule
  2. Collect base schedule's blocks
  3. Apply overrides/removes/appends from extending schedule
  4. Override by block name (not by time)
  5. Handle multi-level inheritance recursively
fn merge_schedules(
    child: &Schedule,
    parent: &Schedule,
) -> ResolvedSchedule {
    let mut blocks = HashMap::new();

    // Step 1: Add parent blocks
    for block in &parent.blocks {
        if let Some(name) = &block.name {
            blocks.insert(name.clone(), block.clone());
        }
    }

    // Step 2: Apply child modifications
    for item in &child.items {
        match item {
            ScheduleItem::Block(block) => {
                if let Some(name) = &block.name {
                    blocks.insert(name.clone(), block.clone());
                }
            }
            ScheduleItem::Override(ovr) => {
                if let Some(block) = blocks.get_mut(&ovr.block_name) {
                    apply_override(block, ovr);
                }
            }
            ScheduleItem::Remove(name) => {
                blocks.remove(name);
            }
            ScheduleItem::ReplaceAll => {
                blocks.clear();
            }
            // ... handle patterns
        }
    }

    ResolvedSchedule { blocks: blocks.into_values().collect() }
}

8.2 Pattern Resolution

Weekday Patterns expand to 7 day-specific schedules: (we have to account for user-defined story constants)

weekday (mon, tue, wed, thu, fri) {
    block work { 9:00 - 17:00 }
}

// Expands to:
// monday: { work { 9:00 - 17:00 } }
// tuesday: { work { 9:00 - 17:00 } }
// ...

Season Patterns apply conditionally at runtime based on current season.

Event Patterns override specific days when event matches.


9. Integration with Resource Linking

9.1 Simple Case

schedule BakerSchedule {
    block work { 5:00 - 13:00, activity: work }
    block lunch { 13:00 - 14:00, activity: eat }
    block rest { 14:00 - 22:00, activity: rest }
}

character Martha: Human {
    uses schedule: BakerSchedule
}

9.2 Conditional Schedule Linking

schedule WorkdaySchedule {
    block work { 9:00 - 17:00, activity: work }
}

schedule WeekendSchedule {
    block leisure { 10:00 - 22:00, activity: leisure }
}

character Martha: Human {
    uses schedules: [
        { schedule: WorkdaySchedule, when: day_of_week is weekday } (hmmmm i like this but we need to scope how we handle abstract constructs like `day_of_week` because that's arbitrary)
        { schedule: WeekendSchedule, when: day_of_week is weekend }
    ]
}

9.3 Seasonal Schedules

schedule SummerHours {
    block open { 6:00 - 20:00, activity: work }
}

schedule WinterHours {
    block open { 7:00 - 18:00, activity: work }
}

institution Bakery {
    uses schedules: [
        { schedule: SummerHours, when: season == summer } (we have to figure out how to define seasons)
        { schedule: WinterHours, when: season == winter }
    ]
}

10. Examples

Example 1: Simple Daily Schedule (Backward Compatible)

schedule SimpleDay {
    block sleep { 0:00 - 6:00, activity: sleep }
    block work { 9:00 - 17:00, activity: work }
    block leisure { 17:00 - 22:00, activity: leisure }
    block sleep { 22:00 - 24:00, activity: sleep }
}

Example 2: Schedule with Override

schedule BaseWorkday {
    block sleep { 0:00 - 6:00, activity: sleep }
    block work { 9:00 - 17:00, activity: work }
    block leisure { 17:00 - 22:00, activity: leisure }
    block sleep { 22:00 - 24:00, activity: sleep }
}

schedule BakerSchedule extends BaseWorkday {
    override work { time: 5:00 - 13:00, location: Bakery }
    append prep { time: 3:00 - 5:00, activity: bake_prep }
}

Example 3: Weekly Pattern

schedule WorkWeek {
    weekday (mon, tue, wed, thu, fri) {
        block work { 9:00 - 17:00, activity: work }
        block leisure { 17:00 - 22:00, activity: leisure }
    }

    weekend (sat, sun) {
        block leisure { 10:00 - 22:00, activity: leisure }
    }
}

Example 4: Seasonal Business Hours

schedule BakeryHours {
    season (spring, summer) {
        block open { 6:00 - 20:00, activity: serve_customers }
        block prep { 4:00 - 6:00, activity: bake_bread }
    }

    season (fall, winter) {
        block open { 7:00 - 18:00, activity: serve_customers }
        block prep { 5:00 - 7:00, activity: bake_bread }
    }
}

Example 5: Full Year with Events

schedule AnnualSchedule extends WorkWeek {
    event Christmas on Dec 25 {
        block family { 0:00 - 24:00, activity: family_time }
    }

    event NewYear on Jan 1 {
        block celebration { 0:00 - 24:00, activity: celebrate }
    }

    every saturday {
        block market { 8:00 - 12:00, activity: sell_at_market }
    }
}

Example 6: Complex Multi-Level Inheritance

schedule BaseHuman {
    block sleep { 0:00 - 6:00, activity: sleep }
    block breakfast { 6:00 - 7:00, activity: eat }
    block dinner { 18:00 - 19:00, activity: eat }
    block sleep { 22:00 - 24:00, activity: sleep }
}

schedule Worker extends BaseHuman {
    block work { 9:00 - 17:00, activity: work }
}

schedule Baker extends Worker {
    override work { time: 5:00 - 13:00, location: Bakery }
    override breakfast { time: 13:30 - 14:00 }  // Late breakfast
    append prep { time: 3:00 - 5:00, activity: bake }
}

schedule RetiredBaker extends BaseHuman {
    // No work, just keep eating/sleeping schedule
    append hobby { time: 10:00 - 16:00, activity: hobby }
}

11. SBIR Representation

11.1 SCHEDULES Section Extension

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

Schedule:
  - name: String
  - parent_schedule_id: Option<u32>     // extends reference
  - blocks: [ScheduleBlock...]
  - patterns: [SchedulePattern...]      // weekday, season, event

ScheduleBlock:
  - name: Option<String>
  - start: Time (u16 minutes since midnight)
  - end: Time (u16 minutes since midnight)
  - activity: String
  - fields: Map<String, Value>

SchedulePattern:
  - kind: PatternKind (Weekday, Season, Event)
  - specification: bytes (encoded pattern details)
  - blocks: [ScheduleBlock...]

PatternKind:
  - Weekday(days: [DayOfWeek])
  - Season(seasons: [Season])
  - Event(date: DateSpec)

11.2 Runtime Evaluation

At runtime, the engine:

  1. Resolves character's schedule links (conditional selection)
  2. Merges inherited schedules
  3. Evaluates patterns for current day/season
  4. Produces final 24-hour schedule for today

Example Flow:

Character Martha uses BakerSchedule
  ↓
BakerSchedule extends BaseWorkday
  ↓
Merge: BaseWorkday blocks + Baker overrides
  ↓
Result: Martha's schedule for today

12. Implementation Plan

Phase 1: AST Extension (Week 1)

  1. Add extended Schedule struct with extends and items
  2. Add ScheduleItem enum (Block, Override, Remove, etc.)
  3. Add pattern types (WeekdayPattern, SeasonPattern, EventPattern)
  4. Add DayOfWeek, Season, DateSpec enums
  5. Update existing ScheduleBlock to support optional names

Phase 2: Parser Implementation (Week 1-2)

  1. Implement extends clause parsing
  2. Implement override/remove/append operators
  3. Implement weekday/day patterns
  4. Implement season patterns
  5. Implement event patterns
  6. Write parser tests for all patterns

Phase 3: Resolution & Merging (Week 2)

  1. Implement schedule inheritance resolution
  2. Implement merge algorithm (same as behavior merging)
  3. Implement pattern expansion
  4. Implement multi-level inheritance
  5. Write resolution tests

Phase 4: 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

Phase 5: Documentation & Examples (Week 3)

  1. Update language documentation
  2. Create comprehensive schedule examples
  3. Update Alice in Wonderland example with patterns
  4. Create migration guide

Total Estimate: 3 weeks


13. Open Questions

Question 1: Block Naming (yes)

Should all blocks require names?

Current: Blocks can be anonymous Proposed: Blocks need names for override system

Recommendation: Require names for override-ability

Question 2: Time Overlap Detection (ummmmmmm... yeah prolly.)

Should parser/validator detect time overlaps?

schedule Broken {
    block work { 9:00 - 17:00 }
    block lunch { 12:00 - 13:00 }  // Overlaps with work!
}

Recommendation: Warning (not error) for overlaps

Question 3: Default Block Duration (must throw an error)

What if user writes just block lunch?

Option A: Error (must specify time) Option B: Default duration (e.g., 1 hour)

Recommendation: Option A (explicit is better)

Question 4: Seasonal Calendar (configurable per world)

Which calendar system?

Option A: Simple 4 seasons (Spring, Summer, Fall, Winter) Option B: Month-specific (Jan is winter, etc.) Option C: Configurable per world

Recommendation: Option A, with Option C as future extension


14. Success Criteria

Must Have

  • Backward compatible with current simple schedules
  • Template inheritance with extends
  • Override/remove/append operators
  • Weekday patterns (weekday/weekend)
  • Day-specific patterns (on monday)
  • Seasonal patterns
  • Event overrides
  • Integration with uses schedule: linking
  • Multi-level inheritance
  • Merge algorithm defined
  • SBIR representation specified

Should Have

  • Recurring event patterns (every saturday)
  • Time overlap warnings
  • Pattern validation
  • Comprehensive examples
  • Runtime evaluation algorithm

Nice to Have

  • Calendar abstraction for different worlds
  • Behavior references in schedule blocks
  • Visual schedule editor design
  • Performance optimization for large schedules

15. Comparison with Behavior Linking

Aspect Behavior Linking Schedule Linking
Inheritance from Template extends Base
Merge Rule Concatenation + override by name Same
Override Character's behavior replaces template's Child's block replaces parent's
Selection Priority + conditions Temporal + conditions
Multi-level Supported Supported
Empty Array Inherit all Inherit all

Design Principle: Keep schedule composition consistent with behavior composition for user familiarity.


End of Design Document

Next Step: Review and approval before implementation (Task #12).