mudra-skills 3.0.7 → 3.0.8

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mudra-skills",
3
- "version": "3.0.7",
3
+ "version": "3.0.8",
4
4
  "description": "Mudra Band skills for Claude Code, Codex, and Antigravity — 2D, 3D/XR, or auto-classified",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: mudra-master
3
- version: 3.0.0
3
+ version: 3.0.1
4
4
  description: Master router for Mudra Band app builds. Use when the user describes an app, experience, prototype, timer, counter, or tool to build with the Mudra Band but has not made clear whether they want a 2D (flat/screen) or 3D (spatial/XR/VR/AR) version. This skill classifies the prompt deterministically and hands off the original prompt verbatim to either mudra-preview (2D) or mudra-xr (3D), asking exactly one 2D-or-3D disambiguation question only when the dimension cannot be inferred. Do not use for pure code edits, repo questions, or any request that is not a Mudra-app build.
5
5
  ---
6
6
  # Mudra Master Skill
@@ -13,7 +13,7 @@ This skill emits no app artifacts of its own. Its sole outputs are a routing dec
13
13
 
14
14
  Activate when the user:
15
15
 
16
- - Describes something they want to **build / make / create / prototyp e** with the Mudra Band — an app, experience, tool, timer, counter, demo, game, dashboard, visualizer, panel, or scene — AND
16
+ - Describes something they want to **build / make / create / prototype** with the Mudra Band — an app, experience, tool, timer, counter, demo, game, dashboard, visualizer, panel, or scene — AND
17
17
  - Has not made clear whether they want a 2D (screen-based) or 3D (spatial / XR / VR / AR) version.
18
18
 
19
19
  ### The verbatim-prompt rule (FR-012)
@@ -43,8 +43,6 @@ Before running any rule: if the trimmed prompt is **empty**, do NOT run the clas
43
43
 
44
44
  ### 3D cue tokens
45
45
 
46
- **Fixed built-in constant. Changing this list requires a new `version` bump in this SKILL.md's frontmatter (FR-018).**
47
-
48
46
  Whole-word match (case-insensitive): `XR`, `VR`, `AR`.
49
47
 
50
48
  Contiguous-substring match (case-insensitive): `immersive`, `spatial`, `room-scale`, `world-space`, `in 3d space`, `headset`, `stereo`.
@@ -53,8 +51,6 @@ Rule-5 evaluation order is the order above: `XR` is checked first, then `VR`, `A
53
51
 
54
52
  ### 2D cue tokens
55
53
 
56
- **Fixed built-in constant. Changing this list requires a new `version` bump in this SKILL.md's frontmatter (FR-018).**
57
-
58
54
  Whole-word match (case-insensitive): `flat`, `HUD`.
59
55
 
60
56
  Contiguous-substring match (case-insensitive): `on-screen`, `on my screen`, `dashboard`, `screen-based`.
@@ -649,7 +649,7 @@
649
649
  "code_examples": {
650
650
  "javascript": {
651
651
  "description": "Basic WebSocket connection and signal handling (new Dart server protocol)",
652
- "code": "const ws = new WebSocket('ws://127.0.0.1:8766');\nconst subscriptionRecord = new Set();\nconst backoffSchedule = [1000, 2000, 5000, 10000];\nlet backoffIndex = 0;\nlet suppressReconnect = false;\nlet reconnectTimer = null;\nlet lastBandConnected = false;\n\nfunction subscribe(signal) {\n subscriptionRecord.add(signal);\n ws.send(JSON.stringify({ command: 'subscribe', signal }));\n}\n\nfunction connect() {\n const socket = new WebSocket('ws://127.0.0.1:8766');\n\n socket.onopen = () => {\n backoffIndex = 0;\n socket.send(JSON.stringify({ command: 'get_status' }));\n subscriptionRecord.forEach(signal => socket.send(JSON.stringify({ command: 'subscribe', signal })));\n };\n\n socket.onmessage = (event) => {\n const msg = JSON.parse(event.data);\n if (msg.type === 'status') {\n const bandConnected = Boolean(msg.data.device.firmware && msg.data.device.serial_number);\n const hand = bandConnected ? msg.data.device.hand : 'None';\n updateConnectionLabel(bandConnected, hand);\n if (bandConnected && !lastBandConnected) {\n // Band just reconnected — replay subscriptions (FR-018a)\n subscriptionRecord.forEach(signal => socket.send(JSON.stringify({ command: 'subscribe', signal })));\n }\n lastBandConnected = bandConnected;\n }\n if (msg.type === 'error' && msg.data.error === 'client_already_connected') {\n suppressReconnect = true;\n showAlreadyInUseMessage();\n }\n if (msg.type === 'gesture') handleGesture(msg.data);\n if (msg.type === 'pressure') handlePressure(msg.data);\n if (msg.type === 'navigation') handleNavigation(msg.data);\n };\n\n socket.onclose = () => {\n if (suppressReconnect) return;\n showReconnecting();\n const delay = backoffSchedule[Math.min(backoffIndex, backoffSchedule.length - 1)];\n backoffIndex = Math.min(backoffIndex + 1, backoffSchedule.length - 1);\n reconnectTimer = setTimeout(connect, delay);\n };\n}"
652
+ "code": "const ws = new WebSocket('ws://127.0.0.1:8766');\nconst subscriptionRecord = new Set();\nconst backoffSchedule = [1000, 2000, 5000, 10000];\nlet backoffIndex = 0;\nlet suppressReconnect = false;\nlet reconnectTimer = null;\nlet lastBandConnected = false;\n\nfunction subscribe(signal) {\n subscriptionRecord.add(signal);\n ws.send(JSON.stringify({ command: 'subscribe', signal }));\n}\n\nfunction connect() {\n const socket = new WebSocket('ws://127.0.0.1:8766');\n\n socket.onopen = () => {\n backoffIndex = 0;\n socket.send(JSON.stringify({ command: 'get_status' }));\n subscriptionRecord.forEach(signal => socket.send(JSON.stringify({ command: 'subscribe', signal })));\n };\n\n socket.onmessage = (event) => {\n const msg = JSON.parse(event.data);\n if (msg.type === 'status') {\n const bandConnected = Boolean(msg.data.device.firmware && msg.data.device.serial_number);\n const hand = bandConnected ? msg.data.device.hand : 'None';\n updateConnectionLabel(bandConnected, hand);\n if (bandConnected && !lastBandConnected) {\n // Band just reconnected — replay subscriptions \n subscriptionRecord.forEach(signal => socket.send(JSON.stringify({ command: 'subscribe', signal })));\n }\n lastBandConnected = bandConnected;\n }\n if (msg.type === 'error' && msg.data.error === 'client_already_connected') {\n suppressReconnect = true;\n showAlreadyInUseMessage();\n }\n if (msg.type === 'gesture') handleGesture(msg.data);\n if (msg.type === 'pressure') handlePressure(msg.data);\n if (msg.type === 'navigation') handleNavigation(msg.data);\n };\n\n socket.onclose = () => {\n if (suppressReconnect) return;\n showReconnecting();\n const delay = backoffSchedule[Math.min(backoffIndex, backoffSchedule.length - 1)];\n backoffIndex = Math.min(backoffIndex + 1, backoffSchedule.length - 1);\n reconnectTimer = setTimeout(connect, delay);\n };\n}"
653
653
  },
654
654
  "test_gesture": {
655
655
  "description": "Simulate a gesture for testing without device",
@@ -649,7 +649,7 @@
649
649
  "code_examples": {
650
650
  "javascript": {
651
651
  "description": "Basic WebSocket connection and signal handling (new Dart server protocol)",
652
- "code": "const ws = new WebSocket('ws://127.0.0.1:8766');\nconst subscriptionRecord = new Set();\nconst backoffSchedule = [1000, 2000, 5000, 10000];\nlet backoffIndex = 0;\nlet suppressReconnect = false;\nlet reconnectTimer = null;\nlet lastBandConnected = false;\n\nfunction subscribe(signal) {\n subscriptionRecord.add(signal);\n ws.send(JSON.stringify({ command: 'subscribe', signal }));\n}\n\nfunction connect() {\n const socket = new WebSocket('ws://127.0.0.1:8766');\n\n socket.onopen = () => {\n backoffIndex = 0;\n socket.send(JSON.stringify({ command: 'get_status' }));\n subscriptionRecord.forEach(signal => socket.send(JSON.stringify({ command: 'subscribe', signal })));\n };\n\n socket.onmessage = (event) => {\n const msg = JSON.parse(event.data);\n if (msg.type === 'status') {\n const bandConnected = Boolean(msg.data.device.firmware && msg.data.device.serial_number);\n const hand = bandConnected ? msg.data.device.hand : 'None';\n updateConnectionLabel(bandConnected, hand);\n if (bandConnected && !lastBandConnected) {\n // Band just reconnected — replay subscriptions (FR-018a)\n subscriptionRecord.forEach(signal => socket.send(JSON.stringify({ command: 'subscribe', signal })));\n }\n lastBandConnected = bandConnected;\n }\n if (msg.type === 'error' && msg.data.error === 'client_already_connected') {\n suppressReconnect = true;\n showAlreadyInUseMessage();\n }\n if (msg.type === 'gesture') handleGesture(msg.data);\n if (msg.type === 'pressure') handlePressure(msg.data);\n if (msg.type === 'navigation') handleNavigation(msg.data);\n };\n\n socket.onclose = () => {\n if (suppressReconnect) return;\n showReconnecting();\n const delay = backoffSchedule[Math.min(backoffIndex, backoffSchedule.length - 1)];\n backoffIndex = Math.min(backoffIndex + 1, backoffSchedule.length - 1);\n reconnectTimer = setTimeout(connect, delay);\n };\n}"
652
+ "code": "const ws = new WebSocket('ws://127.0.0.1:8766');\nconst subscriptionRecord = new Set();\nconst backoffSchedule = [1000, 2000, 5000, 10000];\nlet backoffIndex = 0;\nlet suppressReconnect = false;\nlet reconnectTimer = null;\nlet lastBandConnected = false;\n\nfunction subscribe(signal) {\n subscriptionRecord.add(signal);\n ws.send(JSON.stringify({ command: 'subscribe', signal }));\n}\n\nfunction connect() {\n const socket = new WebSocket('ws://127.0.0.1:8766');\n\n socket.onopen = () => {\n backoffIndex = 0;\n socket.send(JSON.stringify({ command: 'get_status' }));\n subscriptionRecord.forEach(signal => socket.send(JSON.stringify({ command: 'subscribe', signal })));\n };\n\n socket.onmessage = (event) => {\n const msg = JSON.parse(event.data);\n if (msg.type === 'status') {\n const bandConnected = Boolean(msg.data.device.firmware && msg.data.device.serial_number);\n const hand = bandConnected ? msg.data.device.hand : 'None';\n updateConnectionLabel(bandConnected, hand);\n if (bandConnected && !lastBandConnected) {\n // Band just reconnected — replay subscriptions\n subscriptionRecord.forEach(signal => socket.send(JSON.stringify({ command: 'subscribe', signal })));\n }\n lastBandConnected = bandConnected;\n }\n if (msg.type === 'error' && msg.data.error === 'client_already_connected') {\n suppressReconnect = true;\n showAlreadyInUseMessage();\n }\n if (msg.type === 'gesture') handleGesture(msg.data);\n if (msg.type === 'pressure') handlePressure(msg.data);\n if (msg.type === 'navigation') handleNavigation(msg.data);\n };\n\n socket.onclose = () => {\n if (suppressReconnect) return;\n showReconnecting();\n const delay = backoffSchedule[Math.min(backoffIndex, backoffSchedule.length - 1)];\n backoffIndex = Math.min(backoffIndex + 1, backoffSchedule.length - 1);\n reconnectTimer = setTimeout(connect, delay);\n };\n}"
653
653
  },
654
654
  "test_gesture": {
655
655
  "description": "Simulate a gesture for testing without device",