<!-- SAGA-STAGING · part 97 -->
MAN TRIPPED (age=' + age + 'ms) -> zero intent + release');
        SD.deadManTripped = true;
        try{
          var R = window.ACTOR_RUNTIME;
          if(R){
            R.submitIntent("ai", {moveX:0, moveZ:0});
            R.releaseAI();
            R.authority = "legacy";
          }
        }catch(e){}
        SD.active = false;
        sdUpdateDiag();
      }
    }, DEAD_MAN_MS + 50);
  }

  /* Validate and apply incoming SSE intent */
  function sdOnIntent(data){
    var R = window.ACTOR_RUNTIME;
    if(!R || !SD.active || SD.sessionInvalidated) return;

    // 1. Epoch must match active session
    if(data.epoch !== SD.epoch){
      SD.lastRejection = 'epoch_mismatch';
      SD.rejectedCount++;
      sdLog('REJECT: epoch_mismatch');
      sdUpdateDiag();
      return;
    }
    // 2. Sequence must be monotonically increasing
    if(typeof data.seq !== 'number' || data.seq <= SD.lastSeq){
      SD.lastRejection = 'stale_seq seq=' + data.seq + ' last=' + SD.lastSeq;
      SD.rejectedCount++;
      sdLog('REJECT: ' + SD.lastRejection);
      sdUpdateDiag();
      return;
    }
    // 3. Command age must be < 500ms
    var age = Date.now() - data.ts;
    if(age > DEAD_MAN_MS){
      SD.lastRejection = 'expired age=' + age + 'ms';
      SD.rejectedCount++;
      sdLog('REJECT: ' + SD.lastRejection);
      sdUpdateDiag();
      return;
    }
    // 4. Safety Supervisor must be SAFE/PERMIT
    var sv = R.safetySupervisor;
    if(!sv || sv.status !== "SAFE" || !sv.permit){
      SD.lastRejection = 'safety_not_permit';
      SD.rejectedCount++;
      sdLog('REJECT: safety_not_permit -> zero intent');
      try{ R.submitIntent("ai", {moveX:0, moveZ:0}); }catch(e){}
      sdUpdateDiag();
      return;
    }
    // 5. Schema: moveX/moveZ finite numbers in [-1, 1]
    var mx = data.moveX, mz = data.moveZ;
    if(typeof mx !== 'number' || !isFinite(mx) || Math.abs(mx) > 1 ||
       typeof mz !== 'number' || !isFinite(mz) || Math.abs(mz) > 1){
      SD.lastRejection = 'bad_schema';
      SD.rejectedCount++;
      sdLog('REJECT: bad_schema');
      sdUpdateDiag();
      return;
    }

    // 6. Clamp to 2.0 u/s (WALK only, no jump/ascend/descend in Stage 2)
    var mag = Math.sqrt(mx*mx + mz*mz);
    if(mag > MAX_MAG){
      var scale = MAX_MAG / mag;
      mx *= scale;
      mz *= scale;
    }

    // 7. Ensure AI guarded authority is active
    if(R.authority !== "ai_guarded" || !R.ai.active){
      R.authority = "ai_guarded";
      R.ai.active = true;
      R.ai.agentId = "solid-drive";
      R.ai.control = "remote";
    }

    // 8. Submit through existing guarded path
    var ok = R.submitIntent("ai", {moveX: mx, moveZ: mz});
    if(!ok){
      SD.lastRejection = 'submit_rejected';
      SD.rejectedCount++;
      sdLog('REJECT: submitIntent returned false');
      sdUpdateDiag();
      return;
    }

    // Accepted
    SD.lastSeq = data.seq;
    SD.lastIntentAt = Date.now();
    SD.lastIntent = {moveX: mx, moveZ: mz};
    SD.lastRejection = null;
    SD.acceptedCount++;
    SD.deadManTripped = false;
    sdArmDeadMan(); // reset dead-man on every accepted intent
    sdUpdateDiag();
  }

  /* Human takeover detection: if human grabs control, invalidate session */
  function sdWatchHuman(){
    setInterval(function(){
      if(!SD.active || SD.sessionInvalidated) return;
      var R = window.ACTOR_RUNTIME;
      if(!R) return;
      // If input owner is human but we think AI should be driving,
      // a human has taken over outside the bridge -> invalidate
      if(R.input.owner === "human" && R.ai.active){
        sdLog('HUMAN TAKEOVER detected -> invalidating session ' + SD.epoch);
        SD.sessionInvalidated = true;
        SD.active = false;
        try{
          R.releaseAI();
          R.authority = "legacy";
          if(SD.sse){ SD.sse.close(); SD.sse = null; }
          if(SD.deadManTimer){ clearTimeout(SD.deadManTimer); SD.deadManTimer = null; }
        }catch(e){}
        sdUpdateDiag();
      }
    }, 100);
  }

  /* Diagnostics display */
  function sdUpdateDiag(){
    var R = window.ACTOR_RUNTIME;
    var d = document.getElementById('sd-diag');
    if(!d) return;
    var sv = R ? R.safetySupervisor : null;
    var age = SD.lastIntentAt ? (Date.now() - SD.lastIntentAt) : -1;
    var dmState = !SD.active ? 'inactive' :
      (SD.deadManTripped ? 'TRIPPED' :
      (age >= 0 && age > DEAD_MAN_MS ? 'TRIPPED' : 'ok'));
    d.textContent =
      'epoch: ' + (SD.epoch || 'none') + '\n' +
      'active: ' + SD.active + '  invalidated: ' + SD.sessionInvalidated + '\n' +
      'lastSeq: ' + SD.lastSeq + '  accepted: ' + SD.acceptedCount +
      '  rejected: ' + SD.rejectedCount + '\n' +
      'cmdAge: ' + (age >= 0 ? age + 'ms' : 'no cmd') +
      '  deadMan: ' + dmState + '\n' +
      'intent: mx=' + SD.lastIntent.moveX.toFixed(3) +
      ' mz=' + SD.lastIntent.moveZ.toFixed(3) + '\n' +
      'authority: ' + (R ? R.authority : '?') +
      '  owner: ' + (R ? R.inpu