Grand Diomande Research · Full HTML Reader

EchelonCapture Integration with HandGuard

HandGuard and EchelonCapture can now **share the same latent stream** without redundant sensor uploads. Both apps receive the same `z(t)` latent state from CC-MCS and apply different policies.

Embodied Trajectory Systems research note backlog reference score 18 .md

Full Public Reader

EchelonCapture Integration with HandGuard

Date: 2025-12-15
Status: ✅ SHARED LATENT STREAM ENABLED

---

Overview

HandGuard and EchelonCapture can now share the same latent stream without redundant sensor uploads. Both apps receive the same `z(t)` latent state from CC-MCS and apply different policies.

Apple Watch (100Hz sensors)
    ↓
HandGuard uploads as "watch_left_handguard"
    ↓
CC-MCS computes z(t) for "watch_left_handguard"
    ↓
Broadcasts to ALL subscribers:
    ↓                           ↓
HandGuard                   EchelonCapture
(nail-biting policy)        (music control policy)

---

HandGuard Configuration ✅

Already configured in [CCConfig.swift](cc-handguard/Services/CloudBridge/CCConfig.swift):

swift
static let deviceID = "watch_left_handguard"

Both `CCBridgeManager` (upload) and `CCLatentSubscriber` (receive) use this shared device_id.

---

EchelonCapture Configuration

To enable EchelonCapture to receive the same latent stream as HandGuard, configure it to subscribe to the same device_id.

Option A: Subscribe Only (Recommended)

EchelonCapture does NOT upload, only subscribes to HandGuard's stream.

#### Location
Find the latent stream subscription code in EchelonCapture. This is likely in:
- `latent_subscriber.py` (Python)
- `LatentStreamManager.swift` (Swift)
- Or equivalent WebSocket connection code

Change Required

Before (unique device_id):

python
# Python example
DEVICE_ID = f"echelon_{uuid.uuid4()}"  # Random device
ws_url = f"wss://cc-mcs-headless.../visualization?device_id={DEVICE_ID}&subscribe=latent,trajectory"

After (shared device_id):

python
# Python example
DEVICE_ID = "watch_left_handguard"  # Match HandGuard
ws_url = f"wss://cc-mcs-headless.../visualization?device_id={DEVICE_ID}&subscribe=latent,trajectory"

Swift example:

swift
// Before
private let deviceID = "echelon_\(UUID().uuidString)"

// After
private let deviceID = "watch_left_handguard" // Match HandGuard

#### Result
- HandGuard uploads sensor data as `watch_left_handguard`
- CC-MCS broadcasts latent state for `watch_left_handguard`
- EchelonCapture subscribes to `watch_left_handguard`
- Both receive same `z(t)`, apply different policies
- **50

---

Option B: Upload from EchelonCapture (Alternative)

If you prefer EchelonCapture to handle uploads instead:

1. Disable HandGuard uploads:

swift
// In HandGuard CloudBridgeCoordinator.swift
// Comment out:
// await ccBridge.start()

2. Configure EchelonCapture to upload as `watch_left_handguard`:

python
DEVICE_ID = "watch_left_handguard"
# Upload sensors using this device_id

3. Configure HandGuard to subscribe only:

swift
// In HandGuard CloudBridgeCoordinator.swift
// Keep only:
await ccLatent.connect()
// Remove:
// await ccBridge.start()

Result: EchelonCapture uploads, both apps subscribe to same stream.

---

Backend Behavior

CC-MCS-Headless automatically broadcasts latent state to ALL WebSocket subscribers for a given device_id.

How it works:
1. One client uploads sensor data for `device_id=watch_left_handguard`
2. CC-MCS runs LIM-RPS equilibrium solver
3. CC-MCS broadcasts latent state via WebSocket to ALL clients subscribed to `watch_left_handguard`
4. Multiple clients can receive simultaneously

No backend changes needed - this is already supported!

---

Testing the Integration

### Step 1: Deploy HandGuard
1. Deploy HandGuard to iPhone + Apple Watch
2. Verify uploads working (check console for `✅ CCBridge: Connected`)
3. Verify latent stream working (check `✅ CCLatent: Connected`)

### Step 2: Configure EchelonCapture
1. Update device_id to `"watch_left_handguard"`
2. Remove upload code (optional)
3. Keep only latent subscription

### Step 3: Run Both Apps
1. Start HandGuard on iPhone
2. Start EchelonCapture on same iPhone (or different device)
3. Both should receive same latent state

Step 4: Verify Shared Stream

HandGuard Console:

✅ CCBridge: Uploaded 100 frames
📊 Latent state received (position: [0.23, -0.45, 0.12])

EchelonCapture Console:

📊 Latent state received (position: [0.23, -0.45, 0.12])  ← Same values!

Both should show identical position vectors at the same timestamps.

---

File Locations

### HandGuard
All configuration in one place:
- [CCConfig.swift](cc-handguard/Services/CloudBridge/CCConfig.swift)
- `deviceID = "watch_left_handguard"`
- Used by CCBridgeManager and CCLatentSubscriber

### EchelonCapture
Find and update your latent subscription code:
- Python: `latent_subscriber.py` or similar
- Swift: `LatentStreamManager.swift` or similar
- Change device_id to `"watch_left_handguard"`

---

Troubleshooting

### "EchelonCapture receives different latent state"
- Cause: Using different device_id
- Fix: Verify both apps use exact same device_id string

### "No latent states in EchelonCapture"
- Cause: HandGuard not uploading, or wrong device_id
- Fix:
1. Check HandGuard console shows `✅ CCBridge: Uploaded`
2. Verify device_id matches exactly
3. Check WebSocket URL includes correct device_id

### "Both apps uploading (redundant)"
- Cause: Both apps have upload code active
- Fix: Choose Option A (HandGuard uploads) or Option B (EchelonCapture uploads)
- Disable upload in one app

### "High battery drain"
- Cause: Both apps uploading sensor data
- Fix: Only one app should upload, both can subscribe
- 50

---

Advanced: Multiple Policy Apps

This architecture supports unlimited policy apps subscribing to the same latent stream:

Watch → HandGuard uploads as "watch_left_handguard"
            ↓
    CC-MCS computes z(t)
            ↓
    Broadcasts to ALL subscribers:
        ↓           ↓           ↓           ↓
    HandGuard   Echelon   GestureLog   Biofeedback
    (haptics)   (music)   (research)   (HRV)

Each app:
- Subscribes to same device_id
- Receives same latent state
- Applies its own policy
- Independent logic and UI

Benefits:
- Single sensor stream (minimal battery)
- Single upload (minimal network)
- Single computation (efficient)
- Multiple interpretations (flexible)

---

Device ID Naming Convention

Recommended format: `watch_{position}_{primary_app}`

Examples:
- `watch_left_handguard` - Left wrist, HandGuard primary
- `watch_right_echelon` - Right wrist, Echelon primary
- `watch_dual_performance` - Both wrists, performance app

Current: `watch_left_handguard`

To change: Edit `CCConfig.swift` line 40:

swift
static let deviceID = "watch_left_handguard"  // Change here

---

Migration Guide

From Separate Streams → Shared Stream

Step 1: Record current device_ids

bash
# HandGuard
echo "watch_left_handguard"

# EchelonCapture
# (find in your code)

Step 2: Choose primary uploader
- HandGuard (recommended) - already configured
- EchelonCapture - modify HandGuard to disable upload

Step 3: Update subscriber
- If HandGuard uploads → Update EchelonCapture device_id
- If EchelonCapture uploads → Update HandGuard device_id

Step 4: Test
- Run both apps
- Verify same latent state values
- Check battery usage (should drop ~50

---

Summary

Status: ✅ HandGuard configured for shared latent stream

Device ID: `watch_left_handguard` (in CCConfig.swift)

To integrate EchelonCapture:
1. Find latent subscription code
2. Change device_id to `"watch_left_handguard"`
3. Run both apps
4. Verify receiving same latent state

Benefits:
- 50
- 50
- Single computation
- Multiple policies

Files to Update:
- HandGuard: ✅ Already configured (CCConfig.swift)
- EchelonCapture: Update device_id in latent subscriber

---

Ready to integrate! Update EchelonCapture device_id and both apps will share the same latent stream. 🚀

Promotion Decision

Keep in the searchable backlog until it intersects a live paper or system.

Source Anchor

Comp-Core/apps/ios/cc-handguard/ECHELON_INTEGRATION.md

Detected Structure

Method · Figures · Code Anchors · Architecture