A Modern TypeScript Interactive Fiction Platform
Sharpee is a modern, TypeScript-based Interactive Fiction platform designed for extensibility, clean separation of concerns, and developer experience. This report focuses on recent platform improvements since January 3, 2026.
Modular slot consumer architecture with action-centric grammar API.
68% reduction in grammar engine size (1355 to 432 lines)
// Before: Monolithic 1355-line switch statement
consumeSlot(slotType) {
switch (slotType) {
case 'ENTITY': // 350 lines
case 'TEXT': // 150 lines
case 'NUMBER': // 400 lines
// ... etc
}
}
// After: Strategy Pattern with Registry
slot-consumers/
entity-slot-consumer.ts (381 lines)
text-slot-consumer.ts (183 lines)
typed-slot-consumer.ts (174 lines)
vocabulary-slot-consumer.ts (216 lines)
DRY verb definitions with automatic synonym expansion
// Before: Pattern-centric (action ID repeated, easy to miss synonyms)
grammar.define('push :target').mapsTo('if.action.pushing').build();
grammar.define('shove :target').mapsTo('if.action.pushing').build();
grammar.define('move :target').mapsTo('if.action.pushing').build();
// Oops - forgot 'press :target'!
// After: Action-centric (verb list explicit, can't miss synonyms)
grammar
.forAction('if.action.pushing')
.verbs(['push', 'press', 'shove', 'move'])
.pattern(':target')
.where('target', scope => scope.touchable())
.build();
| Improvement | Details |
|---|---|
| Testability | Slot consumers now unit testable in isolation (41 new tests) |
| Extensibility | New slot types = new consumer class, no switch modification |
| Bug Prevention | .forAction() API prevents missing verb synonyms |
| Line Reduction | Direction commands: 24 definitions reduced to 1 |
Pronoun resolution, neopronouns support, and perspective-aware messages.
8 pronoun sets including neopronouns
// Standard pronouns
PRONOUNS.HE_HIM // he/him/his/himself
PRONOUNS.SHE_HER // she/her/hers/herself
PRONOUNS.THEY_THEM // they/them/their/themselves
// Neopronouns
PRONOUNS.XE_XEM // xe/xem/xyr/xemself
PRONOUNS.ZE_ZIR // ze/zir/zirs/zirself
PRONOUNS.FAE_FAER // fae/faer/faers/faerself
// Multiple pronoun sets (he/they, she/they)
const alice = world.createEntity('alice', 'Alice', {
actor: {
pronouns: [PRONOUNS.SHE_HER, PRONOUNS.THEY_THEM],
honorific: HONORIFICS.DR,
},
});
// Player types: "talk to alice" then "give her the key"
// Parser resolves "her" -> alice
1st, 2nd, or 3rd person story narration
// Story configuration
export const storyConfig: StoryConfig = {
id: 'my-story',
title: 'My Story',
narrative: {
perspective: '1st', // "I take the lamp"
},
};
// Message templates with placeholders
messages: {
'taken_from': "{You} {take} {item} from {container}."
}
// Renders as:
// 2nd person (default): "You take sword from chest."
// 1st person: "I take sword from chest."
// 3rd person (she): "She takes sword from chest."
| Phase | Component | Status |
|---|---|---|
| A | IdentityTrait expansion (world-model) | Complete |
| B | PronounContext (parser) - "it/them/him/her" tracking | Complete |
| C | NarrativeSettings (engine) | Complete |
| D | Message placeholders (lang-en-us) | Complete |
| E | Advanced verb conjugation | Future |
Entities declare capabilities, behaviors implement the 4-phase pattern.
validate/execute/report/blocked phases
// 1. Trait declares capabilities
class BasketElevatorTrait implements ITrait {
static readonly type = 'dungeo.trait.basket_elevator';
static readonly capabilities = ['if.action.lowering', 'if.action.raising'];
position: 'top' | 'bottom' = 'top';
}
// 2. Behavior implements 4-phase pattern
const BasketLoweringBehavior: CapabilityBehavior = {
validate(entity, world, actorId) {
const trait = entity.get(BasketElevatorTrait);
if (trait.position === 'bottom') {
return { valid: false, error: 'dungeo.basket.already_down' };
}
return { valid: true };
},
execute(entity, world, actorId) {
entity.get(BasketElevatorTrait).position = 'bottom';
},
report(entity, world, actorId) {
return [createEffect('if.event.lowered', { target: entity.id })];
},
blocked(entity, world, actorId, error) {
return [createEffect('action.blocked', { messageId: error })];
}
};
// 3. Register behavior
registerCapabilityBehavior(
BasketElevatorTrait.type,
'if.action.lowering',
BasketLoweringBehavior
);
// Now "lower basket" automatically dispatches to BasketLoweringBehavior!
| Component | Location | Purpose |
|---|---|---|
CapabilityBehavior |
@sharpee/world-model | Interface for 4-phase behavior pattern |
CapabilityRegistry |
@sharpee/world-model | Maps trait+capability to behavior |
createCapabilityDispatchAction() |
@sharpee/stdlib | Factory for capability-aware actions |
ValidationResult.data |
@sharpee/stdlib | Pass data from validate to execute (no sharedData mutation) |
lowering / raising |
@sharpee/stdlib | New stdlib actions using capability dispatch |
First proof-of-concept: "lower basket" and "raise basket" now use capability dispatch. Player inside basket is automatically transported when basket position changes. All 13 transcript tests pass.
Comprehensive testing infrastructure for action correctness.
Phase 6 - New test utilities
// Capture entity state before action
const before = captureEntityState(world, entity, ['isOpen', 'isLocked']);
// Execute action
await engine.execute('open door');
// Verify state changes
expectTraitChanged(before, world, entity, 'isOpen', false, true);
expectLocation(world, player, room);
expectLocationChanged(before, world, item, oldRoom, newRoom);
| Action | Behavior Delegation | Tests Added |
|---|---|---|
| opening / closing | OpenableBehavior.open/close | 6 tests |
| locking / unlocking | LockableBehavior.lock/unlock | 6 tests |
| switching_on / switching_off | SwitchableBehavior + LightSourceBehavior | 12 tests |
| wearing / taking_off | WearableBehavior.wear/remove | 12 tests |
| entering / exiting / going | world.moveEntity | Existing tests fixed |
| putting / inserting / removing | world.moveEntity | Existing tests verified |
docs/reference/core-concepts.md now includes World State Verification section. CLAUDE.md updated with Stdlib Action Testing guidance. New action test template at packages/stdlib/tests/unit/actions/_action-test-template.ts.
.forAction() API with verb alias support
Strategy Pattern slot consumers, 68% size reduction
Inclusive pronouns, narrative perspective, message placeholders
Trait capabilities + registered behaviors
EventDataRegistry with 25+ typed event data types
Direct GrammarBuilder access, -789 lines
PerceptionService, unified darkness checking
Treaty of Babel compliant story identification
npm Beta Release
All 11 packages published to npm at 0.9.1-beta.13. Monorepo refactored to workspace:* dependencies.
ADR-087/088: Grammar Refactor
Strategy Pattern extraction reduces grammar engine 68%. Action-centric .forAction() API with verb aliases. 41 new unit tests.
ADR-089: Pronoun System
Phases A-D complete. Parser pronoun resolution, narrative settings, perspective placeholders. 48 new unit tests.
ADR-090: Capability Dispatch
Phases 1-5 complete. Capability registry, behavior pattern, Dungeo basket elevator proof-of-concept.
ValidationResult.data Infrastructure
Clean data flow from validate() to execute/report phases without sharedData mutation.
Stdlib Testing Mitigation Complete
Phase 2.2 property mutation actions verified. Test helper infrastructure added. Documentation updated.
Platform Status Update
93+ ADRs documented. 2,800+ unit tests. All major systems verified and tested.
The platform has reached full maturity with comprehensive testing, modular architecture, and inclusive design. Four major ADRs implemented in the past week significantly improve developer experience and code quality.
| Aspect | Rating | Recent Improvements |
|---|---|---|
| Four-Phase Compliance | Excellent | 100% of 47 actions follow pattern |
| Type Safety | Excellent | Typed events, ValidationResult.data |
| Grammar System | Excellent | Modular consumers, action-centric API |
| Perception System | Excellent | PerceptionService, unified darkness |
| Identity & Pronouns | Excellent | Inclusive design, narrative perspective |
| Extensibility | Excellent | Capability dispatch pattern |
| Test Coverage | Excellent | World state verification tests |
| Documentation | Excellent | 93+ ADRs, inline docs, test templates |
| Category | Remaining Work |
|---|---|
| ADR-089 Phase E | Advanced verb conjugation, past tense support |
| Grammar Migration | Migrate remaining verbs to .forAction() API |
| Documentation | Author guides, API reference, example games |
| GenAI Layer | Story spec templates, LLM code generation pipeline |
| Advanced Features | Disambiguation, undo/redo |
| Web Client | React template, accessibility, standard UI |
| NPC System | Conversation trees, behavior scheduling |