Skip to main content

context

Runtime context passed to compiled closures — the world as seen from inside

معلومات المصدر

المستودع
SimHacker/moollm
آخر نشاط في المصدر
٩ فبراير ٢٠٢٦ في ٢١:١٧
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٦٠
التفرعات
٥

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

مستكشف الملفات
6 ملفات

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
context
description
Runtime context passed to compiled closures — the world as seen from inside
allowed-tools
["read_file","write_file"]
tier
1
protocol
RUNTIME-CONTEXT
tags
["moollm","runtime","context","closure","state","primitive"]
related
["object","adventure","room","buff","simulation"]
adversary
global-state
# Context > *"The context IS the world as seen from inside the closure."* > — Dave Ungar, on lexical scope --- ## What Is It? The **world** object is passed to every compiled closure. It provides: 1. **Standard keys** — Always present (adventure, player, room, turn) 2. **Extended keys** — Contextual (object, target, npc) 3. **Skill namespaces** — Skills register state under `world.skills.skill_name` 4. **Utility functions** — API for interacting with the world ### Why "world" not "ctx"? - More evocative — closures see the WORLD - Self-documenting — `world.player`, `world.room` - Matches the mental model --- ## Standard Keys Always present in every world: ```javascript world.turn // Current simulation turn world.timestamp // ISO timestamp world.adventure // Root adventure state .name .flags // Global boolean flags .world_state // Global key/value state world.player // Current player .id .name .location // Path to current room .inventory // Array of item ids .buffs // Active buffs world.room // Current room .id .name .path .exits .objects .is_dark .is_dangerous world.party // Party state .members .leader ``` --- ## Extended Keys Present when relevant: ```javascript // When running object simulate/methods: world.object // The object being simulated .id .state // Object's mutable state // Methods are bound: world.consume_fuel(1) // When action targets something: world.target // The target .id .type // "object", "character", "room" // When NPC is simulating: world.npc // The NPC .id .goals .state ``` --- ## Skill State Namespaces Skills register state under `world.skills.<skill_name>` using **underscores**: ```javascript // Skill "economy" → world.skills.economy world.skills.economy.gold // 100 // Skill "pie-menu" → world.skills.pie_menu (underscore!) world.skills.pie_menu.last_selection // "north" // Skill "time" → world.skills.time world.skills.time.hour // 14 world.skills.time.phase // "afternoon" ``` **Why underscores?** Dashes aren't valid JS/Python identifiers. `foo-bar` skill → `foo_bar` namespace. This keeps skill state organized and avoids collisions. --- ## Utility Functions Methods bound to world for interaction: ### Narrative ```javascript world.emit("The lamp dies!") // Show message world.narrate("Darkness falls.", "dramatic") ``` ### Events ```javascript world.trigger_event("GRUE_APPROACHES", { room: world.room.path }) ``` ### Inventory ```javascript world.has("brass-key") // true/false world.give("gold-coins") // Add to inventory world.take("used-potion") // Remove from inventory ``` ### Flags ```javascript world.flag("dragon_slain") // Get flag world.set_flag("treasure_found", true) // Set flag ``` ### State ```javascript world.get("object.state.fuel") // Get by path world.set("object.state.lit", true) // Set by path ``` ### Navigation ```javascript world.go("../maze/room-a/") // Move player world.can_go("north") // Check exit ``` ### Buffs ```javascript world.add_buff({ name: "Caffeinated", effect: { energy: +2 }, duration: 5 }) world.remove_buff("caffeinated") world.has_buff("grue_immunity") ``` ### Logging ```javascript world.log("Debug: fuel = " + world.object.state.fuel) ``` --- ## Example: Lamp Simulate ```javascript simulate_js: (world) => { if (world.object.state.lit) { world.consume_fuel(1); // Call object method if (world.object.state.fuel <= 0) { world.extinguish(); // Call object method world.emit("The lamp sputters and dies!"); if (world.room.is_dark && world.room.is_dangerous) { world.trigger_event("GRUE_APPROACHES"); } } } } ``` --- ## Example: Guard Expression ```yaml guard: "player has the key AND room is not dark" guard_js: (world) => world.has("brass-key") && !world.room.is_dark ``` --- ## Example: Score Calculation ```yaml score_if: "player is tired OR room is dark" score_if_js: (world) => world.has_buff("tired") || world.room.is_dark ``` --- ## Example: Skill State ```yaml # Skill "economy" needs to check gold guard: "player has at least 10 gold" guard_js: (world) => world.skills.economy.gold >= 10 # Skill "pie-menu" checks last selection score_if: "last pie menu selection was north" score_if_js: (world) => world.skills.pie_menu.last_selection === "north" ``` --- ## Design Principles ### Structured, Not Arbitrary world is NOT just a bag of key/values. It has defined structure: - Standard keys are always present - Extended keys appear in context - Skills namespace their state (with underscores!) - Functions are bound methods ### Skill Namespaces (Underscores!) Skills don't pollute root world. They register under `world.skills.skill_name`: ```javascript // Skill "economy" → world.skills.economy world.skills.economy.gold world.skills.economy.currency // Skill "pie-menu" → world.skills.pie_menu (underscore!) world.skills.pie_menu.last_selection world.skills.pie_menu.hover_direction // Skill "foo-bar" → world.skills.foo_bar world.skills.foo_bar.some_state ``` **Rule:** `skill-name` with dashes → `skill_name` with underscores in namespace. ### Methods Are Bound Object methods appear as functions on world: ```javascript // Object defines: methods: consume_fuel: "reduce fuel by amount" // At runtime, method is bound: world.consume_fuel(1) // Works! ``` --- ## Related Skills - [object](../object/) — Provides ctx.object - [room](../room/) — Provides ctx.room - [adventure](../adventure/) — Provides ctx.adventure - [buff](../buff/) — Used by ctx.add_buff/has_buff --- ## Dual Runtime: Python + JavaScript **CRITICAL:** We always generate BOTH `_js` AND `_py` versions of compiled expressions. ```yaml # Natural language guard: "player has the key AND room is not dark" # BOTH generated: guard_js: (world) => world.has("brass-key") && !world.room.is_dark guard_py: lambda world: world.has("brass-key") and not world.room.is_dark ``` ### Why Dual Runtimes? | Runtime | Purpose | |---------|---------| | **Python** | Server-side simulation, testing, LLM tethering | | **JavaScript** | Browser runtime, standalone play | ### Keeping Them In Sync 1. **Same semantics** — Both should produce identical results 2. **Same world structure** — `world.player`, `world.room`, etc. 3. **Same utility functions** — `world.has()`, `world.emit()`, etc. 4. **Generated together** — LLM produces both in one pass ### The Compilation Event ```yaml - event: COMPILE_EXPRESSION field: guard source: "player has the key" targets: - field: guard_js language: javascript - field: guard_py language: python expected_type: boolean ``` ### Python Runtime Class ```python class World: """Python runtime context — mirrors JavaScript World class.""" def __init__(self, adventure_data): self.turn = 0 self.adventure = adventure_data self.player = adventure_data['player'] self.room = None # Set on navigation self.party = adventure_data['party'] self.object = None # Set during object simulation self.skills = {} # Skill state namespaces def has(self, item_id: str) -> bool: return item_id in self.player.get('inventory', []) def flag(self, name: str) -> bool: return self.adventure.get('flags', {}).get(name, False) def emit(self, message: str): print(message) # Or queue for output def trigger_event(self, name: str, data=None): # Event system handles this pass ``` ### JavaScript Runtime Class ```javascript class World { /** JavaScript runtime context — mirrors Python World class. */ constructor(adventureData) { this.turn = 0; this.adventure = adventureData; this.player = adventureData.player; this.room = null; // Set on navigation this.party = adventureData.party; this.object = null; // Set during object simulation this.skills = {}; // Skill state namespaces } has(itemId) { return (this.player.inventory || []).includes(itemId); } flag(name) { return (this.adventure.flags || {})[name] || false; } emit(message) { console.log(message); // Or queue for UI } triggerEvent(name, data) { // Event system handles this } } ``` --- ## Protocol Symbol ``` RUNTIME-CONTEXT — The world passed to closures (Python + JavaScript) ```
عرض على GitHub