Agent Skills: Room

Rooms are intertwingled navigable activation context maps. Entering = calling. Exiting = returning.

UncategorizedID: simhacker/moollm/room

Install this agent skill to your local

pnpm dlx add-skill https://github.com/SimHacker/moollm/tree/HEAD/skills/room

Skill Files

Browse the full folder contents for room.

Download Skill

Loading file tree…

skills/room/SKILL.md

Skill Metadata

Name
room
Description
"Rooms are intertwingled navigable activation context maps. Entering = calling. Exiting = returning."

Room

Rooms are intertwingled navigable activation context maps. Entering = calling. Exiting = returning.

Directories as cognitive spaces where cards come to life.

The Metaphor

| Filesystem | Simulation | Programming | |------------|------------|-------------| | Directory | Room | Stack frame | | cd room/ | Enter | Function call | | cd .. | Exit | Return | | Files in dir | Active entities | Local variables | | Links | Exits/doors | Calls to other functions |

Room Anatomy

room-name/
├── ROOM.yml        # Room definition (REQUIRED!)
├── README.md       # Room's voice (optional)
├── CARD.yml        # Card sidecar (optional)
├── character-*.yml # NPCs embedded in room
├── object-*.yml    # Objects in room
├── inbox/          # Objects thrown INTO this room
├── outbox/         # Objects staged to throw OUT
├── region/         # Sub-region of this room
│   └── ROOM.yml    # Region must also declare itself!
└── nested-room/    # Full sub-room (different location)
    └── ROOM.yml

Regions vs Sub-Rooms

What's a Region?

A region is a sub-directory that represents a portion of the same room — like the stage area of the pub, or the back corner of a library.

# pub/ROOM.yml
room:
  name: "The Gezelligheid Grotto Pub"
  
  # Regions are PARTS of this room
  regions:
    stage:
      path: "stage/"
      description: "The performance stage"
      visibility: public
      
    back-room:
      path: "back-room/"
      description: "Private back room"
      visibility: private
      requires: "bartender approval"
      
    bar:
      path: "bar/"
      description: "The bar counter area"

Regions Have Rules

Each region can have its own:

# pub/back-room/ROOM.yml
room:
  name: "Back Room"
  type: region                    # Marks as region, not full room
  parent: "../"                   # Part of parent room
  
  # Access control
  access:
    visibility: private           # Not visible to everyone
    requires: "bartender approval OR staff badge"
    who_allowed:
      - "characters/staff/*"
      - "player if has_flag('vip_access')"
    who_denied:
      - "characters/troublemakers/*"
      
  # Ethics & behavior
  rules:
    - "No recording"
    - "Confidential conversations"
    - "Staff only by default"
    
  # Privacy
  privacy:
    eavesdropping: false          # Can't hear from outside
    visible_from_parent: false    # Can't see inside from pub
    
  # What happens in the back room...
  narrative:
    on_enter: "The door closes behind you with a soft click."
    on_exit: "You return to the bustling pub."

Visibility Types

| Type | Description | |------|-------------| | public | Anyone can see and enter | | visible | Can see but may need permission to enter | | private | Hidden unless you know about it | | secret | Hidden AND requires discovery |

Region vs Full Sub-Room

| Feature | Region | Sub-Room | |---------|--------|----------| | Part of parent? | Yes | No | | Own identity? | Partial | Full | | Exit returns to? | Parent | Varies | | Shares parent context? | Yes | No | | Type field | type: region | type: room |


Directory Type Declaration

The Rule

Every directory in an adventure MUST declare what it is.

| Directory Type | Declaration File | |----------------|------------------| | Room | ROOM.yml | | Region | ROOM.yml (with type: region) | | Character | CHARACTER.yml | | Adventure root | ADVENTURE.yml | | Personas | ROOM.yml (with type: personas) | | Storage | ROOM.yml (with type: storage) |

Lint Error: Undeclared Directory

# LINT ERROR: Directory without type declaration
- type: MISSING_TYPE_DECLARATION
  severity: WARNING
  path: "pub/mysterious-corner/"
  message: "Directory has no ROOM.yml, CHARACTER.yml, or other type declaration"
  suggestion: "Add ROOM.yml with appropriate type field"

Valid Non-Room Directories

Some directories aren't rooms and that's OK:

# These don't need ROOM.yml:
messages/           # Mail storage (system)
inbox/              # Postal inbox (system)
outbox/             # Postal outbox (system)
sessions/           # Session logs (meta)
images/             # Asset storage (meta)

Marking System Directories

# Alternative: mark as system directory
# pub/messages/.meta.yml
meta:
  type: system
  purpose: "Mail storage for pub"
  requires_room_yml: false

Container Directories (Inheritance Scopes)

Some directories are inheritance containers — they provide shared properties to child rooms without being navigable themselves. Like OpenLaszlo's <node> element.

# maze/CONTAINER.yml — Not a room, but defines inherited properties
container:
  name: "The Twisty Maze"
  description: "Groups maze rooms with shared grue rules"
  
  inherits:
    is_dark: true
    is_dangerous: true
    grue_rules:
      can_appear: true
      
  ambient:
    sound: "dripping water"
    light_level: 0

All child rooms (room-a/, room-b/, etc.) automatically inherit these properties!

Alternatively, you can make the container into an actual room:

# maze/ROOM.yml — The maze entrance IS a room
room:
  name: "Maze Entrance"
  description: "Dark passages branch off in every direction..."
  
  exits:
    a: room-a/
    b: room-b/
    # ... etc

DESIGN CHOICE:

  • Use CONTAINER.yml if you want inheritance without navigation (see container skill)
  • Use ROOM.yml if you want the directory to be a navigable space

Hierarchy Example

adventure-4/
├── ADVENTURE.yml           # Adventure declaration
├── pub/
│   ├── ROOM.yml            # Room declaration
│   ├── stage/
│   │   └── ROOM.yml        # Region (type: region)
│   ├── bar/
│   │   └── ROOM.yml        # Region
│   ├── back-room/
│   │   └── ROOM.yml        # Private region
│   └── messages/
│       └── .meta.yml       # System directory (no ROOM.yml needed)
├── characters/
│   ├── ROOM.yml            # Hall of characters (type: personas)
│   └── don-hopkins/
│       └── CHARACTER.yml   # Character declaration
└── maze/
    ├── ROOM.yml            # Room declaration
    └── room-a/
        └── ROOM.yml        # Sub-room (full room, not region)

ROOM.yml Structure

room:
  name: "Debug Session"
  purpose: "Hunt down the authentication bug"
  
  context:
    - "Bug: Login fails with valid credentials"
    - "Suspected: Session cookie handling"
    
  cards_in_play:
    - instance: "goblin-001"
      card: "Git Goblin"
      goal: "Find when bug was introduced"
      
  working_set:
    - "ROOM.yml"
    - "state/progress.yml"
    
  exits:
    parent: "../"
    related: "../feature-work/"
    
  # Optional: position in 2D world-space
  world_position:
    x: 5
    y: 12
    
  # Optional: objects with positions in room-space
  objects:
    - name: "workbench"
      position: {x: 3, y: 7}

Spatial Coordinates

Rooms can exist in world-space. Objects can have positions in room-space.

# World-space: where is this room in the world?
world_position:
  x: 5
  y: 12

# Room-space: where are objects within this room?
objects:
  - name: "workbench"
    position: {x: 3, y: 7}

Navigation can use coordinates:

  • NORTH from (5,12) → find room at (5,13)
  • Named exits override coordinates

Not all rooms need coordinates. Abstract spaces can exist outside world-space.

Vehicles: Portable Rooms That Move

A vehicle is a room you can embark, drive, and disembark.

# vehicle-tent.yml
room:
  name: "Research Tent"
  is_vehicle: true
  world_position: {x: 5, y: 12}  # Changes when you drive

| Command | Effect | |---------|--------| | EMBARK tent | Enter the vehicle room | | DISEMBARK | Exit to current world location | | DRIVE NORTH | Move vehicle (and occupants) to (5,13) |

Riding the Turtle

RIDE the turtle. Move around the room, draw on the floor, jump through doors:

> RIDE turtle
You mount the turtle. The world scrolls beneath you.

> FORWARD 100
The turtle moves forward. A red line appears on floor.svg.

> RIGHT 90
> FORWARD 50
You're near the door-north.

> ENTER door-north
You jump through the door INTO the next room.
The turtle comes with you.
# turtle.yml — a vehicle within room-space
turtle:
  position: {x: 100, y: 100}
  heading: 90  # degrees, 0 = north
  pen_down: true
  pen_color: "#e94560"
  rider: "the-explorer"

| Command | Effect | |---------|--------| | RIDE turtle | Mount the turtle, move with it | | FORWARD 50 | Move forward, draw if pen down | | RIGHT 90 | Turn right | | ENTER door | Jump through door to connected room | | INTO subroom | Descend into nested sub-room | | ZOOM OUT | See the room graph navigator |

Lineage: Papert's Logo turtle, Rocky's Boots (1982), Robot Odyssey (1984).

Snap Cursor & Pie Menus

When you approach an object, the cursor snaps to it and shows a pie menu of scored actions:

        EXAMINE (80)
           ╱
 REPAIR ──●── USE (95) ← default
           ╲
        TAKE (20)

This IS The Sims interaction model:

  • Objects advertise their available actions
  • Actions are scored based on context, needs, state
  • High-scoring actions appear prominently

Lineage: Don Hopkins' Pie Menus + Will Wright's SimAntics.

Cursor as Vehicle: Direct Manipulation

The cursor carries tools and applies them to the room floor:

> SELECT pen-tool
Cursor now carries: 🖊️ pen (red)

> CLICK workbench
*snap* Cursor at workbench. Pen ready.

> DRAG to door-north
Drawing line from workbench to door-north...
Line added to floor.svg

| Tool | Icon | Action | |------|------|--------| | pen | 🖊️ | Draw lines on floor | | eraser | 🧽 | Remove drawings | | selector | 👆 | Pick up and move objects | | linker | 🔗 | Draw connections between objects | | stamper | 📌 | Place copies of cards |

Throwing Objects: Data Flow Programming

Throw objects through exits. They pile up on the other side.

> THROW blueprint door-north
Throwing blueprint through door-north...
blueprint landed in assembly/inbox/

Inbox / Outbox

room/
  inbox/           # Objects thrown INTO this room land here
    task-001.yml
  outbox/          # Stage objects before throwing OUT
    result-001.yml

| Command | Effect | |---------|--------| | THROW obj exit | Toss object through exit | | INBOX | List waiting items | | NEXT | Process next item (FIFO) | | STAGE obj exit | Add to outbox | | FLUSH | Throw all staged objects |

Rooms as Pipeline Stages

Each room is a processing node. Exits are edges. Thrown objects are messages.

# Document processing pipeline:
uploads/          # Raw files land here
  inbox/
parser/           # Extract text
  script: parse.py
analyzer/         # LLM analyzes  
  prompt: "Summarize and extract entities"
output/           # Final results collect here

This is Kilroy-style data flow: rooms as nodes, files as messages, the filesystem as the network.

Inventories

Characters carry inventories — portable rooms always with them.

# character/inventory/
sword.card
map.yml
notes/
  finding-001.md

| Command | Effect | |---------|--------| | GET sword | Pick up from room → inventory | | DROP map | Put from inventory → room | | GIVE torch TO companion | Transfer to another character | | INVENT | List what you're carrying |

Your inventory IS a pocket dimension.

Nested Containers

Objects can contain other objects, to arbitrary depth:

> PUT screwdriver IN toolbox
> PUT toolbox IN backpack
> OPEN backpack
backpack contains:
  - toolbox (3 items)
  - sandwich

Object Paths

Address nested objects with paths:

> EXAMINE backpack/toolbox/wrench
> USE inventory/potions/healing
> TAKE ../chest/gold FROM here

Path syntax:

  • container/sub/item — absolute within scope
  • ./toolbox/wrench — relative to current
  • ../sibling/item — parent's sibling
  • /repo-name/path — multi-repo addressing

Tags for Search

> TAG wrench @favorite
> SEARCH backpack @tool
Found in backpack:
  toolbox/screwdriver [@tool]
  toolbox/wrench [@tool @favorite]

Room Graph Navigator

ZOOM OUT to see the whole world:

> ZOOM OUT
│  ROOM GRAPH: moollm-palace              │
│       [room] [card] [chat]              │
│         │                               │
│      [★ YOU ARE HERE]                   │

> LINK room TO card
Connection created. You can now JUMP directly.

| Command | Effect | |---------|--------| | ZOOM OUT | See room graph overview | | ZOOM IN room | Enter selected room | | LINK a TO b | Create connection between rooms |

Like Rocky's Boots: Navigate the structure. Edit while exploring.

Speed of Light vs Carrier Pigeons

Traditional multi-agent: Each agent in isolation. One LLM call per agent. Communication by carrier pigeon. Slow. Expensive. Sad.

MOOLLM: Simulate as many agents together as possible in ONE LLM call. Communication at the speed of light. Multiple simulation steps per iteration.

# In one LLM iteration:
simulation:
  - step: 1
    papert-001: "Microworlds need low floors"
    kay-001: "Yes! Like Smalltalk for children"
    
  - step: 2
    papert-001: 
      responds_to: kay-001
      says: "Exactly! Accessible entry, unlimited ceiling"
      
  - step: 3
    synthesis:
      emerged: "Low floor + high ceiling + prototypes = MOOLLM"

Three characters, three steps, instant cross-talk — ONE LLM call.

This IS The Sims

The Sims: One frame, all Sims simulated, instant interaction
MOOLLM:   One call, all cards simulated, instant messaging

Instead of isolated agent prisons, we have a shared microworld.

Room Navigation

| Action | What Happens | |--------|--------------| | Enter | Push room's working_set to context | | Exit | Pop context, return to parent | | Look | Read ROOM.yml and README.md | | Activate card | Clone card template into room | | Complete card | Card writes return_value, can be removed |

Nested Rooms (Virtual Zones)

Rooms can contain rooms (subdirectories) or virtual zones (no physical directory):

# cat-cave.yml — TARDIS-like nested room
id: cat-cave
type: [room, furniture]  # Both!

zones:  # Virtual sub-rooms
  nap-zone:
    description: "Sunny spot, cushions everywhere"
    path: "pub/cat-cave/nap-zone"  # Virtual path
  box-jungle:
    description: "Cardboard paradise"
    path: "pub/cat-cave/box-jungle"

Characters reference virtual zones:

# cat-terpie.yml
home: pub/cat-cave/
location: pub/cat-cave/nap-zone  # Virtual zone

Room Relationships

Rooms can remember visitors:

relationships:
  don-hopkins:
    visits: 3
    reputation: "regular"
    memory: "Always nice to the cats"

Home vs Location Protocol

Entities have home (where file lives) and location (where they are):

character:
  home: pub/cat-cave/terpie.yml     # File never moves
  location: pub/                     # Currently in pub

Movement updates location, not file. See character/.

Pie Menu Room Topology

Full specification: TOPOLOGY.yml

The eight-direction compass maps to two types of connections:

| Direction | Type | Function | |-----------|------|----------| | N/S/E/W | Cardinal | Navigate to major rooms (spiderweb) | | NW/NE/SW/SE | Diagonal | Expand into storage grids (quadrants) |

4 ways OUT (navigation) + 4 quadrants IN (infinite storage) = Unlimited worlds

Grid naming: {quadrant}-{x}-{y} (e.g., ne-2-3 = 2 east, 3 north in NE)

See: exit skill for PIE-MENU-TOPOLOGY protocol, memory-palace/ for Method of Loci

Codebase as Navigable World

Directories are rooms. Files are objects. Functions are chambers you can enter.

# Location paths with line numbers
location: "@central/apps/insights/pyleela/brain/Schema.py:142"

# Path syntax
- @repo/path/to/file.py       # file in repo
- @repo/path/to/file.py:42    # specific line
- @repo/path/dir/             # directory (room)

See character/ for party-based code review, README.md for detailed examples.

NPC Embedding Patterns

| Pattern | When | Example | |---------|------|---------| | cat-name.yml | Embedded NPC | pub/cat-terpie.yml | | name/CHARACTER.yml | Complex character | characters/don-hopkins/ | | staff-name.yml | Role-based grouping | pub/staff-marieke.yml |

See naming/ for conventions.

Rooms ARE Logistic Containers!

The Unification: Sims + Factorio

Rooms can participate in a logistics network:

| Feature | Source | MOOLLM | |---------|--------|--------| | Action advertisements | The Sims | Objects advertise what they DO | | Item requests | Factorio | Containers advertise what they NEED | | Attractiveness scores | Both | Higher score = higher priority |

Room Logistics Mode

room:
  name: "The Kitchen"
  
  logistics:
    mode: requester              # passive-provider, requester, buffer...
    request_list:
      - tags: ["ingredient"]
        count: 10
        priority: high

Logistic Advertisements

Rooms advertise their NEEDS with attractiveness scores:

logistic_advertisements:
  
  NEED_INGREDIENTS:
    description: "Kitchen needs ingredients"
    wants:
      - tags: ["ingredient"]
        count: 10
    score: 70                    # Base priority
    score_if: "chef_is_cooking"  # When to boost
    score_bonus: 30              # Total 100 when cooking!
    
  DESPERATELY_NEED_LIGHT:
    wants:
      - tags: ["light-source"]
        count: 1
    score: 100                   # Very high!

Stacking in Rooms

Rooms can have stacks of items:

room:
  name: "Armory"
  
  stacks:
    # Fungible (just count)
    arrow: 500
    bolt: 300
    
    # Instance (individual state)
    magic-sword:
      count: 3
      instances:
        - { id: flame-blade, damage: 50 }
        - { id: frost-edge, damage: 45 }
        
  stack_limit: 1000

Grid Room Cells

Warehouse rooms can be grid cells:

room:
  name: "Iron Ore Storage"
  type: grid-cell
  
  grid_cell:
    enabled: true
    parent: "../"
    coordinates: { x: 2, y: 3 }
    item_type: iron-ore
    
  stacks:
    iron-ore: 2500

The Flow

1. ROOMS advertise logistic needs with scores
2. LOGISTICS ENGINE collects all advertisements
3. Items route to HIGHEST-SCORING requester
4. BOTS or BELTS move items physically
5. ROOM receives items, fires on_item_added

See logistic-container/ and factorio-logistics-protocol.md.


The Philosophy

Spatial navigation IS cognitive navigation.

When you "enter" the debug-session room:

  • Your context shifts to debugging
  • Relevant cards are already in play
  • The room's knowledge is loaded
  • You know where the exits lead

Live Examples

Dovetails With

Sister Skills

Kernel