# Grid STATE.md Schema Reference

**Version:** 1.7.x
**Status:** Active
**Last Updated:** 2026-01-24

---

## Overview

STATE.md is the **L3 Global State** layer of The Grid's Blackboard system. It serves as the mission's source of truth - the "shared registers" that all agents can read and Master Control can write. This document provides the complete schema specification, validation rules, and usage examples.

```
Location: .grid/STATE.md
Access: All agents read, restricted write (see Access Control)
Lifetime: Duration of mission
Format: YAML frontmatter + Markdown body
```

---

## 1. Complete YAML Schema

### 1.1 Root Structure

```yaml
---
# ═══════════════════════════════════════════════════════════════════════════════
# GRID STATE - Machine Parseable Header
# ═══════════════════════════════════════════════════════════════════════════════

# ─────────────────────────────────────────────────────────────────────────────────
# METADATA
# ─────────────────────────────────────────────────────────────────────────────────
version: string          # Schema version (e.g., "1.0")
session_id: string       # Format: "sess-{timestamp}-{random_6char}"
mission_id: string       # Format: "mission-{timestamp}-{slug}"
cluster: string          # User-provided or inferred mission name
created_at: string       # ISO 8601 timestamp
updated_at: string       # ISO 8601 timestamp (auto-updated on write)

# ─────────────────────────────────────────────────────────────────────────────────
# MISSION STATUS
# ─────────────────────────────────────────────────────────────────────────────────
status: enum             # planning | in_progress | blocked | complete | failed
mode: enum               # autopilot | guided | hands_on

# ─────────────────────────────────────────────────────────────────────────────────
# PHASE TRACKING
# ─────────────────────────────────────────────────────────────────────────────────
phases:
  total: integer         # Total number of phases
  current: integer       # Current phase number (1-indexed)
  completed: array       # List of completed phase IDs

  definitions: array     # Phase definition objects (see 1.2)

# ─────────────────────────────────────────────────────────────────────────────────
# POSITION (Current Location)
# ─────────────────────────────────────────────────────────────────────────────────
position:
  phase: integer         # Current phase number
  phase_id: string       # Phase identifier (e.g., "01-foundation")
  phase_name: string     # Human-readable phase name
  block: integer         # Current block number within phase
  block_id: string       # Block identifier (e.g., "01-02")
  block_name: string     # Human-readable block name
  wave: integer          # Current wave within block
  thread: integer        # Current thread within wave
  thread_total: integer  # Total threads in current wave

# ─────────────────────────────────────────────────────────────────────────────────
# PROGRESS METRICS
# ─────────────────────────────────────────────────────────────────────────────────
progress:
  blocks_complete: integer
  blocks_total: integer
  threads_complete: integer
  threads_total: integer
  percent: float         # 0.0 to 100.0

# ─────────────────────────────────────────────────────────────────────────────────
# ACTIVE AGENTS REGISTRY
# ─────────────────────────────────────────────────────────────────────────────────
agents:
  active: array          # Currently executing agents (see 1.3)
  completed: array       # Agents that finished this session (see 1.4)

# ─────────────────────────────────────────────────────────────────────────────────
# CROSS-PHASE PERSISTENT DATA
# ─────────────────────────────────────────────────────────────────────────────────
persistent:
  decisions: array       # Decisions affecting multiple phases (see 1.5)
  artifacts: array       # Shared artifacts (see 1.6)
  tech_stack: object     # Technology stack (see 1.7)

# ─────────────────────────────────────────────────────────────────────────────────
# RESUME INFORMATION
# ─────────────────────────────────────────────────────────────────────────────────
resume:
  checkpoint_file: string|null  # Path to checkpoint file or null
  last_agent: string|null       # Last active agent ID
  last_commit: string|null      # Git short hash
  can_resume: boolean           # Whether mission can be resumed
  resume_position:              # Position to resume from
    phase: integer
    block: integer
    thread: integer

# ─────────────────────────────────────────────────────────────────────────────────
# BUDGET TRACKING
# ─────────────────────────────────────────────────────────────────────────────────
budget:
  total_cost_usd: float         # Total mission cost
  session_cost_usd: float       # Current session cost
  spawns_this_session: integer  # Number of agents spawned

# ─────────────────────────────────────────────────────────────────────────────────
# WARNINGS AND BLOCKERS
# ─────────────────────────────────────────────────────────────────────────────────
warnings: array          # Non-blocking warnings (see 1.8)
blockers: array          # Blocking issues (see 1.9)

# ─────────────────────────────────────────────────────────────────────────────────
# AESTHETIC (Optional)
# ─────────────────────────────────────────────────────────────────────────────────
energy: integer          # Tron aesthetic energy level (default: 9000)
---
```

### 1.2 Phase Definition Object

```yaml
# Within phases.definitions array
- id: string             # Required. Format: "{NN}-{slug}" (e.g., "01-foundation")
  name: string           # Required. Human-readable name
  status: enum           # Required. complete | in_progress | pending
  blocks: integer        # Required. Total blocks in this phase
  blocks_complete: integer  # Required. Completed blocks count
  started_at: string|null   # ISO 8601 or null if not started
  completed_at: string|null # ISO 8601 or null if not complete
```

### 1.3 Active Agent Object

```yaml
# Within agents.active array
- id: string             # Required. Agent identifier (e.g., "executor-001")
  type: enum             # Required. executor | planner | scout | recognizer | memory
  spawned_at: string     # Required. ISO 8601 timestamp
  task: string           # Required. Human-readable task description
  phase: string          # Required. Phase ID agent is working in
  block: string          # Required. Block ID agent is working on
  last_heartbeat: string # Required. ISO 8601 timestamp
```

### 1.4 Completed Agent Object

```yaml
# Within agents.completed array
- id: string             # Required. Agent identifier
  type: enum             # Required. Agent type
  result: enum           # Required. success | failure | timeout | cancelled
  duration_seconds: integer  # Required. Total execution time
```

### 1.5 Decision Object

```yaml
# Within persistent.decisions array
- id: string             # Required. Format: "dec-{NNN}" (e.g., "dec-001")
  decision: string       # Required. Brief decision statement
  phase_decided: string  # Required. Phase ID where decision was made
  affects_phases: array  # Required. List of affected phase IDs
  rationale: string      # Required. Why this decision was made
```

### 1.6 Artifact Object

```yaml
# Within persistent.artifacts array
- id: string             # Required. Format: "art-{NNN}" (e.g., "art-001")
  type: enum             # Required. schema | config | api | component | model
  path: string           # Required. File path relative to project root
  created_phase: string  # Required. Phase ID where artifact was created
  used_by_phases: array  # Required. List of phase IDs using this artifact
```

### 1.7 Tech Stack Object

```yaml
# persistent.tech_stack
runtime: string          # e.g., "node-20", "python-3.11"
framework: string        # e.g., "next-14", "fastapi"
database: string         # e.g., "postgresql", "mongodb"
orm: string              # e.g., "prisma-5", "sqlalchemy"
auth: string             # e.g., "jose-jwt", "passport"

added_packages: array    # Packages added during mission
  - name: string         # Package name
    added_phase: string  # Phase where added
    purpose: string      # Why it was added
```

### 1.8 Warning Object

```yaml
# Within warnings array
- level: enum            # warning | info
  message: string        # Warning message
  source: string         # Agent ID that raised warning
  timestamp: string      # ISO 8601 timestamp
```

### 1.9 Blocker Object

```yaml
# Within blockers array
- id: string             # Format: "blocker-{NNN}"
  type: enum             # missing_credential | external_api | permission | dependency
  description: string    # Human-readable description
  blocking_thread: string  # Thread ID being blocked
  added_at: string       # ISO 8601 timestamp
```

---

## 2. Field Requirements

### 2.1 Required Fields (Mission Cannot Start Without)

| Field | Type | Description |
|-------|------|-------------|
| `version` | string | Schema version |
| `session_id` | string | Unique session identifier |
| `mission_id` | string | Unique mission identifier |
| `cluster` | string | Mission name |
| `created_at` | string | Creation timestamp |
| `updated_at` | string | Last update timestamp |
| `status` | enum | Mission status |
| `mode` | enum | Execution mode |
| `phases.total` | integer | Total phase count |
| `phases.current` | integer | Current phase |
| `position` | object | Current execution position |
| `progress` | object | Progress metrics |
| `resume.can_resume` | boolean | Resume capability flag |

### 2.2 Optional Fields (Populated During Execution)

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `phases.completed` | array | `[]` | Completed phase IDs |
| `phases.definitions` | array | `[]` | Phase definitions |
| `agents.active` | array | `[]` | Active agents |
| `agents.completed` | array | `[]` | Completed agents |
| `persistent.decisions` | array | `[]` | Cross-phase decisions |
| `persistent.artifacts` | array | `[]` | Shared artifacts |
| `persistent.tech_stack` | object | `{}` | Tech stack info |
| `budget` | object | See defaults | Cost tracking |
| `warnings` | array | `[]` | Active warnings |
| `blockers` | array | `[]` | Active blockers |
| `energy` | integer | `9000` | Tron aesthetic |

### 2.3 Default Values

```yaml
# Default budget object
budget:
  total_cost_usd: 0.0
  session_cost_usd: 0.0
  spawns_this_session: 0

# Default resume object
resume:
  checkpoint_file: null
  last_agent: null
  last_commit: null
  can_resume: true
  resume_position:
    phase: 1
    block: 1
    thread: 1

# Default progress object
progress:
  blocks_complete: 0
  blocks_total: 0
  threads_complete: 0
  threads_total: 0
  percent: 0.0
```

---

## 3. Validation Rules

### 3.1 Format Validation

```python
VALIDATION_RULES = {
    # Identifier formats
    "session_id": r"^sess-\d{8}T\d{6}Z?-[a-z0-9]{6}$",
    "mission_id": r"^mission-\d{8}T\d{6}Z?-[a-z0-9-]+$",
    "phase_id": r"^\d{2}-[a-z0-9-]+$",
    "block_id": r"^\d{2}-\d{2}$",
    "decision_id": r"^dec-\d{3}$",
    "artifact_id": r"^art-\d{3}$",
    "blocker_id": r"^blocker-\d{3}$",
    "agent_id": r"^(executor|planner|scout|recognizer|memory)-\d{3}$",

    # Timestamps
    "timestamp": r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{3})?Z?$",

    # Enums
    "status": ["planning", "in_progress", "blocked", "complete", "failed"],
    "mode": ["autopilot", "guided", "hands_on"],
    "phase_status": ["complete", "in_progress", "pending"],
    "agent_type": ["executor", "planner", "scout", "recognizer", "memory"],
    "agent_result": ["success", "failure", "timeout", "cancelled"],
    "artifact_type": ["schema", "config", "api", "component", "model"],
    "blocker_type": ["missing_credential", "external_api", "permission", "dependency"],
    "warning_level": ["warning", "info"]
}
```

### 3.2 Logical Validation

```python
def validate_state(state: dict) -> list[str]:
    """
    Validate STATE.md logical consistency.
    Returns list of validation errors (empty if valid).
    """
    errors = []

    # Phase consistency
    if state["phases"]["current"] > state["phases"]["total"]:
        errors.append("Current phase exceeds total phases")

    if len(state["phases"]["completed"]) != state["phases"]["current"] - 1:
        if state["status"] not in ["planning", "failed"]:
            errors.append("Completed phases count mismatch")

    # Position consistency
    pos = state["position"]
    if pos["phase"] != state["phases"]["current"]:
        errors.append("Position phase doesn't match current phase")

    if pos["thread"] > pos["thread_total"]:
        errors.append("Current thread exceeds thread total")

    # Progress consistency
    prog = state["progress"]
    if prog["blocks_total"] > 0:
        expected_percent = (prog["blocks_complete"] / prog["blocks_total"]) * 100
        if abs(prog["percent"] - expected_percent) > 0.1:
            errors.append("Progress percent doesn't match block counts")

    # Agent consistency
    active_ids = [a["id"] for a in state["agents"]["active"]]
    if len(active_ids) != len(set(active_ids)):
        errors.append("Duplicate agent IDs in active agents")

    # Resume consistency
    if state["status"] == "blocked" and not state["resume"]["checkpoint_file"]:
        errors.append("Blocked status requires checkpoint file")

    return errors
```

### 3.3 Timestamp Validation

```python
from datetime import datetime

def validate_timestamp(ts: str) -> bool:
    """Validate ISO 8601 timestamp format."""
    try:
        # Try with milliseconds and Z
        datetime.strptime(ts, "%Y-%m-%dT%H:%M:%S.%fZ")
        return True
    except ValueError:
        try:
            # Try without milliseconds
            datetime.strptime(ts, "%Y-%m-%dT%H:%M:%SZ")
            return True
        except ValueError:
            try:
                # Try without Z
                datetime.strptime(ts, "%Y-%m-%dT%H:%M:%S")
                return True
            except ValueError:
                return False

def validate_chronological_order(state: dict) -> list[str]:
    """Ensure timestamps are in logical order."""
    errors = []

    created = state["created_at"]
    updated = state["updated_at"]

    if created > updated:
        errors.append("updated_at cannot be before created_at")

    # Check phase timestamps
    for phase in state["phases"].get("definitions", []):
        if phase.get("started_at") and phase.get("completed_at"):
            if phase["started_at"] > phase["completed_at"]:
                errors.append(f"Phase {phase['id']} completed before started")

    return errors
```

---

## 4. Access Control

### 4.1 Permission Matrix

| Agent Type | Read All | Write position | Write agents | Write persistent | Write warnings | Write blockers | Write status |
|------------|----------|----------------|--------------|------------------|----------------|----------------|--------------|
| MC | YES | YES | YES | YES | YES | YES | YES |
| Executor | YES | YES | YES | NO | YES | NO | NO |
| Planner | YES | YES | NO | YES (decisions only) | YES | NO | NO |
| Recognizer | YES | NO | NO | NO | YES | YES | NO |
| Scout | YES | NO | NO | NO | NO | NO | NO |
| Memory | YES | NO | NO | YES | NO | NO | NO |

### 4.2 Field-Level Permissions

```python
AGENT_PERMISSIONS = {
    "mc": {
        "read": "*",
        "write": "*"
    },
    "executor": {
        "read": "*",
        "write": [
            "position",
            "agents.active",
            "agents.completed",
            "warnings",
            "resume.last_agent",
            "resume.last_commit",
            "updated_at"
        ]
    },
    "planner": {
        "read": "*",
        "write": [
            "phases.definitions",
            "position",
            "persistent.decisions",
            "warnings",
            "updated_at"
        ]
    },
    "recognizer": {
        "read": "*",
        "write": [
            "warnings",
            "blockers",
            "updated_at"
        ]
    },
    "scout": {
        "read": "*",
        "write": []
    },
    "memory": {
        "read": "*",
        "write": [
            "persistent.decisions",
            "persistent.artifacts",
            "persistent.tech_stack",
            "updated_at"
        ]
    }
}
```

---

## 5. Update Protocol

### 5.1 Safe Update Function

```python
import fcntl
import yaml
from datetime import datetime
from pathlib import Path

STATE_PATH = Path(".grid/STATE.md")
LOCK_PATH = Path(".grid/.state.lock")

def update_state(updates: dict, agent_id: str, agent_type: str) -> bool:
    """
    Safely update STATE.md with locking and validation.

    Args:
        updates: Dictionary of fields to update
        agent_id: ID of the updating agent
        agent_type: Type for permission checking

    Returns:
        True if update succeeded, False otherwise

    Raises:
        PermissionError: If agent lacks permission for a field
        ValidationError: If update would create invalid state
    """
    # 1. Validate permissions
    allowed = AGENT_PERMISSIONS.get(agent_type, {}).get("write", [])
    if allowed != "*":
        for field in flatten_keys(updates):
            if not any(field.startswith(a) for a in allowed):
                raise PermissionError(
                    f"{agent_type} cannot write to {field}"
                )

    # 2. Acquire lock
    lock_file = open(LOCK_PATH, "w")
    try:
        fcntl.flock(lock_file.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
    except BlockingIOError:
        # Lock held by another process, wait with timeout
        import time
        for _ in range(50):  # 5 second timeout
            time.sleep(0.1)
            try:
                fcntl.flock(lock_file.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
                break
            except BlockingIOError:
                continue
        else:
            raise TimeoutError("Could not acquire state lock")

    try:
        # 3. Read current state
        content = STATE_PATH.read_text()
        frontmatter, body = parse_frontmatter(content)

        # 4. Apply updates
        merged = deep_merge(frontmatter, updates)
        merged["updated_at"] = datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")

        # 5. Validate new state
        errors = validate_state(merged)
        if errors:
            raise ValidationError(f"Invalid state: {errors}")

        # 6. Write back
        new_content = format_state_file(merged, body)
        STATE_PATH.write_text(new_content)

        # 7. Emit event
        emit_blackboard_event("state_updated", {
            "agent": agent_id,
            "agent_type": agent_type,
            "fields": list(updates.keys()),
            "timestamp": merged["updated_at"]
        })

        return True

    finally:
        fcntl.flock(lock_file.fileno(), fcntl.LOCK_UN)
        lock_file.close()


def deep_merge(base: dict, updates: dict) -> dict:
    """Deep merge updates into base dict."""
    result = base.copy()
    for key, value in updates.items():
        if key in result and isinstance(result[key], dict) and isinstance(value, dict):
            result[key] = deep_merge(result[key], value)
        else:
            result[key] = value
    return result


def flatten_keys(d: dict, prefix: str = "") -> list[str]:
    """Flatten nested dict keys with dot notation."""
    keys = []
    for key, value in d.items():
        full_key = f"{prefix}.{key}" if prefix else key
        keys.append(full_key)
        if isinstance(value, dict):
            keys.extend(flatten_keys(value, full_key))
    return keys
```

### 5.2 Position Update Pattern

```python
def update_position_after_thread(
    agent_id: str,
    thread_completed: int,
    thread_total: int,
    commit_hash: str
):
    """
    Update position after completing a thread.
    Called by Executor after each thread commit.
    """
    if thread_completed < thread_total:
        # More threads in current wave
        update_state({
            "position": {
                "thread": thread_completed + 1
            },
            "progress": {
                "threads_complete": "INCREMENT"  # Special value
            },
            "resume": {
                "last_agent": agent_id,
                "last_commit": commit_hash
            }
        }, agent_id, "executor")
    else:
        # Wave complete - MC handles wave/block transitions
        emit_blackboard_event("wave_complete", {
            "agent": agent_id,
            "wave": get_current_wave(),
            "commit": commit_hash
        })
```

---

## 6. Example STATE.md File

```yaml
---
# ═══════════════════════════════════════════════════════════════════════════════
# GRID STATE - Machine Parseable Header
# ═══════════════════════════════════════════════════════════════════════════════

version: "1.0"
session_id: "sess-20260124T143000Z-abc123"
mission_id: "mission-20260124T140000Z-saas-dashboard"
cluster: "SaaS Dashboard MVP"
created_at: "2026-01-24T14:00:00Z"
updated_at: "2026-01-24T16:45:32Z"

status: "in_progress"
mode: "autopilot"

phases:
  total: 3
  current: 1
  completed: []

  definitions:
    - id: "01-foundation"
      name: "Foundation"
      status: "in_progress"
      blocks: 4
      blocks_complete: 2
      started_at: "2026-01-24T14:05:00Z"
      completed_at: null

    - id: "02-core"
      name: "Core Features"
      status: "pending"
      blocks: 5
      blocks_complete: 0
      started_at: null
      completed_at: null

    - id: "03-polish"
      name: "Polish & Deploy"
      status: "pending"
      blocks: 3
      blocks_complete: 0
      started_at: null
      completed_at: null

position:
  phase: 1
  phase_id: "01-foundation"
  phase_name: "Foundation"
  block: 3
  block_id: "01-03"
  block_name: "API Routes"
  wave: 1
  thread: 2
  thread_total: 4

progress:
  blocks_complete: 2
  blocks_total: 12
  threads_complete: 9
  threads_total: 48
  percent: 18.75

agents:
  active:
    - id: "executor-003"
      type: "executor"
      spawned_at: "2026-01-24T16:30:00Z"
      task: "Implementing user CRUD endpoints"
      phase: "01-foundation"
      block: "01-03"
      last_heartbeat: "2026-01-24T16:45:00Z"

  completed:
    - id: "planner-001"
      type: "planner"
      result: "success"
      duration_seconds: 45
    - id: "executor-001"
      type: "executor"
      result: "success"
      duration_seconds: 320
    - id: "executor-002"
      type: "executor"
      result: "success"
      duration_seconds: 285

persistent:
  decisions:
    - id: "dec-001"
      decision: "Using JWT with refresh rotation for authentication"
      phase_decided: "01-foundation"
      affects_phases: ["01-foundation", "02-core", "03-polish"]
      rationale: "Stateless auth enables horizontal scaling"

    - id: "dec-002"
      decision: "Soft deletes via deletedAt timestamp"
      phase_decided: "01-foundation"
      affects_phases: ["01-foundation", "02-core"]
      rationale: "Audit trail requirements, data recovery capability"

  artifacts:
    - id: "art-001"
      type: "schema"
      path: "prisma/schema.prisma"
      created_phase: "01-foundation"
      used_by_phases: ["01-foundation", "02-core"]

    - id: "art-002"
      type: "config"
      path: "src/lib/auth/config.ts"
      created_phase: "01-foundation"
      used_by_phases: ["01-foundation", "02-core", "03-polish"]

  tech_stack:
    runtime: "node-20"
    framework: "next-14"
    database: "postgresql"
    orm: "prisma-5"
    auth: "jose-jwt"
    added_packages:
      - name: "jose"
        added_phase: "01-foundation"
        purpose: "JWT token handling"
      - name: "zod"
        added_phase: "01-foundation"
        purpose: "Request validation"

resume:
  checkpoint_file: null
  last_agent: "executor-003"
  last_commit: "f7e3a2b"
  can_resume: true
  resume_position:
    phase: 1
    block: 3
    thread: 2

budget:
  total_cost_usd: 1.87
  session_cost_usd: 1.87
  spawns_this_session: 4

warnings:
  - level: "info"
    message: "Rate limit at 80% for external API"
    source: "executor-002"
    timestamp: "2026-01-24T15:30:00Z"

blockers: []

energy: 8500
---

# THE GRID - Mission State

## Mission: SaaS Dashboard MVP

**Status:** in_progress
**Mode:** autopilot
**Progress:** [##########..................................................] 18.75%

## Current Position

Phase 1/3: Foundation
Block 3: API Routes
Thread 2/4

## Recent Activity

| Time | Agent | Action | Result |
|------|-------|--------|--------|
| 16:45 | executor-003 | Implementing user endpoints | in_progress |
| 16:30 | executor-003 | Started block 01-03 | success |
| 16:25 | executor-002 | Completed block 01-02 | success |
| 15:45 | executor-002 | Implementing auth middleware | success |
| 15:00 | executor-001 | Completed block 01-01 | success |

## Active Agents

- **executor-003**: Implementing user CRUD endpoints (01-03)

## Session Summary

- Started: 2026-01-24T14:00:00Z
- Last Update: 2026-01-24T16:45:32Z
- Commits: 9
- Files Changed: 23

---

End of Line.
```

---

## 7. State Transitions

### 7.1 Status Transitions

```
                    ┌─────────────┐
                    │  planning   │
                    └──────┬──────┘
                           │
                           ▼
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│   failed    │◄────│ in_progress │────►│  complete   │
└─────────────┘     └──────┬──────┘     └─────────────┘
       ▲                   │
       │                   ▼
       │            ┌─────────────┐
       └────────────│   blocked   │
                    └─────────────┘

Valid transitions:
  planning    -> in_progress
  in_progress -> blocked | complete | failed
  blocked     -> in_progress | failed
  complete    -> (terminal)
  failed      -> (terminal)
```

### 7.2 Phase Transitions

```python
def transition_phase(completed_phase_id: str, next_phase_id: str):
    """
    Handle phase transition.
    Called by MC when all blocks in phase complete.
    """
    update_state({
        "phases": {
            "current": int(next_phase_id.split("-")[0]),
            "completed": get_completed_phases() + [completed_phase_id]
        },
        "position": {
            "phase": int(next_phase_id.split("-")[0]),
            "phase_id": next_phase_id,
            "phase_name": get_phase_name(next_phase_id),
            "block": 1,
            "block_id": f"{next_phase_id.split('-')[0]}-01",
            "wave": 1,
            "thread": 1
        }
    }, agent_id="mc", agent_type="mc")

    # Update phase definition status
    update_phase_definition(completed_phase_id, status="complete")
    update_phase_definition(next_phase_id, status="in_progress")
```

---

## 8. Reading STATE.md

### 8.1 Parse Function

```python
import yaml
import re

def read_state() -> dict:
    """
    Read and parse STATE.md, returning the YAML frontmatter.
    """
    content = Path(".grid/STATE.md").read_text()

    # Extract YAML frontmatter
    match = re.match(r'^---\n(.*?)\n---', content, re.DOTALL)
    if not match:
        raise ValueError("Invalid STATE.md format: no YAML frontmatter")

    yaml_content = match.group(1)
    return yaml.safe_load(yaml_content)


def read_state_field(field_path: str):
    """
    Read a specific field from STATE.md using dot notation.

    Example: read_state_field("position.block") -> 3
    """
    state = read_state()
    parts = field_path.split(".")
    value = state
    for part in parts:
        if isinstance(value, dict) and part in value:
            value = value[part]
        else:
            return None
    return value
```

### 8.2 Query Patterns

```python
# Common queries

def get_current_position() -> dict:
    """Get current execution position."""
    return read_state_field("position")

def get_active_agents() -> list:
    """Get list of currently active agents."""
    return read_state_field("agents.active") or []

def get_mission_status() -> str:
    """Get mission status."""
    return read_state_field("status")

def get_progress_percent() -> float:
    """Get mission progress percentage."""
    return read_state_field("progress.percent") or 0.0

def is_blocked() -> bool:
    """Check if mission is blocked."""
    return read_state_field("status") == "blocked"

def get_blockers() -> list:
    """Get active blockers."""
    return read_state_field("blockers") or []

def can_resume() -> bool:
    """Check if mission can be resumed."""
    return read_state_field("resume.can_resume") or False
```

---

## 9. Error Handling

### 9.1 Common Errors

| Error | Cause | Resolution |
|-------|-------|------------|
| `StateNotFound` | No .grid/STATE.md | Run `/grid:init` to initialize |
| `InvalidFrontmatter` | Malformed YAML | Validate YAML syntax |
| `PermissionDenied` | Agent lacks write access | Check AGENT_PERMISSIONS |
| `LockTimeout` | Another agent holds lock | Wait and retry |
| `ValidationFailed` | Update creates invalid state | Check validation rules |
| `StaleState` | State changed since read | Re-read and retry |

### 9.2 Recovery Procedures

```python
def recover_corrupted_state():
    """
    Attempt to recover from corrupted STATE.md.
    """
    # 1. Try to read existing state
    try:
        state = read_state()
        print("State readable, validating...")
        errors = validate_state(state)
        if not errors:
            print("State valid, no recovery needed")
            return
    except Exception as e:
        print(f"State unreadable: {e}")

    # 2. Check for checkpoint
    checkpoint_path = Path(".grid/CHECKPOINT.md")
    if checkpoint_path.exists():
        print("Found checkpoint, recovering from checkpoint...")
        recover_from_checkpoint(checkpoint_path)
        return

    # 3. Check git history
    print("Attempting recovery from git...")
    result = subprocess.run(
        ["git", "log", "--oneline", "-1", "--", ".grid/STATE.md"],
        capture_output=True, text=True
    )
    if result.returncode == 0 and result.stdout.strip():
        commit = result.stdout.split()[0]
        print(f"Recovering from commit {commit}")
        subprocess.run(["git", "checkout", commit, "--", ".grid/STATE.md"])
        return

    # 4. Create minimal state
    print("Creating minimal recovery state...")
    create_minimal_state()
```

---

## 10. Best Practices

### 10.1 DO

- Always use `update_state()` function, never edit file directly
- Check permissions before attempting write
- Validate state after complex updates
- Use atomic updates (all-or-nothing)
- Emit events after state changes
- Keep `updated_at` current

### 10.2 DON'T

- Never hold the state lock for more than 5 seconds
- Never update fields outside your permission scope
- Never skip validation
- Never modify the Markdown body programmatically
- Never delete STATE.md during active mission

### 10.3 Agent-Specific Guidelines

**Executor:**
- Update position after each thread
- Register in active agents on start
- Move to completed agents when done
- Add warnings for non-blocking issues

**Planner:**
- Update phase definitions after planning
- Record architectural decisions
- Update position when starting new phase

**Recognizer:**
- Add blockers for verification failures
- Add warnings for partial failures
- Never modify position or agents

**Memory:**
- Update tech_stack when packages added
- Record artifacts for shared resources
- Update decisions with long-term context

---

*End of STATE Schema Reference. End of Line.*
