arch: Add Gateway Architecture + crawler_gen_0 organism

Gateway Architecture (new):
- Unified tier model (Tier 0-5) for sensory routing
- Weight-based routing: node.weight determines processing tier
- Function Gemma as structured JSON boundary
- Separates routing from translation (vocabulary only at Tier 4)

crawler_gen_0 (new):
- First Virtual Garden organism specification
- Light-seeking cube with photoresistor
- Lifeforce economy: light = income, movement = cost

Updated documents with Gateway references:
- Endgame-Vision.md (v6.5)
- Cellular-Architecture.md (v4.3)
- Nervous-System.md
- Attention-Flow.md
- Message-Protocol-Design.md (Escalation Service = Gateway)
- Organisms-Index.md

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-03 16:44:20 +01:00
parent 7df236b325
commit 2406083045
8 changed files with 885 additions and 13 deletions

View File

@@ -0,0 +1,313 @@
# Crawler Generation 0: Light Seeker
**The simplest organism — a cube that seeks light.**
---
## Overview
Crawler Gen 0 is the foundational organism for the Virtual Garden. Before building physical robots, we train behaviors in simulation. This organism has one sensor, one goal: **move into the light cone to survive**.
**Philosophy:** *Start with phototropism. 3.5 billion years of evolution can't be wrong.*
---
## Purpose
1. **Validate the training pipeline** — Can we generate useful training data in simulation?
2. **Establish baseline behavior** — Light-seeking becomes the foundation for all "seek resource" reflexes
3. **Measure noise gap** — When we build physical Gen 0, how well does simulation predict reality?
---
## Hardware Abstraction (Virtual)
### Sensors
| Sensor | Location | Output | Purpose |
|--------|----------|--------|---------|
| `photoresistor` | Back face | `0.0 - 1.0` | Light intensity measurement |
**Why back face?** The organism must orient toward light. If sensor is on front, it would face away from what it's measuring. Back-mounted = face the light to maximize reading.
### Actuators
| Actuator | Function | Cost |
|----------|----------|------|
| `move_x` | Translate on X axis | `-0.1 LF per unit` |
| `move_y` | Translate on Y axis | `-0.1 LF per unit` |
| `rotate` | Rotate in place | `-0.05 LF per degree` |
| `idle` | Do nothing | `0 LF` |
### Physical Properties
```
┌───────┐
│ │
│ ◼ │ ← 10cm cube
│ │
└───┬───┘
[photoresistor] ← back face
```
- **Size:** 10cm × 10cm × 10cm
- **Mass:** Simulated as point mass for Gen 0
- **Movement:** Frictionless glide (simplified physics)
---
## Environment: The Light Cone
### Setup
```
🔆 LIGHT SOURCE
│ cone angle: 45°
╱│╲
│ ╲
│ ╲
│ ╲ intensity gradient:
│ ╲ center = 1.0
│ ╲ edge = 0.3
│ ╲ outside = 0.0
───────▀───────┴───────▀─────── floor (2m × 2m)
```
### Light Intensity Function
```python
def light_intensity(position, light_source):
"""
Calculate light intensity at position.
Returns 0.0 - 1.0 based on distance from cone center.
"""
distance = dist(position, light_source.center_projection)
if distance > light_source.cone_radius:
return 0.0 # Outside cone
# Linear falloff from center
normalized = 1.0 - (distance / light_source.cone_radius)
return normalized * light_source.max_intensity
```
---
## Lifeforce Economy
### Income
| Source | Amount | Condition |
|--------|--------|-----------|
| Light exposure | `+light_reading × 0.5 LF/tick` | Continuous while in light |
### Expenses
| Action | Cost |
|--------|------|
| Movement | `-0.1 LF per unit distance` |
| Rotation | `-0.05 LF per 10°` |
| Existence | `-0.01 LF/tick` (metabolism) |
### Death Condition
```
IF lifeforce <= 0:
organism.die()
episode.end(reason="starvation")
```
### Survival Equation
```
To survive indefinitely:
light_income >= existence_cost
light_reading × 0.5 >= 0.01
light_reading >= 0.02
Minimum viable light: 2% intensity (edge of cone)
Optimal position: center of cone (100% intensity)
```
---
## Training Data Generation
### Episode Structure
```python
def run_episode(max_ticks=1000):
# Random start position (outside cone 50% of time)
cube.position = random_position()
cube.lifeforce = 10.0 # Starting budget
trajectory = []
for tick in range(max_ticks):
# Observe
state = {
"light": photoresistor.read(),
"position": cube.position,
"orientation": cube.orientation,
"lifeforce": cube.lifeforce
}
# Act (random policy for data collection, or learned policy)
action = agent.act(state)
# Execute
old_light = state["light"]
cube.execute(action)
new_light = photoresistor.read()
# Calculate reward
light_delta = new_light - old_light
action_cost = calculate_cost(action)
reward = (new_light * 0.5) - action_cost - 0.01
# Update lifeforce
cube.lifeforce += reward
# Record
trajectory.append({
"state": state,
"action": action,
"reward": reward,
"next_state": get_current_state(),
"done": cube.lifeforce <= 0
})
if cube.lifeforce <= 0:
break
return trajectory
```
### Dataset Output Format
```json
{
"episode_id": "gen0_ep_00001",
"organism": "crawler_gen_0",
"ticks_survived": 847,
"final_lifeforce": 0.0,
"death_reason": "starvation",
"trajectory": [
{
"tick": 0,
"state": {"light": 0.0, "position": [1.2, 0.8], "lifeforce": 10.0},
"action": {"type": "move", "dx": -0.1, "dy": 0.0},
"reward": -0.11,
"next_light": 0.0
},
...
]
}
```
---
## Expected Emergent Behaviors
With sufficient training data and GRPO optimization:
| Behavior | Description | When Emerges |
|----------|-------------|--------------|
| **Gradient following** | Move toward increasing light | Early |
| **Spiral search** | When lost, spiral outward to find cone | Mid |
| **Center locking** | Stop at maximum intensity | Mid |
| **Energy conservation** | Reduce movement when stable | Late |
| **Edge avoidance** | Stay away from cone boundary | Late |
---
## Simulation Platform
### Option A: Blender + Python
Use existing `nimmerlab_bare1.blend`:
- Light source with volumetric cone already exists
- Add cube with raycast to light for photoresistor value
- Python script for episode runner
- Export trajectories to JSON
### Option B: Godot (Aligns with Management Portal)
- Simple 2D/3D scene
- Built-in physics
- Easy to iterate
- Same engine as Command Center
### Option C: Pure Python + NumPy
- Fastest iteration
- No visualization (add later)
- Easiest data pipeline to GRPO
**Recommendation:** Start with Option C for rapid data generation, add Blender visualization for debugging.
---
## Physical Realization (Future)
When Virtual Garden validates the behavior:
| Virtual | Physical |
|---------|----------|
| Simulated cube | Box Robot (Phase 0) |
| Raycast light reading | Actual photoresistor |
| Frictionless movement | Differential drive motors |
| Instant rotation | Turn in place |
| Perfect sensing | Noisy ADC readings |
**Noise Gap Target:** <20% after calibration
---
## Connection to Architecture
| Layer | Component | Role |
|-------|-----------|------|
| Layer 1 | `light_sensor` cell | Wraps photoresistor hardware |
| Layer 1 | `motor_drive` cell | Wraps differential motors |
| Layer 1 | `seek_light` nerve | Composed behavior |
| Layer 2 | LoRA training data | GRPO from trajectories |
---
## Success Criteria
### Virtual Garden
- [ ] Generate 10,000 episodes
- [ ] Train policy that survives >90% of episodes
- [ ] Policy reaches cone center within 100 ticks from random start
- [ ] Energy-positive when centered (lifeforce increasing)
### Physical Transfer
- [ ] Box Robot follows light source
- [ ] Noise gap <20%
- [ ] Survives 10-minute test under desk lamp
---
## Next Steps
1. **Implement Episode Runner** — Pure Python, state machine
2. **Generate Baseline Dataset** — Random policy, 1000 episodes
3. **Train First Policy** — Simple RL or behavior cloning
4. **Visualize in Blender** — Replay trajectories for debugging
5. **Measure & Iterate** — Survival rate, time to center
---
**File:** crawler_gen_0.md
**Version:** 0.1
**Created:** 2026-01-03
**Status:** Design document
**Philosophy:** "First, learn to find the light. Everything else follows."
🌱🔆 *The simplest behavior. The deepest foundation.*