mudra-skills 3.1.1 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/README.md +3 -2
  2. package/package.json +1 -1
  3. package/skills/mudra-master/SKILL.md +1 -1
  4. package/skills/mudra-master/mudra-preview/SKILL.md +45 -17
  5. package/skills/mudra-master/mudra-preview/assets/ar-menu.html +1 -1
  6. package/skills/mudra-master/mudra-preview/assets/document-scroller.html +2 -2
  7. package/skills/mudra-master/mudra-preview/assets/drum-machine.html +1 -1
  8. package/skills/mudra-master/mudra-preview/assets/emg-visualizer.html +6 -6
  9. package/skills/mudra-master/mudra-preview/assets/generative-art.html +1 -1
  10. package/skills/mudra-master/mudra-preview/assets/gesture-assistant.html +1 -1
  11. package/skills/mudra-master/mudra-preview/assets/gesture-speech.html +1 -1
  12. package/skills/mudra-master/mudra-preview/assets/hands-free-desktop.html +1 -1
  13. package/skills/mudra-master/mudra-preview/assets/model-rotator.html +1 -1
  14. package/skills/mudra-master/mudra-preview/assets/mudra-duel.html +48 -48
  15. package/skills/mudra-master/mudra-preview/assets/mudra-monitor.html +55 -55
  16. package/skills/mudra-master/mudra-preview/assets/mudra-ultimate-template.html +13 -13
  17. package/skills/mudra-master/mudra-preview/assets/music-sequencer.html +1 -1
  18. package/skills/mudra-master/mudra-preview/assets/neural-pong.html +1 -1
  19. package/skills/mudra-master/mudra-preview/assets/neural-snake.html +1 -1
  20. package/skills/mudra-master/mudra-preview/assets/presentation-controller.html +1 -1
  21. package/skills/mudra-master/mudra-preview/assets/pressure-painter.html +4 -4
  22. package/skills/mudra-master/mudra-preview/assets/runner.html +11 -11
  23. package/skills/mudra-master/mudra-preview/assets/smart-home.html +1 -1
  24. package/skills/mudra-master/mudra-preview/assets/space-invaders.html +1 -1
  25. package/skills/mudra-master/mudra-preview/assets/waterful-ring-toss.html +1 -1
  26. package/skills/mudra-master/mudra-preview/references/agent_protocol.json +224 -58
  27. package/skills/mudra-master/mudra-preview/references/prompt.md +373 -211
  28. package/skills/mudra-master/mudra-xr/SKILL.md +35 -11
  29. package/skills/mudra-master/mudra-xr/references/agent_protocol.json +180 -39
  30. package/skills/mudra-master/mudra-xr/references/prompt.md +70 -35
  31. package/skills/mudra-preview/SKILL.md +45 -17
  32. package/skills/mudra-preview/assets/ar-menu.html +1 -1
  33. package/skills/mudra-preview/assets/document-scroller.html +2 -2
  34. package/skills/mudra-preview/assets/drum-machine.html +1 -1
  35. package/skills/mudra-preview/assets/emg-visualizer.html +6 -6
  36. package/skills/mudra-preview/assets/generative-art.html +1 -1
  37. package/skills/mudra-preview/assets/gesture-assistant.html +1 -1
  38. package/skills/mudra-preview/assets/gesture-speech.html +1 -1
  39. package/skills/mudra-preview/assets/hands-free-desktop.html +1 -1
  40. package/skills/mudra-preview/assets/model-rotator.html +1 -1
  41. package/skills/mudra-preview/assets/mudra-duel.html +48 -48
  42. package/skills/mudra-preview/assets/mudra-monitor.html +55 -55
  43. package/skills/mudra-preview/assets/mudra-ultimate-template.html +13 -13
  44. package/skills/mudra-preview/assets/music-sequencer.html +1 -1
  45. package/skills/mudra-preview/assets/neural-pong.html +1 -1
  46. package/skills/mudra-preview/assets/neural-snake.html +1 -1
  47. package/skills/mudra-preview/assets/presentation-controller.html +1 -1
  48. package/skills/mudra-preview/assets/pressure-painter.html +4 -4
  49. package/skills/mudra-preview/assets/runner.html +11 -11
  50. package/skills/mudra-preview/assets/smart-home.html +1 -1
  51. package/skills/mudra-preview/assets/space-invaders.html +1 -1
  52. package/skills/mudra-preview/assets/waterful-ring-toss.html +1 -1
  53. package/skills/mudra-preview/references/agent_protocol.json +224 -58
  54. package/skills/mudra-preview/references/prompt.md +373 -211
  55. package/skills/mudra-xr/SKILL.md +35 -11
  56. package/skills/mudra-xr/references/agent_protocol.json +180 -39
  57. package/skills/mudra-xr/references/prompt.md +70 -35
@@ -193,24 +193,24 @@
193
193
  .button-stat-val { font-size: 1.1rem; font-weight: 700; color: var(--primary); }
194
194
  .button-stat-label { font-size: 0.68rem; color: var(--text-secondary); margin-top: 2px; }
195
195
 
196
- /* ── SNC Panel (wide) ── */
197
- .snc-panel { grid-column: 1 / 3; grid-row: 2; }
198
- .snc-graph-wrap { position: relative; height: 150px; margin-top: 4px; }
199
- .snc-canvas { width: 100%; height: 100%; display: block; border-radius: 8px; background: var(--card-inner); }
200
- .snc-legend {
196
+ /* ── EMG Panel (wide) ── */
197
+ .emg-panel { grid-column: 1 / 3; grid-row: 2; }
198
+ .emg-graph-wrap { position: relative; height: 150px; margin-top: 4px; }
199
+ .emg-canvas { width: 100%; height: 100%; display: block; border-radius: 8px; background: var(--card-inner); }
200
+ .emg-legend {
201
201
  display: flex; gap: 16px; margin-top: 8px; font-size: 0.75rem;
202
202
  }
203
- .snc-legend-item { display: flex; align-items: center; gap: 5px; }
204
- .snc-legend-dot { width: 8px; height: 8px; border-radius: 50%; }
205
- .snc-stats {
203
+ .emg-legend-item { display: flex; align-items: center; gap: 5px; }
204
+ .emg-legend-dot { width: 8px; height: 8px; border-radius: 50%; }
205
+ .emg-stats {
206
206
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-top: 8px;
207
207
  }
208
- .snc-stat {
208
+ .emg-stat {
209
209
  padding: 6px 8px; border-radius: 8px; background: var(--card-inner);
210
210
  border: 1px solid var(--border-dim); text-align: center;
211
211
  }
212
- .snc-stat-val { font-size: 1rem; font-weight: 700; font-family: 'JetBrains Mono', monospace; }
213
- .snc-stat-label { font-size: 0.68rem; color: var(--text-secondary); margin-top: 2px; }
212
+ .emg-stat-val { font-size: 1rem; font-weight: 700; font-family: 'JetBrains Mono', monospace; }
213
+ .emg-stat-label { font-size: 0.68rem; color: var(--text-secondary); margin-top: 2px; }
214
214
 
215
215
  /* ── Navigation / Motion Panel ── */
216
216
  .motion-panel { grid-column: 3; grid-row: 2; }
@@ -409,7 +409,7 @@
409
409
  .dashboard {
410
410
  grid-template-columns: 1fr 1fr;
411
411
  }
412
- .snc-panel { grid-column: 1 / 3; }
412
+ .emg-panel { grid-column: 1 / 3; }
413
413
  .motion-panel { grid-column: 1; grid-row: 3; }
414
414
  .imu-panel { grid-column: 1 / 3; grid-row: 4; }
415
415
  .controls-panel { grid-column: 2; grid-row: 3; }
@@ -417,7 +417,7 @@
417
417
  }
418
418
  @media (max-width: 700px) {
419
419
  .dashboard { grid-template-columns: 1fr; }
420
- .snc-panel, .imu-panel, .log-panel { grid-column: 1; }
420
+ .emg-panel, .imu-panel, .log-panel { grid-column: 1; }
421
421
  .motion-panel, .controls-panel { grid-column: 1; }
422
422
  .imu-graphs { grid-template-columns: 1fr; }
423
423
  }
@@ -518,29 +518,29 @@
518
518
  </div>
519
519
  </section>
520
520
 
521
- <!-- SNC Panel -->
522
- <section class="card snc-panel">
523
- <div class="card-title"><span class="icon">&#9876;</span> SNC — Surface Nerve Conductance</div>
524
- <div class="snc-graph-wrap">
525
- <canvas class="snc-canvas" id="sncCanvas"></canvas>
521
+ <!-- EMG Panel -->
522
+ <section class="card emg-panel">
523
+ <div class="card-title"><span class="icon">&#9876;</span> EMG — Surface Nerve Conductance</div>
524
+ <div class="emg-graph-wrap">
525
+ <canvas class="emg-canvas" id="sncCanvas"></canvas>
526
526
  </div>
527
- <div class="snc-legend">
528
- <div class="snc-legend-item"><div class="snc-legend-dot" style="background:#77eae9"></div>Ulnar</div>
529
- <div class="snc-legend-item"><div class="snc-legend-dot" style="background:#a78bfa"></div>Median</div>
530
- <div class="snc-legend-item"><div class="snc-legend-dot" style="background:#f472b6"></div>Radial</div>
527
+ <div class="emg-legend">
528
+ <div class="emg-legend-item"><div class="emg-legend-dot" style="background:#77eae9"></div>Ulnar</div>
529
+ <div class="emg-legend-item"><div class="emg-legend-dot" style="background:#a78bfa"></div>Median</div>
530
+ <div class="emg-legend-item"><div class="emg-legend-dot" style="background:#f472b6"></div>Radial</div>
531
531
  </div>
532
- <div class="snc-stats">
533
- <div class="snc-stat">
534
- <div class="snc-stat-val" id="sncUlnar" style="color:#77eae9">0.000</div>
535
- <div class="snc-stat-label">Ulnar</div>
532
+ <div class="emg-stats">
533
+ <div class="emg-stat">
534
+ <div class="emg-stat-val" id="sncUlnar" style="color:#77eae9">0.000</div>
535
+ <div class="emg-stat-label">Ulnar</div>
536
536
  </div>
537
- <div class="snc-stat">
538
- <div class="snc-stat-val" id="sncMedian" style="color:#a78bfa">0.000</div>
539
- <div class="snc-stat-label">Median</div>
537
+ <div class="emg-stat">
538
+ <div class="emg-stat-val" id="sncMedian" style="color:#a78bfa">0.000</div>
539
+ <div class="emg-stat-label">Median</div>
540
540
  </div>
541
- <div class="snc-stat">
542
- <div class="snc-stat-val" id="sncRadial" style="color:#f472b6">0.000</div>
543
- <div class="snc-stat-label">Radial</div>
541
+ <div class="emg-stat">
542
+ <div class="emg-stat-val" id="sncRadial" style="color:#f472b6">0.000</div>
543
+ <div class="emg-stat-label">Radial</div>
544
544
  </div>
545
545
  </div>
546
546
  </section>
@@ -607,9 +607,9 @@
607
607
  </div>
608
608
  </div>
609
609
  <div class="imu-legend">
610
- <div class="snc-legend-item"><div class="snc-legend-dot" style="background:#77eae9"></div>X Axis</div>
611
- <div class="snc-legend-item"><div class="snc-legend-dot" style="background:#a78bfa"></div>Y Axis</div>
612
- <div class="snc-legend-item"><div class="snc-legend-dot" style="background:#f472b6"></div>Z Axis</div>
610
+ <div class="emg-legend-item"><div class="emg-legend-dot" style="background:#77eae9"></div>X Axis</div>
611
+ <div class="emg-legend-item"><div class="emg-legend-dot" style="background:#a78bfa"></div>Y Axis</div>
612
+ <div class="emg-legend-item"><div class="emg-legend-dot" style="background:#f472b6"></div>Z Axis</div>
613
613
  </div>
614
614
  </section>
615
615
 
@@ -631,10 +631,10 @@
631
631
  <span class="sig-pkts" id="pkts-pressure">0</span>
632
632
  <div class="toggle-switch on" data-sub="pressure"></div>
633
633
  </div>
634
- <div class="toggle-row" data-signal="snc">
635
- <span class="sig-name">snc</span>
636
- <span class="sig-pkts" id="pkts-snc">0</span>
637
- <div class="toggle-switch on" data-sub="snc"></div>
634
+ <div class="toggle-row" data-signal="emg">
635
+ <span class="sig-name">emg</span>
636
+ <span class="sig-pkts" id="pkts-emg">0</span>
637
+ <div class="toggle-switch on" data-sub="emg"></div>
638
638
  </div>
639
639
  <div class="toggle-row" data-signal="battery">
640
640
  <span class="sig-name">battery</span>
@@ -721,7 +721,7 @@
721
721
  <button class="log-filter" data-filter="gesture">Gesture</button>
722
722
  <button class="log-filter" data-filter="pressure">Pressure</button>
723
723
  <button class="log-filter" data-filter="imu">IMU</button>
724
- <button class="log-filter" data-filter="snc">SNC</button>
724
+ <button class="log-filter" data-filter="emg">EMG</button>
725
725
  <button class="log-filter" data-filter="nav">Nav</button>
726
726
  <button class="log-filter" data-filter="cmd">Commands</button>
727
727
  </div>
@@ -754,9 +754,9 @@ let logFilter = "all";
754
754
  const pressureSamples = [];
755
755
 
756
756
  // Subscription tracking
757
- const activeSubs = new Set(["gesture", "pressure", "snc", "battery", "navigation", "button"]);
757
+ const activeSubs = new Set(["gesture", "pressure", "emg", "battery", "navigation", "button"]);
758
758
  const packetCounts = {};
759
- const ALL_SIGNALS = ["gesture", "pressure", "snc", "battery", "navigation", "button", "nav_direction", "imu_acc", "imu_gyro"];
759
+ const ALL_SIGNALS = ["gesture", "pressure", "emg", "battery", "navigation", "button", "nav_direction", "imu_acc", "imu_gyro"];
760
760
  const MOTION_CONFLICTS = {
761
761
  navigation: ["nav_direction", "imu_acc", "imu_gyro"],
762
762
  button: ["nav_direction", "imu_acc", "imu_gyro"],
@@ -773,7 +773,7 @@ const state = {
773
773
  navDirection: "None",
774
774
  imuAcc: [0, 0, 9.81],
775
775
  imuGyro: [0, 0, 0],
776
- snc: [0, 0, 0],
776
+ emg: [0, 0, 0],
777
777
  battery: { level: -1, charging: false }
778
778
  };
779
779
 
@@ -837,7 +837,7 @@ function connect() {
837
837
  try { ws = new WebSocket(WS_URL); } catch { setConn("err", "Invalid URL"); return; }
838
838
 
839
839
  ws.onopen = () => {
840
- setConn("on", "Connected to Mudra Companion");
840
+ setConn("on", "Connected to Mudra Link");
841
841
  subscribeAll();
842
842
  };
843
843
  ws.onclose = () => {
@@ -957,7 +957,7 @@ function switchMode(mode) {
957
957
  });
958
958
 
959
959
  // Also re-subscribe universal ones
960
- ["gesture", "pressure", "snc", "battery"].forEach(s => {
960
+ ["gesture", "pressure", "emg", "battery"].forEach(s => {
961
961
  if (activeSubs.has(s)) send({ command: "subscribe", signal: s });
962
962
  });
963
963
 
@@ -995,7 +995,7 @@ function routeMessage(msg) {
995
995
  else if (t === "nav_direction") onNavDirection(d);
996
996
  else if (t === "imu_acc") onImuAcc(d);
997
997
  else if (t === "imu_gyro") onImuGyro(d);
998
- else if (t === "snc") onSnc(d);
998
+ else if (t === "emg") onEmg(d);
999
999
  else if (t === "battery") onBattery(d);
1000
1000
 
1001
1001
  addLog(categorize(t), t, d);
@@ -1005,7 +1005,7 @@ function categorize(t) {
1005
1005
  if (t === "gesture") return "gesture";
1006
1006
  if (t === "pressure") return "pressure";
1007
1007
  if (t === "imu_acc" || t === "imu_gyro") return "imu";
1008
- if (t === "snc") return "snc";
1008
+ if (t === "emg") return "emg";
1009
1009
  if (t === "navigation" || t === "nav_direction" || t === "button") return "nav";
1010
1010
  return "other";
1011
1011
  }
@@ -1122,17 +1122,17 @@ function onImuGyro(d) {
1122
1122
  if (controlMode === "imu") projectImu();
1123
1123
  }
1124
1124
 
1125
- function onSnc(d) {
1125
+ function onEmg(d) {
1126
1126
  const v = Array.isArray(d.values) ? d.values : [0, 0, 0];
1127
- state.snc = [Number(v[0]||0), Number(v[1]||0), Number(v[2]||0)];
1127
+ state.emg = [Number(v[0]||0), Number(v[1]||0), Number(v[2]||0)];
1128
1128
 
1129
- pushRing(sncHistory.ch0, state.snc[0]);
1130
- pushRing(sncHistory.ch1, state.snc[1]);
1131
- pushRing(sncHistory.ch2, state.snc[2]);
1129
+ pushRing(sncHistory.ch0, state.emg[0]);
1130
+ pushRing(sncHistory.ch1, state.emg[1]);
1131
+ pushRing(sncHistory.ch2, state.emg[2]);
1132
1132
 
1133
- ui.sncUlnar.textContent = state.snc[0].toFixed(3);
1134
- ui.sncMedian.textContent = state.snc[1].toFixed(3);
1135
- ui.sncRadial.textContent = state.snc[2].toFixed(3);
1133
+ ui.sncUlnar.textContent = state.emg[0].toFixed(3);
1134
+ ui.sncMedian.textContent = state.emg[1].toFixed(3);
1135
+ ui.sncRadial.textContent = state.emg[2].toFixed(3);
1136
1136
  }
1137
1137
 
1138
1138
  function onBattery(d) {
@@ -370,7 +370,7 @@
370
370
  <div class="status-row">
371
371
  <div class="status" id="status">
372
372
  <span class="dot" id="statusDot"></span>
373
- <span id="statusText">Connecting to Mudra Companion…</span>
373
+ <span id="statusText">Connecting to Mudra Link…</span>
374
374
  </div>
375
375
  <span class="hand-chip none" id="handChip">None</span>
376
376
  </div>
@@ -416,7 +416,7 @@
416
416
  <div class="metric-value" id="motionValue">x:0 y:0</div>
417
417
  </div>
418
418
  <div class="metric">
419
- <div class="metric-label">SNC Energy</div>
419
+ <div class="metric-label">EMG Energy</div>
420
420
  <div class="metric-value" id="sncValue">0.00</div>
421
421
  <div class="bar"><span id="sncBar"></span></div>
422
422
  </div>
@@ -447,7 +447,7 @@
447
447
  const WS_URL = "ws://127.0.0.1:8766";
448
448
  const MAX_LOG_LINES = 80;
449
449
  const PRESSURE_WINDOW = 5;
450
- const SNC_BUFFER_SIZE = 500;
450
+ const EMG_BUFFER_SIZE = 500;
451
451
  const STATUS_POLL_INTERVAL = 2000;
452
452
  const BACKOFF_SCHEDULE = [1000, 2000, 5000, 10000];
453
453
 
@@ -479,7 +479,7 @@
479
479
  navY: 0,
480
480
  imuAcc: [0, 0, 9.81],
481
481
  imuGyro: [0, 0, 0],
482
- snc: [0, 0, 0],
482
+ emg: [0, 0, 0],
483
483
  navDirection: "None"
484
484
  };
485
485
 
@@ -604,7 +604,7 @@
604
604
  if (msg.type === "nav_direction") handleNavDirection(msg.data);
605
605
  if (msg.type === "imu_acc") handleImuAcc(msg.data);
606
606
  if (msg.type === "imu_gyro") handleImuGyro(msg.data);
607
- if (msg.type === "snc") handleSnc(msg.data);
607
+ if (msg.type === "emg") handleEmg(msg.data);
608
608
  }
609
609
 
610
610
  // ─── Connection label ─────────────────────────────────────────────────────
@@ -641,12 +641,12 @@
641
641
  case "in-use":
642
642
  el.classList.add("in-use");
643
643
  dot.style.background = "var(--error)";
644
- text.textContent = "Mudra Companion is already in use by another tab — please close it before continuing.";
644
+ text.textContent = "Mudra Link is already in use by another tab — please close it before continuing.";
645
645
  chip.textContent = "None";
646
646
  chip.classList.add("none");
647
647
  break;
648
648
  default: // "connecting"
649
- text.textContent = "Connecting to Mudra Companion…";
649
+ text.textContent = "Connecting to Mudra Link…";
650
650
  chip.textContent = "None";
651
651
  chip.classList.add("none");
652
652
  }
@@ -670,7 +670,7 @@
670
670
  // ─── Signal subscriptions ─────────────────────────────────────────────────
671
671
 
672
672
  function getActiveSignalNames() {
673
- const base = ["gesture", "pressure", "snc"];
673
+ const base = ["gesture", "pressure", "emg"];
674
674
  if (controlMode === "pointer") return [...base, "navigation", "button"];
675
675
  if (controlMode === "direction") return [...base, "nav_direction"];
676
676
  return [...base, "imu_acc", "imu_gyro"];
@@ -757,17 +757,17 @@
757
757
  render();
758
758
  }
759
759
 
760
- function handleSnc(data = {}) {
760
+ function handleEmg(data = {}) {
761
761
  const channels = Array.isArray(data.values) && data.values.length === 3
762
762
  ? data.values : [[0], [0], [0]];
763
763
  for (let i = 0; i < 3; i++) {
764
764
  sncBuffers[i].push(...channels[i]);
765
- if (sncBuffers[i].length > SNC_BUFFER_SIZE) {
766
- sncBuffers[i].splice(0, sncBuffers[i].length - SNC_BUFFER_SIZE);
765
+ if (sncBuffers[i].length > EMG_BUFFER_SIZE) {
766
+ sncBuffers[i].splice(0, sncBuffers[i].length - EMG_BUFFER_SIZE);
767
767
  }
768
768
  }
769
- state.snc = sncBuffers.map(buf => Number(buf[buf.length - 1] || 0));
770
- const energy = Math.min(1, (Math.abs(state.snc[0]) + Math.abs(state.snc[1]) + Math.abs(state.snc[2])) / 3);
769
+ state.emg = sncBuffers.map(buf => Number(buf[buf.length - 1] || 0));
770
+ const energy = Math.min(1, (Math.abs(state.emg[0]) + Math.abs(state.emg[1]) + Math.abs(state.emg[2])) / 3);
771
771
  ui.sncValue.textContent = energy.toFixed(2);
772
772
  ui.sncBar.style.width = `${Math.round(energy * 100)}%`;
773
773
  }
@@ -159,7 +159,7 @@ function triggerGesture(type) {
159
159
  else emit('gesture', { type, confidence: 0.95, timestamp: Date.now() });
160
160
  }
161
161
 
162
- /* ── Simulation (when Companion not reachable) ─────────────── */
162
+ /* ── Simulation (when Link not reachable) ─────────────── */
163
163
  function startSim() {
164
164
  if (simTimer) return;
165
165
  simulating = true;
@@ -141,7 +141,7 @@ function triggerGesture(type) {
141
141
  else emit('gesture', { type, confidence: 0.95, timestamp: Date.now() });
142
142
  }
143
143
 
144
- /* ── Simulation (when Companion not reachable) ─────────────── */
144
+ /* ── Simulation (when Link not reachable) ─────────────── */
145
145
  let simAutoServe = null;
146
146
  function startSim() {
147
147
  if (simTimer) return;
@@ -152,7 +152,7 @@ function triggerGesture(type) {
152
152
  else emit('gesture', { type, confidence: 0.95, timestamp: Date.now() });
153
153
  }
154
154
 
155
- /* ── Simulation (when Companion not reachable) ─────────────── */
155
+ /* ── Simulation (when Link not reachable) ─────────────── */
156
156
  function startSim() {
157
157
  if (simTimer) return;
158
158
  simulating = true;
@@ -183,7 +183,7 @@ function triggerGesture(type) {
183
183
  else emit('gesture', { type, confidence: 0.95, timestamp: Date.now() });
184
184
  }
185
185
 
186
- /* ── Simulation (when Companion not reachable) ─────────────── */
186
+ /* ── Simulation (when Link not reachable) ─────────────── */
187
187
  function startSim() {
188
188
  if (simTimer) return;
189
189
  simulating = true;
@@ -81,7 +81,7 @@
81
81
  <script>
82
82
  /* ── Mudra Protocol Connection (v2) ────────────────────────── */
83
83
  const WS_URL = 'ws://127.0.0.1:8766';
84
- const SIGNALS = ['pressure', 'gesture', 'snc'];
84
+ const SIGNALS = ['pressure', 'gesture', 'emg'];
85
85
 
86
86
  let ws, reconnectTimer, simTimer;
87
87
  let wsOpen = false, deviceReady = false, simulating = true;
@@ -127,7 +127,7 @@ function triggerGesture(type) {
127
127
  else emit('gesture', { type, confidence: 0.95, timestamp: Date.now() });
128
128
  }
129
129
 
130
- /* ── Simulation (when Companion not reachable) ─────────────── */
130
+ /* ── Simulation (when Link not reachable) ─────────────── */
131
131
  function startSim() {
132
132
  if (simTimer) return;
133
133
  simulating = true;
@@ -136,7 +136,7 @@ function startSim() {
136
136
  t += 0.05;
137
137
  const n = Math.max(0, Math.min(1, 0.3 + 0.25 * Math.sin(t * 0.7) + (Math.random() - 0.5) * 0.1));
138
138
  emit('pressure', { value: Math.round(n * 100), normalized: n, timestamp: Date.now() });
139
- emit('snc', {
139
+ emit('emg', {
140
140
  values: [
141
141
  0.3 * Math.sin(t * 1.3) + (Math.random() - 0.5) * 0.1,
142
142
  0.2 * Math.cos(t * 1.7) + (Math.random() - 0.5) * 0.1,
@@ -206,7 +206,7 @@ on('pressure', (d) => {
206
206
  pressFill.style.width = Math.round(pressure * 100) + '%';
207
207
  });
208
208
 
209
- on('snc', (d) => {
209
+ on('emg', (d) => {
210
210
  const vals = d.values || [0, 0, 0];
211
211
  const energy = (Math.abs(vals[0]) + Math.abs(vals[1]) + Math.abs(vals[2])) / 3;
212
212
  hue = Math.round((energy * 720) % 360);
@@ -619,11 +619,11 @@ body {
619
619
  <h2>The Ghost Trail</h2>
620
620
  <p class="tagline">See the gap between thought and action</p>
621
621
  <div class="controls-info">
622
- <p><span class="key ghost-key">Mudra SNC</span> = Ghost (Intent)</p>
622
+ <p><span class="key ghost-key">Mudra EMG</span> = Ghost (Intent)</p>
623
623
  <p><span class="key physical-key">Mouse Click</span> = Runner (Action)</p>
624
624
  </div>
625
625
  <div class="threshold-setting">
626
- <label for="threshold-slider">SNC Threshold</label>
626
+ <label for="threshold-slider">EMG Threshold</label>
627
627
  <div class="slider-container">
628
628
  <input type="range" id="threshold-slider" min="0.1" max="0.9" step="0.05" value="0.3">
629
629
  <span id="threshold-value">0.30</span>
@@ -632,7 +632,7 @@ body {
632
632
  <div id="pressure-bar"></div>
633
633
  <div id="threshold-marker"></div>
634
634
  </div>
635
- <span class="threshold-hint">Flex to test - bar shows live SNC magnitude</span>
635
+ <span class="threshold-hint">Flex to test - bar shows live EMG magnitude</span>
636
636
  </div>
637
637
  <button id="start-btn" class="game-btn">Start Run</button>
638
638
  <div id="title-connection-status">
@@ -852,11 +852,11 @@ class IntentRunner {
852
852
  this.ws = new WebSocket('ws://127.0.0.1:8766');
853
853
 
854
854
  this.ws.onopen = () => {
855
- console.log('Connected to Mudra Companion');
856
- // Subscribe to SNC (neuromuscular EMG) events
855
+ console.log('Connected to Mudra Link');
856
+ // Subscribe to EMG (neuromuscular EMG) events
857
857
  this.ws.send(JSON.stringify({
858
858
  command: 'subscribe',
859
- signal: 'snc'
859
+ signal: 'emg'
860
860
  }));
861
861
  };
862
862
 
@@ -869,9 +869,9 @@ class IntentRunner {
869
869
 
870
870
  if (data.type === 'connection_status' && data.data?.status === 'connected') {
871
871
  this.setMudraConnected(true);
872
- } else if (data.type === 'snc') {
873
- // Handle SNC (neuromuscular EMG) signal
874
- // SNC data is typically an array of values in range -1 to 1
872
+ } else if (data.type === 'emg') {
873
+ // Handle EMG (neuromuscular EMG) signal
874
+ // EMG data is typically an array of values in range -1 to 1
875
875
  const rawData = data.data;
876
876
  let magnitude = 0;
877
877
 
@@ -885,7 +885,7 @@ class IntentRunner {
885
885
  values = rawData.flat().filter(v => typeof v === 'number');
886
886
  } else if (typeof rawData === 'object' && rawData !== null) {
887
887
  // Try to find array or number in object
888
- const possibleKeys = ['value', 'values', 'data', 'snc', 'magnitude', 'samples'];
888
+ const possibleKeys = ['value', 'values', 'data', 'emg', 'magnitude', 'samples'];
889
889
  for (const key of possibleKeys) {
890
890
  if (rawData[key] !== undefined) {
891
891
  const val = rawData[key];
@@ -910,7 +910,7 @@ class IntentRunner {
910
910
  magnitude = Math.sqrt(sumSquares / values.length);
911
911
  }
912
912
 
913
- // SNC is in range -1 to 1, so magnitude should be 0 to 1
913
+ // EMG is in range -1 to 1, so magnitude should be 0 to 1
914
914
  // But clamp just in case
915
915
  magnitude = Math.max(0, Math.min(1, magnitude));
916
916
 
@@ -159,7 +159,7 @@ function triggerGesture(type) {
159
159
  else emit('gesture', { type, confidence: 0.95, timestamp: Date.now() });
160
160
  }
161
161
 
162
- /* ── Simulation (when Companion not reachable) ─────────────── */
162
+ /* ── Simulation (when Link not reachable) ─────────────── */
163
163
  function startSim() {
164
164
  if (simTimer) return;
165
165
  simulating = true;
@@ -365,7 +365,7 @@
365
365
  let msg;
366
366
  try { msg = JSON.parse(event.data); } catch { return; }
367
367
 
368
- // Connection status from Companion
368
+ // Connection status from Link
369
369
  if (msg.type === "connection_status") {
370
370
  mudra.deviceReady = msg.data?.status === "connected";
371
371
  setMudraStatus(mudra.deviceReady, mudra.deviceReady ? "Mudra Band ready" : "Connect your Mudra Band");
@@ -683,7 +683,7 @@
683
683
  ws = new WebSocket(WS_URL);
684
684
 
685
685
  ws.onopen = () => {
686
- setStatus(true, "Connected to Mudra Companion");
686
+ setStatus(true, "Connected to Mudra Link");
687
687
  // Subscribe to pressure (analog jet control)
688
688
  send({ command: "subscribe", signal: "pressure" });
689
689
  };