Files
storybook/design/resource-linking-checkpoint2-addendum.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

659 lines
18 KiB
Markdown

# Resource Linking System - Checkpoint 2 Addendum
**Author:** Resource Linking Architect
**Date:** 2026-02-12
**Status:** Draft for Checkpoint 2 Review
**Version:** 0.3
**Addresses:** Checkpoint 1 feedback from Sienna
---
## Changes from Checkpoint 1
This addendum addresses two required changes from Sienna's Checkpoint 1 review:
1. **Template Merging Support** (instead of all-or-nothing replacement)
2. **Dual Operator Support** (`==` and `is` both work)
---
## 1. Template Merging Design
### 1.1 The Problem
**Original Design (Rejected):**
```storybook
template Worker {
uses behaviors: [HandleBasicNeeds, RestWhenTired]
}
character Martha: Human from Worker {
uses behaviors: [BakeryWork] // REPLACES Worker behaviors entirely
}
// Result: Only [BakeryWork] - lost HandleBasicNeeds and RestWhenTired
```
**Requested Behavior:**
Martha should get BOTH Worker behaviors AND her own behaviors, composed together.
### 1.2 Proposed Merge Algorithm
**Merge Semantics:**
- Template links and character links are **concatenated**
- Character links come **first** (evaluated before template links) (no template links come first since that's the "base class")
- If same behavior appears in both, character's version **overrides** template's version
- Priority and conditions are preserved from each source
**Example:**
```storybook
template Worker {
uses behaviors: [
{ tree: HandleBasicNeeds, priority: critical }
{ tree: RestWhenTired, priority: normal }
{ tree: Idle, priority: low }
]
}
character Martha: Human from Worker {
uses behaviors: [
{ tree: BakeryWork, priority: normal }
{ tree: Idle, priority: normal } // Overrides Worker's Idle
]
}
// Merged result:
// [
// { tree: BakeryWork, priority: normal } // From Martha
// { tree: Idle, priority: normal } // From Martha (overrides template)
// { tree: HandleBasicNeeds, priority: critical } // From Worker
// { tree: RestWhenTired, priority: normal } // From Worker
// ]
```
### 1.3 Merge Rules
**Rule 1: Concatenation**
- Merge = `character_links ++ template_links`
- Character links are evaluated first at runtime (higher precedence)
**Rule 2: Override by Name**
- If character defines a link to behavior `X`, template's link to `X` is ignored
- Match by behavior tree name (not by priority or condition)
- Allows character to "replace" template's version of a behavior
**Rule 3: Preserve Priority**
- Priority values are NOT automatically adjusted
- Character can define same behavior with different priority than template
- Runtime selection uses declared priorities as-is
**Rule 4: Preserve Conditions**
- Conditions are NOT merged with boolean operators
- Each link keeps its own condition
- If both have same behavior with different conditions, character's wins (override)
**Rule 5: Default Behavior**
- If both character and template define `default: true` for same link type, character's default wins
- Warning issued if both define defaults (even for different behaviors)
### 1.4 Conflict Resolution
**Conflict Type 1: Same Behavior, Different Priority**
```storybook
template Worker {
uses behaviors: [
{ tree: Rest, priority: high }
]
}
character Martha: Human from Worker {
uses behaviors: [
{ tree: Rest, priority: normal } // Character overrides
]
}
// Result: Martha's Rest(normal) wins, template's Rest(high) ignored
```
**Conflict Type 2: Same Behavior, Different Conditions**
```storybook
template Worker {
uses behaviors: [
{ tree: Work, when: employed }
]
}
character Martha: Human from Worker {
uses behaviors: [
{ tree: Work, when: at_bakery } // Character overrides
]
}
// Result: Martha's Work(when: at_bakery) wins
```
**Conflict Type 3: Multiple Defaults**
```storybook
template Worker {
uses behaviors: [
{ tree: Idle, default: true }
]
}
character Martha: Human from Worker {
uses behaviors: [
{ tree: Rest, default: true } // Warning!
]
}
// Warning: Both template and character define default behaviors
// Resolution: Character's default wins (Rest), template's Idle kept but not default
```
### 1.5 Multi-Level Template Inheritance
Templates can inherit from templates:
```storybook
template LivingBeing {
uses behaviors: [
{ tree: Breathe, priority: critical }
{ tree: Eat, priority: high }
]
}
template Worker from LivingBeing {
uses behaviors: [
{ tree: Work, priority: normal }
{ tree: Rest, priority: normal }
]
}
character Martha: Human from Worker {
uses behaviors: [
{ tree: BakeryWork, priority: normal }
]
}
// Merge chain: LivingBeing -> Worker -> Martha
// Result (in evaluation order):
// [
// BakeryWork(normal), // Martha
// Work(normal), // Worker
// Rest(normal), // Worker
// Breathe(critical), // LivingBeing
// Eat(high) // LivingBeing
// ]
```
**Merge Algorithm for Multi-Level:**
1. Start with deepest template (LivingBeing)
2. Merge next template (Worker) on top
3. Merge character on top
4. At each level, apply override-by-name rule
### 1.6 Explicit Override Syntax (Future Extension)
If we want more control, we could add explicit `override` keyword:
```storybook
character Martha: Human from Worker {
uses behaviors: [
{ tree: Rest, priority: low, override: true } // Explicit override
{ tree: BakeryWork, priority: normal }
]
}
```
**Recommendation:** Start without `override` keyword. Add later if needed.
### 1.7 Empty Array Semantics
**Question:** What if character defines empty array?
```storybook
template Worker {
uses behaviors: [HandleBasicNeeds, Rest]
}
character Martha: Human from Worker {
uses behaviors: [] // Empty!
}
```
**Option A:** Empty array means "use no behaviors" (clear template behaviors)
**Option B:** Empty array is treated as "not defined", inherit from template
**Recommendation:** **Option B** - Only non-empty arrays trigger override/merge. Empty arrays are same as omitted field. (empty array just means "empty array", i think if it's a zero-length array then we would treat it as "not defined")
### 1.8 Updated Merge Pseudocode
```rust
fn merge_behavior_links(
character_links: Vec<BehaviorLink>,
template_links: Vec<BehaviorLink>
) -> Vec<BehaviorLink> {
let mut result = Vec::new();
let mut seen_behaviors = HashSet::new();
// Add character links first (higher precedence)
for link in character_links {
let behavior_name = link.tree.join("::");
seen_behaviors.insert(behavior_name.clone());
result.push(link);
}
// Add template links that don't conflict
for link in template_links {
let behavior_name = link.tree.join("::");
if !seen_behaviors.contains(&behavior_name) {
result.push(link);
}
// else: skip, character already defined this behavior
}
result
}
fn merge_character_with_template(
char: Character,
template: Template
) -> ResolvedCharacter {
// Recursively merge if template has parent template
let template_links = if let Some(parent_template) = template.parent {
merge_behavior_links(template.behavior_links, parent_template.behavior_links)
} else {
template.behavior_links
};
// Merge character on top of (potentially already merged) template
let behavior_links = if !char.behavior_links.is_empty() {
merge_behavior_links(char.behavior_links, template_links)
} else {
template_links // Character doesn't define any, inherit all
};
// Same logic for schedule_links...
ResolvedCharacter { behavior_links, schedule_links, ... }
}
```
### 1.9 Validation Rules
**New Validations:**
1. **Warn on default conflicts:**
```
warning: multiple default behaviors defined
┌─ characters/martha.sb:8:5
8 │ uses behaviors: [
9 │ { tree: Rest, default: true }
= note: template 'Worker' also defines a default behavior: Idle
= help: only one default is used at runtime (character's takes precedence)
```
2. **Warn on priority conflicts (optional):**
```
warning: behavior priority changed from template
┌─ characters/martha.sb:9:9
9 │ { tree: Rest, priority: low }
= note: template 'Worker' defines Rest with priority: high
= help: character's priority (low) will override template's (high)
```
### 1.10 Examples
**Example 1: Simple Composition**
```storybook
template Villager {
uses behaviors: [
{ tree: BasicNeeds, priority: critical }
{ tree: Socialize, priority: normal }
{ tree: Sleep, priority: normal }
]
}
character Martha: Human from Villager {
uses behaviors: [
{ tree: BakeryWork, priority: normal }
]
}
// Martha gets: [BakeryWork, BasicNeeds, Socialize, Sleep]
```
**Example 2: Selective Override**
```storybook
template Villager {
uses behaviors: [
{ tree: BasicNeeds, priority: critical }
{ tree: Sleep, priority: normal }
]
uses schedule: VillagerSchedule
}
character Martha: Human from Villager {
uses behaviors: [
{ tree: Sleep, priority: low } // Override just Sleep
]
uses schedule: BakerSchedule // Override schedule
}
// Behaviors: [Sleep(low), BasicNeeds(critical)]
// Schedule: BakerSchedule (replaces VillagerSchedule)
```
**Example 3: Multi-Level Inheritance**
```storybook
template Mortal {
uses behaviors: [{ tree: Age, priority: critical }]
}
template Worker from Mortal {
uses behaviors: [{ tree: Work, priority: normal }]
}
template Baker from Worker {
uses behaviors: [{ tree: BakeBreed, priority: normal }]
}
character Martha: Human from Baker {
uses behaviors: [{ tree: ManageBakery, priority: normal }]
}
// Result: [ManageBakery, BakeBread, Work, Age]
```
---
## 2. Dual Operator Support (`==` and `is`)
### 2.1 The Request
Sienna wants both `==` and `is` to work for equality comparisons (like Python).
**Examples:**
```storybook
uses behaviors: [
{ tree: Giant, when: current_size == huge } // C-style
{ tree: Tiny, when: current_size is tiny } // Python-style
]
```
### 2.2 Semantic Equivalence
Both operators mean **equality test**:
- `current_size == huge` → true if current_size equals huge
- `current_size is tiny` → true if current_size equals tiny
- No distinction between "identity" and "equality" (like Python's `is` vs `==`)
- They're syntactic alternatives for readability
### 2.3 Grammar Update
```lalrpop
// In parser.lalrpop
CompOp: CompOp = {
">=" => CompOp::Gte,
"<=" => CompOp::Lte,
"==" => CompOp::Eq,
"is" => CompOp::Eq, // NEW - maps to same enum variant
"!=" => CompOp::Neq,
">" => CompOp::Gt,
"<" => CompOp::Lt,
};
```
**AST Representation:**
```rust
pub enum CompOp {
Eq, // Both == and is map to this
Neq,
Lt,
Gt,
Lte,
Gte,
}
```
No AST change needed - both `==` and `is` produce the same `CompOp::Eq`.
### 2.4 Negation
**Question:** Should we support `is not` as well as `!=`? (yes i want this)
```storybook
when: current_size is not huge // Python style
when: current_size != huge // C style
```
**Recommendation:** **Yes**, support `is not` for consistency with Python:
```lalrpop
CompOp: CompOp = {
">=" => CompOp::Gte,
"<=" => CompOp::Lte,
"==" => CompOp::Eq,
"is" => CompOp::Eq,
"is" "not" => CompOp::Neq, // NEW
"!=" => CompOp::Neq,
">" => CompOp::Gt,
"<" => CompOp::Lt,
};
```
### 2.5 Updated Examples
**All valid:**
```storybook
uses behaviors: [
{ tree: Giant, when: size == huge }
{ tree: Giant, when: size is huge }
{ tree: Tiny, when: size != tiny }
{ tree: Tiny, when: size is not tiny }
]
```
### 2.6 Documentation Update
Update language docs to show both styles:
> **Condition Expressions**
>
> Use `when:` clauses to specify conditions for link selection:
>
> ```storybook
> when: emotional_state == frightened // C-style equality
> when: emotional_state is frightened // Python-style equality
> when: size != normal // C-style inequality
> when: size is not normal // Python-style inequality
> ```
>
> Both `==` and `is` mean equality. Both `!=` and `is not` mean inequality.
> Choose whichever reads more naturally for your condition.
---
## 3. Updated Implementation Plan
### Phase 1: AST Extension (Week 1) - UNCHANGED
No changes from original design.
### Phase 2: Parser Implementation (Week 1-2) - UPDATED
**Original:**
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
**Updated:**
1. Implement `BehaviorLinkStmt` and `ScheduleLinkStmt` grammar
2. Implement `BehaviorLinkSpec` and `ScheduleLinkSpec` parsing
3. Add link parsing to character, institution, template productions
4. **Add `is` and `is not` to `CompOp` production** ← NEW
5. Write parser tests for all link variations
6. **Write tests for both `==`/`is` and `!=`/`is not`** ← NEW
### Phase 3: Resolution (Week 2) - UPDATED
**Original:**
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
**Updated:**
1. Implement behavior/schedule name resolution in `resolve/names.rs`
2. Add priority validation
3. Add condition expression validation
4. **Implement template merge algorithm with override-by-name** ← UPDATED
5. **Add multi-level template merge support** ← NEW
6. **Add validation warnings for default/priority conflicts** ← NEW
7. Write resolution tests
8. **Write tests for merge edge cases** ← NEW
### Phase 4: Resolved Types (Week 2) - UNCHANGED
No changes from original design.
### Phase 5: Validation & Diagnostics (Week 3) - UPDATED
**Original:**
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
**Updated:**
1. Implement semantic validation (single default, etc.)
2. Add helpful error messages with fuzzy matching
3. Add warnings for incomplete condition coverage
4. **Add warnings for merge conflicts (defaults, priorities)** ← NEW
5. Write validation tests
### Phase 6: Integration & Documentation (Week 3) - UPDATED
**Original:**
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)
**Updated:**
1. Update examples to use new linking syntax
2. **Update examples to show template merging** ← NEW
3. **Update examples to show both `==` and `is` operators** ← NEW
4. Update language documentation
5. **Document merge algorithm for users** ← NEW
6. Run full test suite
7. Create migration examples (if backward compatibility breaks)
**Total Estimate:** Still 3 weeks (merge adds complexity but not significant time)
---
## 4. Updated 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] **Both `==` and `is` operators supported** ← NEW
- [x] **Both `!=` and `is not` operators supported** ← NEW
- [x] Priorities supported for behaviors
- [x] Default fallback supported (`default: true`)
- [x] **Template merging works (concatenation + override)** ← UPDATED
- [x] **Multi-level template inheritance works** ← NEW
- [x] Character linking works
- [x] Institution linking works
- [x] Parser produces correct AST
- [x] Resolver validates references
- [x] **Warnings for merge conflicts** ← NEW
- [x] Clear error messages
- [x] SBIR format defined
---
## 5. Open Questions for Sienna (Checkpoint 2)
### Question 1: Empty Array Semantics ("not defined)
What should this mean?
```storybook
template Worker {
uses behaviors: [HandleNeeds, Rest]
}
character Martha: Human from Worker {
uses behaviors: [] // Empty array!
}
```
**Option A:** Empty = clear template behaviors (Martha has NO behaviors)
**Option B:** Empty = ignore, inherit from template (same as omitting field)
**Recommendation:** Option B
### Question 2: Priority Conflict Warnings (lsp warning is more than fine, yellow squiggly, internal behavior is to override at the character level)
Should we warn when character changes priority of template behavior?
```storybook
template Worker { uses behaviors: [{ tree: Rest, priority: high }] }
character Martha from Worker { uses behaviors: [{ tree: Rest, priority: low }] }
```
**Option A:** Silent override (no warning)
**Option B:** Warn about priority change
**Option C:** Error (must use same priority)
**Recommendation:** Option A (silent) or Option B (warning)
### Question 3: `is not` Support (absolutely yes)
Should we support `is not` alongside `!=`?
**Recommendation:** Yes, for consistency with Python
### Question 4: Merge Validation Level (um... strict is prolly best tbh)
How strict should merge conflict validation be?
**Option A:** Errors on any conflict (strict)
**Option B:** Warnings only (permissive)
**Option C:** Silent (trust user)
**Recommendation:** Option B (warnings)
---
## 6. Summary of Changes
### From Checkpoint 1 to Checkpoint 2:
**Major Change 1: Template Merging**
- ❌ Old: All-or-nothing replacement
- ✅ New: Concatenation with override-by-name
- Character links evaluated first
- Template links added if not overridden
- Multi-level inheritance supported
**Major Change 2: Operator Support**
- ✅ Added: `is` as synonym for `==`
- ✅ Added: `is not` as synonym for `!=`
- No AST changes needed
- Parser accepts both styles
**Minor Changes:**
- Added merge conflict warnings
- Updated examples to show composition
- Updated implementation plan phases
---
**End of Checkpoint 2 Addendum**
**Next Step:** Review with user (Sienna) for approval, then proceed to implementation (Task #9).