Grand Diomande Research · Full HTML Reader

Integration Plan — Migrating to the Unified Agent OS

1. **Additive, not destructive** — New system reads legacy files; legacy systems continue unchanged until verified. 2. **Dual-write, then cutover** — During migration, both old and new storage are written to. Reads shift to new system first, writes follow. 3. **Each phase has a rollback** — If something breaks, revert by pointing back to legacy files. 4. **Test with real data** — Each phase runs against actual `[home-path]`, `[home-path]`, and `[home-path]`.

Agents That Account for Themselves technical note experiment writeup candidate score 36 .md

Full Public Reader

Integration Plan — Migrating to the Unified Agent OS

> Step-by-step migration from separate systems to UAOS.
> Each phase is independently deployable. No big-bang cutover.

---

Migration Philosophy

1. Additive, not destructive — New system reads legacy files; legacy systems continue unchanged until verified.
2. Dual-write, then cutover — During migration, both old and new storage are written to. Reads shift to new system first, writes follow.
3. Each phase has a rollback — If something breaks, revert by pointing back to legacy files.
4. Test with real data — Each phase runs against actual `[home-path]`, `[home-path]`, and `[home-path]`.

---

Phase 0: Foundation (Day 1)

Goal: Create the UAOS directory structure and state database without touching existing systems.

Steps

1. Create UAOS directory

bash
   mkdir -p [home-path] [home-path]

2. Initialize SQLite database

bash
   # Create state.db with full schema from SHARED_STATE_SCHEMA.md
   sqlite3 [home-path] < schema.sql

3. Write config.yaml
- Copy template from SHARED_STATE_SCHEMA.md
- Adjust paths for this machine
- Set `dual_max.enabled: true`

4. Create the `uaos` Python package

   [home-path]
   ├── uaos/
   │   ├── __init__.py
   │   ├── db.py           # SQLite wrapper
   │   ├── events.py       # EventBus
   │   ├── config.py       # Config loader
   │   ├── context.py      # SharedContext + ContextBuilder
   │   └── adapters/
   │       ├── __init__.py
   │       ├── pulse.py     # PulseSessionAdapter
   │       ├── dream.py     # DreamAdapter
   │       └── heartbeat.py # HeartbeatAdapter
   └── schema.sql

5. Verify

bash
   python3 -c "import sqlite3; db = sqlite3.connect('[home-path]); print(db.execute('SELECT name FROM sqlite_master WHERE type=\"table\"').fetchall())"
   # Should list: entities, events, handoffs, tags, sessions, iterations, ...

### Rollback
Delete `[home-path]`. No other systems affected.

### Definition of Done
- [ ] `[home-path]` exists with all tables
- [ ] `[home-path]` is valid
- [ ] `uaos` package is importable
- [ ] No existing system is modified

---

Phase 1: Import Historical State (Day 2-3)

Goal: Populate the state DB with all existing data from Pulse sessions, Dream Weaver dreams, and Heartbeat state. Read-only — no existing files modified.

Steps

1. Import Pulse sessions

python
   # scripts/import_pulse.py
   from pathlib import Path
   from uaos.adapters.pulse import PulseSessionAdapter
   from uaos.db import StateDB

   db = StateDB()
   sessions_dir = Path.home() / ".pulse" / "sessions"

   for session_file in sessions_dir.glob("*.json"):
       rows = PulseSessionAdapter.from_legacy(session_file)
       db.upsert_entity(rows['entity'])
       db.upsert_session(rows['session'])
       print(f"  Imported: {rows['session']['project_name']}")

   print(f"Total sessions imported: {db.count('sessions')}")

2. Import Noosphere dreams

python
   # scripts/import_dreams.py
   from uaos.adapters.dream import DreamAdapter
   from uaos.db import StateDB
   import json

   db = StateDB()
   dreams_file = Path.home() / ".claude" / "noosphere" / "dreams.json"

   if dreams_file.exists():
       data = json.loads(dreams_file.read_text())
       for dream in data.get('dreams', []):
           rows = DreamAdapter.from_noosphere(dream)
           db.upsert_entity(rows['entity'])
           db.upsert_dream(rows['dream'])
           for tag in rows['tags']:
               db.upsert_tag(tag)
           print(f"  Imported dream: {dream['seed_idea'][:50]}")

   # Also import completed dreams from daemon
   dreams_dir = Path.home() / ".claude" / "dream-weaver" / "dreams"
   for dream_file in dreams_dir.glob("dream_*.json"):
       # ... similar import logic

3. Import Heartbeat state

python
   # scripts/import_heartbeat.py
   from uaos.adapters.heartbeat import HeartbeatAdapter
   from uaos.db import StateDB
   import json

   db = StateDB()
   state_file = Path.home() / "memory" / "heartbeat-state.json"

   if state_file.exists():
       state = json.loads(state_file.read_text())
       domains = HeartbeatAdapter.from_legacy(state)
       for domain in domains:
           db.upsert_check_domain(domain)

4. Import Connection Graph

bash
   # Copy noosphere graph to UAOS location
   cp [home-path] [home-path] 2>/dev/null || true

5. Verify imports

sql
   SELECT type, COUNT(*) FROM entities GROUP BY type;
   -- Should show sessions, dreams, checks

   SELECT COUNT(*) FROM tags;
   -- Should show keywords from dreams

   SELECT domain, last_checked_at FROM check_domains;
   -- Should show heartbeat domains

### Rollback
Drop and recreate tables in state.db. No legacy files touched.

### Definition of Done
- [ ] All Pulse sessions from `[home-path]` are in state.db
- [ ] All Noosphere dreams are in state.db
- [ ] Heartbeat domains are configured in state.db
- [ ] Connection graph copied to `[home-path]`
- [ ] `uaos.context.build()` returns a populated SharedContext
- [ ] Legacy files are untouched

---

Phase 2: Event Bus + Listeners (Day 4-5)

Goal: Implement the event bus and wire up cross-system listeners. Events are published but systems still use legacy state for reads.

Steps

1. Implement EventBus class

python
   # uaos/events.py
   class EventBus:
       def __init__(self, db: StateDB):
           self.db = db
           self._subscribers = defaultdict(list)

       def publish(self, topic, source, payload, entity_id=None, trace_id=None):
           event = {...}
           self.db.insert_event(event)
           self._dispatch(topic, event)

       def subscribe(self, pattern, handler):
           self._subscribers[pattern].append(handler)

       def _dispatch(self, topic, event):
           for pattern, handlers in self._subscribers.items():
               if self._matches(pattern, topic):
                   for handler in handlers:
                       try:
                           handler(event)
                       except Exception as e:
                           log(f"Handler error for {topic}: {e}")

2. Wire up cross-system listeners

python
   # uaos/listeners.py

   def setup_listeners(bus: EventBus, db: StateDB):
       """Register all cross-system event handlers."""

       # Dream emergence → Heartbeat alert
       @bus.subscribe('dream.emerged')
       def on_dream_emerged(event):
           db.insert_check_result({
               'domain': 'dreamWeaver',
               'status': 'ok',
               'alert_level': 8,
               'details': json.dumps({
                   'type': 'dream_emerged',
                   'dream_id': event['entity_id'],
                   'message': f"Dream emerged: {event['payload'].get('seed_idea', '')[:50]}"
               })
           })

       # Dream metamorphosis ready → Log for Cadence review
       @bus.subscribe('dream.metamorphosis.ready')
       def on_metamorphosis_ready(event):
           db.insert_handoff({
               'id': generate_id('ho'),
               'from_system': 'dream_weaver',
               'to_system': 'pulse',
               'from_entity_id': event['entity_id'],
               'handoff_type': 'metamorphosis',
               'payload': event['payload'],
               'status': 'pending',
               'priority': 7,
           })

       # Pulse iteration complete → Feed to Mycelium
       @bus.subscribe('pulse.iteration.completed')
       def on_iteration_completed(event):
           summary = event['payload'].get('summary', '')
           keywords = extract_keywords(summary)
           for kw in keywords:
               db.update_sensing_pattern(kw, {
                   'source': 'pulse',
                   'timestamp': event['timestamp'],
                   'snippet': summary[:200]
               })

       # Heartbeat alert (critical) → Cadence escalation
       @bus.subscribe('heartbeat.alert')
       def on_critical_alert(event):
           level = event['payload'].get('alert_level', 0)
           if level >= 9:
               db.insert_agent_message({
                   'id': generate_id('msg'),
                   'agent_id': 'higher_level',
                   'direction': 'inbox',
                   'msg_type': 'REQUEST',
                   'subject': f"Critical alert: {event['payload'].get('domain', 'unknown')}",
                   'body': json.dumps(event['payload']),
                   'priority': 'High',
                   'status': 'PENDING',
               })

3. Add event publishing to import scripts
- When importing historical data, also create retroactive events so the event log has history

4. Test event flow

python
   # Test: publish a dream.emerged event and verify heartbeat alert is created
   bus.publish('dream.emerged', 'dream_weaver', {
       'seed_idea': 'test dream',
       'connection_strength': 0.75
   }, entity_id='dream_test_123')

   alerts = db.query_check_results(domain='dreamWeaver', limit=1)
   assert alerts[0]['alert_level'] == 8

### Rollback
Remove listener registrations. Event bus is passive — removing it changes nothing.

### Definition of Done
- [ ] EventBus publishes and persists events
- [ ] 4 cross-system listeners are wired up
- [ ] Events table has data
- [ ] Test suite passes for each listener

---

Phase 3: Dual-Write Adapters (Day 6-8)

Goal: Modify existing systems to dual-write — continue writing legacy files AND publish events / write to state.db.

Steps

1. Patch `dual_runner.py` to publish events

python
   # At the top of dual_runner.py, add:
   try:
       from uaos.events import EventBus
       from uaos.db import StateDB
       uaos_db = StateDB()
       uaos_bus = EventBus(uaos_db)
       UAOS_ENABLED = True
   except ImportError:
       UAOS_ENABLED = False

   # In run_iteration(), after updating session:
   if UAOS_ENABLED:
       uaos_bus.publish('pulse.iteration.completed', 'pulse', {
           'session_id': session.id,
           'iteration': session.current_iteration,
           'signal': signal,
           'summary': output[:500]
       }, entity_id=session.id)

2. Patch Dream Weaver `daemon.py` to publish events

python
   # In daemon.py main loop, after each iteration:
   if UAOS_ENABLED:
       uaos_bus.publish('dream.evolved', 'dream_weaver', {
           'dream_id': incubation_id,
           'iteration': result.get('current_iteration'),
           'status': result.get('status')
       }, entity_id=incubation_id)

       if status == 'complete':
           uaos_bus.publish('dream.emerged', 'dream_weaver', {
               'dream_id': incubation_id,
               'seed_idea': result.get('idea', '')
           }, entity_id=incubation_id)

3. Patch Heartbeat check to publish events

python
   # In the main agent's heartbeat handler, after each check:
   if UAOS_ENABLED:
       uaos_bus.publish('heartbeat.check.completed', 'heartbeat', {
           'domain': domain,
           'status': check_status,
           'alert_level': alert_level
       })

4. Add state.db writes alongside legacy file writes
- `save_session()` in `dual_runner.py` → also writes to `sessions` table
- Dream Weaver incubation save → also writes to `dreams` table
- Heartbeat state save → also writes to `check_results` table

5. Verify dual-write consistency

python
   # scripts/verify_sync.py
   # Compare every legacy file against state.db rows
   # Report any discrepancies

### Rollback
Remove the UAOS import blocks. Existing systems fall back to legacy-only writes.

### Definition of Done
- [ ] `dual_runner.py` publishes Pulse events to UAOS
- [ ] Dream Weaver daemon publishes evolution events
- [ ] Heartbeat publishes check results
- [ ] `verify_sync.py` shows zero discrepancies
- [ ] Legacy files continue to be written (backward compat)

---

Phase 4: Unified Daemon (Day 9-12)

Goal: Replace the Dream Weaver daemon with a unified UAOS daemon that runs all subsystem loops.

Steps

1. Create `[home-path]`

python
   #!/usr/bin/env python3
   """
   Unified Agent OS Daemon

   Replaces:
   - Dream Weaver daemon.py (evolution loop)
   - Noosphere bridge sync
   - Heartbeat state management

   Adds:
   - Event processing loop
   - Handoff monitoring
   - Account usage tracking
   """

   import asyncio
   import signal
   from uaos.db import StateDB
   from uaos.events import EventBus
   from uaos.config import load_config
   from uaos.loops import (
       dream_evolution_loop,
       heartbeat_check_loop,
       event_processing_loop,
       handoff_monitor_loop,
       account_reset_loop,
   )

   async def main():
       config = load_config()
       db = StateDB(config.database.path)
       bus = EventBus(db)
       setup_listeners(bus, db)

       # Start all loops
       tasks = [
           asyncio.create_task(dream_evolution_loop(db, bus, config)),
           asyncio.create_task(heartbeat_check_loop(db, bus, config)),
           asyncio.create_task(event_processing_loop(db, bus, config)),
           asyncio.create_task(handoff_monitor_loop(db, bus, config)),
           asyncio.create_task(account_reset_loop(db, config)),
       ]

       bus.publish('system.startup', 'uaos', {'loops': len(tasks)})

       await asyncio.gather(*tasks)

   if __name__ == '__main__':
       asyncio.run(main())

2. Port Dream Weaver daemon logic to `uaos/loops/dream_evolution.py`
- Keep exact same incubation logic from `incubator.py`
- Replace file I/O with state.db reads/writes
- Publish events instead of writing to daemon.log

3. Port Heartbeat logic to `uaos/loops/heartbeat_check.py`
- Parse HEARTBEAT.md for check definitions
- Run checks against check_domains table
- Write results to check_results table
- Publish events for alerts

4. Create handoff monitor `uaos/loops/handoff_monitor.py`
- Check for pending handoffs every 5 minutes
- Auto-accept metamorphosis handoffs if configured
- Expire handoffs older than 24h

5. Stop old Dream Weaver daemon, start UAOS daemon

bash
   # Stop old daemon
   python3 [home-path] stop

   # Start unified daemon
   python3 [home-path] start

6. Verify daemon health

bash
   # Check PID
   cat [home-path]

   # Check logs
   tail -20 [home-path]

   # Check events
   sqlite3 [home-path] "SELECT topic, COUNT(*) FROM events GROUP BY topic ORDER BY COUNT(*) DESC"

### Rollback
Stop UAOS daemon, restart Dream Weaver daemon. Event bus stops but no data is lost.

### Definition of Done
- [ ] UAOS daemon runs with all 5 loops
- [ ] Dream evolution continues at same cadence
- [ ] Heartbeat checks run on schedule
- [ ] Handoff monitor catches pending handoffs
- [ ] Old daemon is stopped
- [ ] `uaos.context.build()` returns live data

---

Phase 5: Unified MCP Server (Day 13-15)

Goal: Create a single MCP server that exposes all subsystem tools under the `uaos.*` namespace.

Steps

1. Create `[home-path]`
- Import tool handlers from each subsystem
- Wrap in unified namespace: `uaos.pulse.start`, `uaos.dream.incubate`, etc.
- Add new cross-system tools: `uaos.context`, `uaos.handoff`, `uaos.events.query`, `uaos.lineage`

2. Register with Claude Desktop

json
   // In claude_desktop_config.json
   {
     "mcpServers": {
       "uaos": {
         "command": "python3",
         "args": ["[home-path]
         "env": {}
       }
     }
   }

3. Deprecate old MCP servers (but don't remove yet)
- Keep `dream-weaver` and `pulse` MCP servers as fallbacks
- Add deprecation notice in their responses

4. Verify all tools work

   # Test each tool category:
   uaos.pulse.start → creates session in state.db
   uaos.pulse.status → reads from state.db
   uaos.dream.incubate → creates dream in state.db
   uaos.dream.evolve → advances dream, publishes event
   uaos.context → returns SharedContext
   uaos.handoff.create → creates handoff record
   uaos.events.query → queries event log

### Rollback
Remove `uaos` from MCP config, re-enable old servers.

### Definition of Done
- [ ] Single MCP server serves all tools
- [ ] `uaos.context` returns live cross-system state
- [ ] `uaos.handoff.create` enables formal dream→pulse metamorphosis
- [ ] `uaos.lineage` traces entity history across systems
- [ ] Old MCP servers still work as fallback

---

Phase 6: Remove Legacy Paths (Day 16-20)

Goal: Stop dual-writing. State.db becomes the single source of truth. Legacy paths become read-only symlinks.

Steps

1. Create compatibility symlinks

bash
   # Pulse sessions: generate JSON files from state.db on read
   # (implement a FUSE mount or a simpler file-watcher approach)

2. Remove dual-write from `dual_runner.py`
- Pulse reads/writes exclusively from state.db
- Legacy `sessions/*.json` files are generated on-demand for backward compat

3. Remove `noosphere_bridge.py`
- The bridge is no longer needed — noosphere dreams live in state.db
- Connection graph still lives in `graph.json` (too graph-specific for SQL)

4. Remove legacy heartbeat-state.json writes
- Heartbeat reads check schedules from state.db
- `HEARTBEAT.md` remains as the human-readable config

5. Archive old files

bash
   mkdir -p [home-path]
   cp -r [home-path] [home-path]
   cp [home-path] [home-path]
   cp [home-path] [home-path]

6. Remove old Dream Weaver daemon files

bash
   # daemon.py, daemon.pid, daemon.log from [home-path]
   # These are superseded by [home-path]

### Rollback
Restore files from `[home-path]` and re-enable dual-write.

### Definition of Done
- [ ] State.db is the single source of truth
- [ ] No more dual-writing
- [ ] Legacy files archived
- [ ] All subsystems read from state.db
- [ ] `noosphere_bridge.py` is removed
- [ ] System runs stable for 48h

---

Phase 7: Enriched Spawn Integration (Day 21-23)

Goal: Update `enriched_spawn.py` to include cross-system context from UAOS.

Steps

1. Add UAOS context to enriched prompts

python
   # In enriched_spawn.py, add after project context:

   def get_uaos_context_block() -> str:
       """Get cross-system context for enriched prompts."""
       try:
           from uaos.context import ContextBuilder
           from uaos.db import StateDB
           ctx = ContextBuilder(StateDB()).build()
           return f"""
   ## UAOS Context
   {ctx.brief()}

   Active Dreams: {len(ctx.gestating_dreams)} gestating, {len(ctx.metamorphosis_ready)} ready
   Active Sessions: {len(ctx.active_sessions)}
   Hot Keywords: {', '.join(ctx.hot_keywords[:5])}
   """
       except Exception:
           return ""

2. Feed dream context into metamorphosis sessions
- When a Pulse session is born from a dream metamorphosis, the enriched prompt includes:
- Dream synthesis
- Explored approaches
- Related plans found during incubation
- Connection graph neighbors

3. Feed Pulse learnings back to dreams
- After each iteration, extract keywords and summaries
- Update sensing patterns in state.db
- Strengthen connections to related dreams

### Definition of Done
- [ ] Enriched prompts include UAOS context
- [ ] Metamorphosis sessions have full dream context
- [ ] Pulse iteration summaries feed back to sensing patterns

---

Phase 8: Cadence Full Integration (Day 24-28)

Goal: Integrate Cadence multi-agent coordination as the orchestration layer.

Steps

1. Register agents in state.db
- `higher_level` agent with escalation capabilities
- `lower_level` agent with implementation capabilities
- `pulse_worker` agent(s) for autonomous dev
- `dream_weaver` agent for incubation

2. Migrate `cadence_bridge.py` to UAOS
- INBOX/OUTBOX detection → event bus subscriptions
- Decision sync → state.db decisions table
- Supabase sync → optional external sync from state.db

3. Implement priority queue
- Cadence router evaluates incoming handoffs against:
- Current Pulse session load
- Account usage limits
- Priority of the request
- Quiet hours
- Decides: accept now, queue for later, or reject

4. Test orchestration flows
- Dream → metamorphosis → Cadence approval → Pulse session
- Heartbeat critical alert → Cadence escalation → human notification
- Cadence delegation → Pulse worker assignment

### Definition of Done
- [ ] All agents registered in state.db
- [ ] Cadence bridge migrated from hook to UAOS listener
- [ ] Priority queue works for handoff routing
- [ ] End-to-end orchestration flows tested

---

Phase 9: Observability & Polish (Day 29-30)

Goal: Dashboard, monitoring, and documentation.

Steps

1. Implement `uaos dashboard` CLI command

bash
   python3 [home-path] dashboard
   # Shows the ASCII dashboard from ARCHITECTURE.md

2. Add metrics collection
- Events per hour by topic
- Average iteration duration
- Dream-to-bloom time
- Handoff completion rate

3. Write operational docs
- How to start/stop the daemon
- How to query the event log
- How to create manual handoffs
- Troubleshooting guide

4. Update HEARTBEAT.md
- Replace Dream Weaver daemon check with UAOS daemon check
- Add UAOS-specific health checks

5. Update AGENTS.md
- Document UAOS as the unified platform
- Update sub-agent spawning instructions

### Definition of Done
- [ ] Dashboard CLI works
- [ ] Metrics are queryable
- [ ] HEARTBEAT.md updated
- [ ] AGENTS.md updated
- [ ] All documentation complete

---

Timeline Summary

PhaseDaysRiskDependencies
0: Foundation1LowNone
1: Import Historical2LowPhase 0
2: Event Bus2LowPhase 0
3: Dual-Write3MediumPhase 1, 2
4: Unified Daemon4MediumPhase 3
5: Unified MCP3MediumPhase 4
6: Remove Legacy5HighPhase 5, 48h stability
7: Enriched Spawn3LowPhase 4
8: Cadence Integration5MediumPhase 5
9: Observability2LowPhase 6
Total~30 days

Critical Path

Phase 0 ──▶ Phase 1 ──▶ Phase 3 ──▶ Phase 4 ──▶ Phase 5 ──▶ Phase 6
                    └──▶ Phase 2 ──┘         └──▶ Phase 7
                                              └──▶ Phase 8 ──▶ Phase 9

---

Risk Register

RiskImpactMitigation
SQLite corruption during daemon crashHighWAL mode + daily backups + graceful shutdown handlers
Dual-write inconsistencyMediumVerify script runs after every write, reconciliation job
Event bus overwhelms DB with writesLowBatch inserts, configurable buffer, event rotation
Legacy system breaks during migrationHighEach phase has explicit rollback steps
Noosphere graph too large for JSONLowOnly if >10K nodes; migrate to SQLite virtual table if needed
Rate limits exceeded during migrationMediumAccount usage tracking preserved from dual_runner.py

---

Success Criteria

The migration is complete when:

1. ✅ All Pulse sessions, Dream Weaver dreams, and Heartbeat checks live in `[home-path]`
2. ✅ A single daemon (`[home-path]`) runs all background loops
3. ✅ A single MCP server exposes all tools under `uaos.*` namespace
4. ✅ Cross-system handoffs work (dream → pulse metamorphosis)
5. ✅ Enriched spawn prompts include cross-system context
6. ✅ Event log captures all inter-system communication
7. ✅ Cadence orchestrates priority and routing
8. ✅ `uaos.context` returns a complete cross-system snapshot
9. ✅ No legacy bridge scripts (`noosphere_bridge.py`) needed
10. ✅ System is stable for 7 consecutive days

Promotion Decision

Attach run IDs, datasets, metrics, and reproduction commands.

Source Anchor

projects/dream-metamorphosis/unified-agent-os/INTEGRATION_PLAN.md

Detected Structure

Method · Evaluation · Figures · Code Anchors · Architecture