{
  "schemaVersion": "1.0.0",
  "referenceVersion": "2.8.0-beta.28",
  "appVersion": "2.8.0-beta.28",
  "releaseChannel": "beta",
  "sourceRevision": "472fb34b484eeef0b663d28cacb628a7b9f14ff1",
  "generatedAt": "2026-10-23T22:20:23.056Z",
  "sourceFingerprints": {
    "src/features/automations.js": "7b829c93ab1fc3c88fe62e71ed0cc7715974562534fed1dcee8dfbf99015769c",
    "src/features/automation-provider-capabilities.js": "1bdb1dc6b4d2bf1173d0d6888fece6915cbc2b05ac76b2305275b017bb888b10",
    "src/features/command-variables.js": "1fe490de567fc6cbf6fdc9cb4fa464e9099c3236928b794e01834c684cd635c1",
    "src/features/command-authority.js": "2bf4293b635898e4b7ca771515df6c22e43e1cc381e243add4455350f64df7ee",
    "src/features/custom-commands.js": "4e4f0a93f5d405a79b53210124a8c05f5ea7e7dffe7e551c99a6d12cbb6296f9",
    "src/features/ai-topics/conversation-topic-actions.js": "59519a4090ce7d2384ef8e225b58284aa7da7df312cf6b3b11f94a8b8873b765",
    "src/features/sheevpad/visual-toggle-state.js": "099f18e459ee8343a8b21db46071e68c4937f713af9474b7870f8af9d451af91",
    "public/index.html": "c003fdaaf5b38caa3ed2503393c512faf272c5d5bc634c03ac7885e2ea8f4286",
    "public/mobile.html": "6f36e80287f6b913db699f604a356cfb93abe4f42cea8ecbafe3cc235af2e692",
    "public/js/automation-trigger-ui.js": "dfcd86eb00a5a4082bdd4d5052bbcab5d8948b916b32daacc8bb3a7b6430cbf5",
    "server.js": "27f037d88ce61ca06747fac93e06b7d7bcdf59913d7b5af0db13d2b997121a14",
    "integrations/action-library-runtime.js": "47676fe55f57e711e56e70873e68bac17a3e95fdc238de61a9f1d92288c6601e",
    "integrations/obs/obs-catalog-targets.js": "f63596dd521f90a8a2d6fd95f74d93e7a910796bceddc8eed947d7522f0bcd08",
    "integrations/streamlabs/streamlabs-client.js": "d70dbb3b095668f1ee9d129fdae72f62c4dec5bd39d18b1a81dc60ae2b178532",
    "integrations/action-library-runtime/execution.js": "5b21825ab30c2e3f1203d540aff25f716d2388e2de13956f780308cda5b2f9c8",
    "src/features/media/mediaCommands.js": "b6c903e55c99e7419997996b39953b78eae4de600e5f77a8c4220b7f01b1558d"
  },
  "coverage": {
    "triggers": 29,
    "actions": 79,
    "globalVariables": 59,
    "globalAliases": 19,
    "commands": 54,
    "fields": 188,
    "filters": 33,
    "navigationModes": 4,
    "operationVariants": 38,
    "entries": 441
  },
  "instructions": [
    "Use only capabilities documented for the user’s app version and selected release channel. This snapshot describes a beta, not the stable release.",
    "Configure commands, automations, timers or SheevPad using exact editor labels and supported fields. JSON examples illustrate fields; they are not an import format.",
    "For how-do-I questions, compose click-by-click instructions from context UI setup, trigger UI selection and action UI/Fields. Include initial name, organizational Category or Group, enabled state, When, Where, Do, action order, save and verification. Distinguish organizational categories, Trigger category and action categories.",
    "Choose an automation for an incoming event, a command for a chat invocation, a timer for recurring execution, or a SheevPad button for a manual tap. Combine compatible actions in one ordered list; do not imply parallel execution or automatic rollback. Use context.raid-response as a complete worked composition.",
    "Ask for missing resource selections and connection details. Fixture IDs and paths must be replaced using the app pickers; never invent a real resource ID.",
    "Check action picker contexts, runtime prerequisites, originating provider, output routing and variable producer/lifetime separately.",
    "Report unsupported steps explicitly. General conditional branching, arbitrary scripts and unavailable placeholders are not implied by this reference.",
    "Imported libraries and Marketplace commands depend on installed packages; consult their own contracts. Never assume every package is installed.",
    "Source-verified means offline source review, not live validation of connected services. Follow the release UAT status."
  ],
  "entries": [
    {
      "id": "action.conversation_topic_refresh",
      "kind": "action",
      "runtimeKey": "conversation_topic_refresh",
      "label": "Refresh Conversation Starters",
      "category": "A.I.",
      "summary": "Check for newly prepared questions and download only a changed package.",
      "status": "gated",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Conversation Starters account access, topics.read entitlement and prepared question service.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/ai-topics/conversation-topic-actions.js",
          "symbol": "CONVERSATION_TOPIC_ACTIONS.conversation_topic_refresh"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {}
        }
      ],
      "details": {
        "behavior": "Download a changed prepared question package; unchanged packages are retained.",
        "fields": [],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "conversation_topic_refresh"
          },
          "timer": {
            "type": "conversation_topic_refresh"
          },
          "command": {
            "type": "conversation_topic_refresh"
          },
          "pad": {
            "type": "conversation_topic_refresh"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category A.I., select Refresh Conversation Starters, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.conversation_topic_next",
      "kind": "action",
      "runtimeKey": "conversation_topic_next",
      "label": "Select Next Conversation Starter",
      "category": "A.I.",
      "summary": "Select one unused prepared question, or reuse the current active question.",
      "status": "gated",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Conversation Starters access and a prepared question pool.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/ai-topics/conversation-topic-actions.js",
          "symbol": "CONVERSATION_TOPIC_ACTIONS.conversation_topic_next"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {}
        }
      ],
      "details": {
        "behavior": "Reuse the active question or select and present an unused question; fail if none is available.",
        "fields": [],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "conversation_topic_next"
          },
          "timer": {
            "type": "conversation_topic_next"
          },
          "command": {
            "type": "conversation_topic_next"
          },
          "pad": {
            "type": "conversation_topic_next"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category A.I., select Select Next Conversation Starter, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.conversation_topic_send",
      "kind": "action",
      "runtimeKey": "conversation_topic_send",
      "label": "Send Current Conversation Starter",
      "category": "A.I.",
      "summary": "Send the current question, mark it used after a successful delivery, and advance to the next one.",
      "status": "gated",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Conversation Starters access, prepared questions and at least one selected connected chat.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/ai-topics/conversation-topic-actions.js",
          "symbol": "CONVERSATION_TOPIC_ACTIONS.conversation_topic_send"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "twitch": true,
            "youtube": false,
            "kick": false,
            "tiktok": false
          }
        }
      ],
      "details": {
        "behavior": "Send to selected connected chats; no explicit toggles means all four. Mark used only after successful delivery and select the next question. No selected/connected chats is an error.",
        "fields": [
          {
            "key": "twitch",
            "type": "checkbox",
            "label": "Twitch",
            "default": true,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": true,
              "timer": true,
              "command": true,
              "pad": true
            },
            "runtimeFallbackNote": "Send to selected connected chats; no explicit toggles means all four. Mark used only after successful delivery and select the next question. No selected/connected chats is an error.",
            "dynamicSource": null
          },
          {
            "key": "youtube",
            "type": "checkbox",
            "label": "YouTube",
            "default": true,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": true,
              "timer": true,
              "command": true,
              "pad": true
            },
            "runtimeFallbackNote": "Send to selected connected chats; no explicit toggles means all four. Mark used only after successful delivery and select the next question. No selected/connected chats is an error.",
            "dynamicSource": null
          },
          {
            "key": "kick",
            "type": "checkbox",
            "label": "Kick",
            "default": true,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": true,
              "timer": true,
              "command": true,
              "pad": true
            },
            "runtimeFallbackNote": "Send to selected connected chats; no explicit toggles means all four. Mark used only after successful delivery and select the next question. No selected/connected chats is an error.",
            "dynamicSource": null
          },
          {
            "key": "tiktok",
            "type": "checkbox",
            "label": "TikTok",
            "default": true,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": true,
              "timer": true,
              "command": true,
              "pad": true
            },
            "runtimeFallbackNote": "Send to selected connected chats; no explicit toggles means all four. Mark used only after successful delivery and select the next question. No selected/connected chats is an error.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "conversation_topic_send",
            "twitch": true,
            "youtube": true,
            "kick": true,
            "tiktok": true
          },
          "timer": {
            "type": "conversation_topic_send",
            "twitch": true,
            "youtube": true,
            "kick": true,
            "tiktok": true
          },
          "command": {
            "type": "conversation_topic_send",
            "twitch": true,
            "youtube": true,
            "kick": true,
            "tiktok": true
          },
          "pad": {
            "type": "conversation_topic_send",
            "twitch": true,
            "youtube": true,
            "kick": true,
            "tiktok": true
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category A.I., select Send Current Conversation Starter, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.conversation_topic_mark_used",
      "kind": "action",
      "runtimeKey": "conversation_topic_mark_used",
      "label": "Mark Conversation Starter Used",
      "category": "A.I.",
      "summary": "Mark the current question used and advance to the next one.",
      "status": "gated",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Conversation Starters access and an active question.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/ai-topics/conversation-topic-actions.js",
          "symbol": "CONVERSATION_TOPIC_ACTIONS.conversation_topic_mark_used"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {}
        }
      ],
      "details": {
        "behavior": "Mark the active question used and advance; fail when no question is selected.",
        "fields": [],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "conversation_topic_mark_used"
          },
          "timer": {
            "type": "conversation_topic_mark_used"
          },
          "command": {
            "type": "conversation_topic_mark_used"
          },
          "pad": {
            "type": "conversation_topic_mark_used"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category A.I., select Mark Conversation Starter Used, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.conversation_topic_release",
      "kind": "action",
      "runtimeKey": "conversation_topic_release",
      "label": "Release Conversation Starter",
      "category": "A.I.",
      "summary": "Return the current question to the unused queue without marking it used.",
      "status": "gated",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Conversation Starters access and an active question.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/ai-topics/conversation-topic-actions.js",
          "symbol": "CONVERSATION_TOPIC_ACTIONS.conversation_topic_release"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {}
        }
      ],
      "details": {
        "behavior": "Return the active question to the unused queue without marking it used; fail when none is selected.",
        "fields": [],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "conversation_topic_release"
          },
          "timer": {
            "type": "conversation_topic_release"
          },
          "command": {
            "type": "conversation_topic_release"
          },
          "pad": {
            "type": "conversation_topic_release"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category A.I., select Release Conversation Starter, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.ai_personality_set",
      "kind": "action",
      "runtimeKey": "ai_personality_set",
      "label": "Set Bot Voice",
      "category": "A.I.",
      "summary": "Activate a saved voice or create a custom one from action text and command variables. Response Rules still apply.",
      "status": "gated",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "A.I. account access; saved voice or voice-generation service.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.ai_personality_set"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "mode": "saved",
            "profileId": "fixture-voice"
          }
        }
      ],
      "details": {
        "behavior": "Saved mode activates profileId. Custom mode generates and activates a voice from customGuidance; empty guidance fails. The Bot Voice editor is synchronized.",
        "fields": [
          {
            "key": "mode",
            "type": "select",
            "label": "Voice source",
            "default": "saved",
            "options": [
              {
                "value": "saved",
                "label": "Saved voice"
              },
              {
                "value": "custom",
                "label": "Custom voice instructions"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "saved",
              "timer": "saved",
              "command": "saved",
              "pad": "saved"
            },
            "runtimeFallbackNote": "Saved mode activates profileId. Custom mode generates and activates a voice from customGuidance; empty guidance fails. The Bot Voice editor is synchronized.",
            "dynamicSource": null
          },
          {
            "key": "profileId",
            "type": "ai_personality_select",
            "label": "Saved voice",
            "visibleWhen": {
              "mode": [
                "",
                "saved"
              ]
            },
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Saved mode activates profileId. Custom mode generates and activates a voice from customGuidance; empty guidance fails. The Bot Voice editor is synchronized.",
            "dynamicSource": "Local Saved voice picker; select an existing resource, never invent its ID."
          },
          {
            "key": "customGuidance",
            "type": "textarea",
            "label": "Custom voice instructions",
            "placeholder": "Describe how the bot should sound, or use variables such as {message}.",
            "maxlength": 500,
            "visibleWhen": {
              "mode": "custom"
            },
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Saved mode activates profileId. Custom mode generates and activates a voice from customGuidance; empty guidance fails. The Bot Voice editor is synchronized.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "ai_personality_set",
            "mode": "saved",
            "profileId": "",
            "customGuidance": ""
          },
          "timer": {
            "type": "ai_personality_set",
            "mode": "saved",
            "profileId": "",
            "customGuidance": ""
          },
          "command": {
            "type": "ai_personality_set",
            "mode": "saved",
            "profileId": "",
            "customGuidance": ""
          },
          "pad": {
            "type": "ai_personality_set",
            "mode": "saved",
            "profileId": "",
            "customGuidance": ""
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category A.I., select Set Bot Voice, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.ai_generated_raid_shoutout",
      "kind": "action",
      "runtimeKey": "ai_generated_raid_shoutout",
      "label": "Generate raid greeting",
      "category": "A.I.",
      "summary": "Generate and send a short greeting using only the incoming raider identity, optional bio, latest title/category, and active Bot Voice.",
      "status": "gated",
      "contexts": [
        "automation",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Incoming raid trigger, A.I. raid.summary entitlement and provider metadata.",
        "accountFeature": {
          "moduleId": "ai_002_shoutouts_raids",
          "featureId": "raid.summary"
        },
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.ai_generated_raid_shoutout"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Incoming raid generation is currently supported for Twitch and Kick events only.",
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {}
        }
      ],
      "details": {
        "behavior": "Requires Incoming raid on Twitch or Kick, even if selected from another builder. Uses the triggering raider identity and active Bot Voice.",
        "fields": [],
        "declaredContexts": [
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [
          "{user}"
        ],
        "defaultsByContext": {
          "automation": {
            "type": "ai_generated_raid_shoutout",
            "message": "",
            "platform": "event"
          },
          "timer": {
            "type": "ai_generated_raid_shoutout",
            "message": "",
            "platform": "all"
          },
          "command": {
            "type": "ai_generated_raid_shoutout",
            "message": "",
            "platform": "event"
          },
          "pad": {
            "type": "ai_generated_raid_shoutout",
            "message": "",
            "platform": "all"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category A.I., select Generate raid greeting, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.ai_generated_shoutout",
      "kind": "action",
      "runtimeKey": "ai_generated_shoutout",
      "label": "Generate creator introduction",
      "category": "A.I.",
      "summary": "Generate and send a voice-aware introduction using the creator's available profile, latest title, and category.",
      "status": "gated",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "A.I. shoutout.message entitlement and connected output chat.",
        "accountFeature": {
          "moduleId": "ai_002_shoutouts_raids",
          "featureId": "shoutout.message"
        },
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.ai_generated_shoutout"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "TikTok creator-profile lookup is unavailable; generated output may still be sent to TikTok.",
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "username": "ExampleCreator",
            "creatorPlatform": "twitch",
            "platform": "twitch"
          }
        }
      ],
      "details": {
        "behavior": "Blank username uses {user}; remove leading @. Creator platform event means originating platform. Sends generated text to selected output targets. TikTok creator lookup is unavailable.",
        "fields": [
          {
            "key": "username",
            "type": "text",
            "label": "Creator username",
            "placeholder": "{user} or a channel username",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Blank username uses {user}; remove leading @. Creator platform event means originating platform. Sends generated text to selected output targets. TikTok creator lookup is unavailable.",
            "dynamicSource": null
          },
          {
            "key": "creatorPlatform",
            "type": "select",
            "label": "Creator platform",
            "default": "event",
            "options": [
              {
                "value": "event",
                "label": "Same platform as trigger"
              },
              {
                "value": "twitch",
                "label": "Twitch"
              },
              {
                "value": "youtube",
                "label": "YouTube"
              },
              {
                "value": "kick",
                "label": "Kick"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "event",
              "timer": "event",
              "command": "event",
              "pad": "event"
            },
            "runtimeFallbackNote": "Blank username uses {user}; remove leading @. Creator platform event means originating platform. Sends generated text to selected output targets. TikTok creator lookup is unavailable.",
            "dynamicSource": null
          },
          {
            "key": "platform",
            "type": "select",
            "label": "Send to",
            "options": [
              {
                "value": "event",
                "label": "Same platform as event"
              },
              {
                "value": "all",
                "label": "Twitch + YouTube + Kick"
              },
              {
                "value": "twitch",
                "label": "Twitch"
              },
              {
                "value": "youtube",
                "label": "YouTube"
              },
              {
                "value": "kick",
                "label": "Kick"
              },
              {
                "value": "tiktok",
                "label": "TikTok"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "event",
              "timer": "all",
              "command": "event",
              "pad": "all"
            },
            "runtimeFallbackNote": "Blank username uses {user}; remove leading @. Creator platform event means originating platform. Sends generated text to selected output targets. TikTok creator lookup is unavailable.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "ai_generated_shoutout",
            "message": "",
            "platform": "event"
          },
          "timer": {
            "type": "ai_generated_shoutout",
            "message": "",
            "platform": "all"
          },
          "command": {
            "type": "ai_generated_shoutout",
            "message": "",
            "platform": "event"
          },
          "pad": {
            "type": "ai_generated_shoutout",
            "message": "",
            "platform": "all"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category A.I., select Generate creator introduction, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.ai_generated_welcome",
      "kind": "action",
      "runtimeKey": "ai_generated_welcome",
      "label": "Generate viewer greeting",
      "category": "A.I.",
      "summary": "Generate a short voice-aware greeting for a first-time chatter, returning viewer, or follower on the triggering platform.",
      "status": "gated",
      "contexts": [
        "automation",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Supported viewer trigger and A.I. welcome.message entitlement.",
        "accountFeature": {
          "moduleId": "ai_003_welcomes_lurks",
          "featureId": "welcome.message"
        },
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.ai_generated_welcome"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {}
        }
      ],
      "details": {
        "behavior": "Only First chat ever, Welcome Back or New follow event contexts are accepted; send on the originating platform.",
        "fields": [],
        "declaredContexts": [
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [
          "{user}"
        ],
        "defaultsByContext": {
          "automation": {
            "type": "ai_generated_welcome",
            "message": "",
            "platform": "event"
          },
          "timer": {
            "type": "ai_generated_welcome",
            "message": "",
            "platform": "all"
          },
          "command": {
            "type": "ai_generated_welcome",
            "message": "",
            "platform": "event"
          },
          "pad": {
            "type": "ai_generated_welcome",
            "message": "",
            "platform": "all"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category A.I., select Generate viewer greeting, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.ai_generated_event_celebration",
      "kind": "action",
      "runtimeKey": "ai_generated_event_celebration",
      "label": "Generate community reaction",
      "category": "A.I.",
      "summary": "Celebrate the triggering support or community event in chat, an Overlay Builder alert, or both.",
      "status": "gated",
      "contexts": [
        "automation",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "A.I. event.celebration entitlement; Alert Box placement for overlay output.",
        "accountFeature": {
          "moduleId": "ai_004_event_celebrations",
          "featureId": "event.celebration"
        },
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.ai_generated_event_celebration"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "outputMode": "chat",
            "platform": "twitch"
          }
        }
      ],
      "details": {
        "behavior": "Output defaults to chat; overlay/both also dispatch an alert with generated text. Alert duration falls back to 8000 ms. Requires a supported community event.",
        "fields": [
          {
            "key": "outputMode",
            "type": "select",
            "label": "Output",
            "default": "chat",
            "options": [
              {
                "value": "chat",
                "label": "Chat only"
              },
              {
                "value": "overlay",
                "label": "Overlay alert only"
              },
              {
                "value": "both",
                "label": "Chat and overlay alert"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "chat",
              "timer": "chat",
              "command": "chat",
              "pad": "chat"
            },
            "runtimeFallbackNote": "Output defaults to chat; overlay/both also dispatch an alert with generated text. Alert duration falls back to 8000 ms. Requires a supported community event.",
            "dynamicSource": null
          },
          {
            "key": "platform",
            "type": "select",
            "label": "Send chat to",
            "options": [
              {
                "value": "event",
                "label": "Same platform as event"
              },
              {
                "value": "all",
                "label": "Twitch + YouTube + Kick"
              },
              {
                "value": "twitch",
                "label": "Twitch"
              },
              {
                "value": "youtube",
                "label": "YouTube"
              },
              {
                "value": "kick",
                "label": "Kick"
              },
              {
                "value": "tiktok",
                "label": "TikTok"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "event",
              "timer": "all",
              "command": "event",
              "pad": "all"
            },
            "runtimeFallbackNote": "Output defaults to chat; overlay/both also dispatch an alert with generated text. Alert duration falls back to 8000 ms. Requires a supported community event.",
            "dynamicSource": null
          },
          {
            "key": "overlaySlug",
            "type": "theme_select",
            "label": "Overlay source",
            "source": "overlay_builder.overlays",
            "labelKey": "overlayName",
            "visibleWhen": {
              "outputMode": [
                "overlay",
                "both"
              ]
            },
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Output defaults to chat; overlay/both also dispatch an alert with generated text. Alert duration falls back to 8000 ms. Requires a supported community event.",
            "dynamicSource": "overlay_builder.overlays"
          },
          {
            "key": "presetId",
            "type": "theme_select",
            "label": "Alert preset",
            "source": "alert_presets.local",
            "labelKey": "presetName",
            "visibleWhen": {
              "outputMode": [
                "overlay",
                "both"
              ]
            },
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Output defaults to chat; overlay/both also dispatch an alert with generated text. Alert duration falls back to 8000 ms. Requires a supported community event.",
            "dynamicSource": "alert_presets.local"
          },
          {
            "key": "durationMs",
            "type": "number",
            "label": "Alert duration (ms)",
            "default": 8000,
            "min": 1000,
            "max": 60000,
            "visibleWhen": {
              "outputMode": [
                "overlay",
                "both"
              ]
            },
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": 8000,
              "timer": 8000,
              "command": 8000,
              "pad": 8000
            },
            "runtimeFallbackNote": "Output defaults to chat; overlay/both also dispatch an alert with generated text. Alert duration falls back to 8000 ms. Requires a supported community event.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "ai_generated_event_celebration",
            "message": "",
            "platform": "event"
          },
          "timer": {
            "type": "ai_generated_event_celebration",
            "message": "",
            "platform": "all"
          },
          "command": {
            "type": "ai_generated_event_celebration",
            "message": "",
            "platform": "event"
          },
          "pad": {
            "type": "ai_generated_event_celebration",
            "message": "",
            "platform": "all"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category A.I., select Generate community reaction, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.ai_stream_showstarter",
      "kind": "action",
      "runtimeKey": "ai_stream_showstarter",
      "label": "Generate stream opening message",
      "category": "A.I.",
      "summary": "Open the show with a fresh message in the active Bot Voice. Optional guidance can name the planned segment or mood.",
      "status": "gated",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "A.I. stream.showstarter entitlement and connected chat.",
        "accountFeature": {
          "moduleId": "ai_005_stream_flow",
          "featureId": "stream.showstarter"
        },
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.ai_stream_showstarter"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "prompt": "Community game night",
            "platform": "twitch"
          }
        }
      ],
      "details": {
        "behavior": "Generate a stream opening in the active Bot Voice. prompt is optional literal guidance; send to chosen output targets.",
        "fields": [
          {
            "key": "prompt",
            "type": "text",
            "label": "Optional opening guidance",
            "placeholder": "Tonight is community game night",
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Generate a stream opening in the active Bot Voice. prompt is optional literal guidance; send to chosen output targets.",
            "dynamicSource": null
          },
          {
            "key": "platform",
            "type": "select",
            "label": "Send to",
            "options": [
              {
                "value": "event",
                "label": "Same platform as event"
              },
              {
                "value": "all",
                "label": "Twitch + YouTube + Kick"
              },
              {
                "value": "twitch",
                "label": "Twitch"
              },
              {
                "value": "youtube",
                "label": "YouTube"
              },
              {
                "value": "kick",
                "label": "Kick"
              },
              {
                "value": "tiktok",
                "label": "TikTok"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "event",
              "timer": "all",
              "command": "event",
              "pad": "all"
            },
            "runtimeFallbackNote": "Generate a stream opening in the active Bot Voice. prompt is optional literal guidance; send to chosen output targets.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "ai_stream_showstarter",
            "message": "",
            "platform": "event"
          },
          "timer": {
            "type": "ai_stream_showstarter",
            "message": "",
            "platform": "all"
          },
          "command": {
            "type": "ai_stream_showstarter",
            "message": "",
            "platform": "event"
          },
          "pad": {
            "type": "ai_stream_showstarter",
            "message": "",
            "platform": "all"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category A.I., select Generate stream opening message, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.ai_stream_ad_followup",
      "kind": "action",
      "runtimeKey": "ai_stream_ad_followup",
      "label": "Generate after-ad message",
      "category": "A.I.",
      "summary": "After the triggering ad finishes, welcome chat back with a fresh message in the active Bot Voice.",
      "status": "gated",
      "contexts": [
        "automation",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Ad break trigger and A.I. stream.ad_followup entitlement.",
        "accountFeature": {
          "moduleId": "ai_005_stream_flow",
          "featureId": "stream.ad_followup"
        },
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.ai_stream_ad_followup"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "postDelayMs": 1000,
            "platform": "twitch"
          }
        }
      ],
      "details": {
        "behavior": "Requires Ad break context. Wait until the known ad end plus postDelayMs (default 1000, clamped 0–30000) before generating. prompt is literal guidance.",
        "fields": [
          {
            "key": "postDelayMs",
            "type": "number",
            "label": "Extra delay after ad (ms)",
            "default": 1000,
            "min": 0,
            "max": 30000,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": 1000,
              "timer": 1000,
              "command": 1000,
              "pad": 1000
            },
            "runtimeFallbackNote": "Requires Ad break context. Wait until the known ad end plus postDelayMs (default 1000, clamped 0–30000) before generating. prompt is literal guidance.",
            "dynamicSource": null
          },
          {
            "key": "prompt",
            "type": "text",
            "label": "Optional follow-up guidance",
            "placeholder": "Remind everyone what we were doing",
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Requires Ad break context. Wait until the known ad end plus postDelayMs (default 1000, clamped 0–30000) before generating. prompt is literal guidance.",
            "dynamicSource": null
          },
          {
            "key": "platform",
            "type": "select",
            "label": "Send to",
            "options": [
              {
                "value": "event",
                "label": "Same platform as event"
              },
              {
                "value": "all",
                "label": "Twitch + YouTube + Kick"
              },
              {
                "value": "twitch",
                "label": "Twitch"
              },
              {
                "value": "youtube",
                "label": "YouTube"
              },
              {
                "value": "kick",
                "label": "Kick"
              },
              {
                "value": "tiktok",
                "label": "TikTok"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "event",
              "timer": "all",
              "command": "event",
              "pad": "all"
            },
            "runtimeFallbackNote": "Requires Ad break context. Wait until the known ad end plus postDelayMs (default 1000, clamped 0–30000) before generating. prompt is literal guidance.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "ai_stream_ad_followup",
            "message": "",
            "platform": "event"
          },
          "timer": {
            "type": "ai_stream_ad_followup",
            "message": "",
            "platform": "all"
          },
          "command": {
            "type": "ai_stream_ad_followup",
            "message": "",
            "platform": "event"
          },
          "pad": {
            "type": "ai_stream_ad_followup",
            "message": "",
            "platform": "all"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category A.I., select Generate after-ad message, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.ai_stream_chat_recap",
      "kind": "action",
      "runtimeKey": "ai_stream_chat_recap",
      "label": "Generate recent chat summary",
      "category": "A.I.",
      "summary": "Summarize recent meaningful viewer conversation without quoting private or filtered chat.",
      "status": "gated",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "A.I. stream.chat_recap entitlement and recent eligible chat.",
        "accountFeature": {
          "moduleId": "ai_005_stream_flow",
          "featureId": "stream.chat_recap"
        },
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.ai_stream_chat_recap"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "platform": "twitch"
          }
        }
      ],
      "details": {
        "behavior": "Summarize recent meaningful conversation from selected context platforms, using optional literal prompt guidance; send to the same targets.",
        "fields": [
          {
            "key": "prompt",
            "type": "text",
            "label": "Optional summary focus",
            "placeholder": "Focus on viewer suggestions",
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Summarize recent meaningful conversation from selected context platforms, using optional literal prompt guidance; send to the same targets.",
            "dynamicSource": null
          },
          {
            "key": "platform",
            "type": "select",
            "label": "Send to",
            "options": [
              {
                "value": "event",
                "label": "Same platform as event"
              },
              {
                "value": "all",
                "label": "Twitch + YouTube + Kick"
              },
              {
                "value": "twitch",
                "label": "Twitch"
              },
              {
                "value": "youtube",
                "label": "YouTube"
              },
              {
                "value": "kick",
                "label": "Kick"
              },
              {
                "value": "tiktok",
                "label": "TikTok"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "event",
              "timer": "all",
              "command": "event",
              "pad": "all"
            },
            "runtimeFallbackNote": "Summarize recent meaningful conversation from selected context platforms, using optional literal prompt guidance; send to the same targets.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "ai_stream_chat_recap",
            "message": "",
            "platform": "event"
          },
          "timer": {
            "type": "ai_stream_chat_recap",
            "message": "",
            "platform": "all"
          },
          "command": {
            "type": "ai_stream_chat_recap",
            "message": "",
            "platform": "event"
          },
          "pad": {
            "type": "ai_stream_chat_recap",
            "message": "",
            "platform": "all"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category A.I., select Generate recent chat summary, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.ai_smart_timer_announcement",
      "kind": "action",
      "runtimeKey": "ai_smart_timer_announcement",
      "label": "Generate scheduled message variations",
      "category": "A.I.",
      "summary": "The first run writes and stores 10 Bot Voice variations of this announcement. Each later run sends the next unused message; after all 10 are used, the following run prepares a new set.",
      "status": "gated",
      "contexts": [
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Timer context and A.I. timer.announcement entitlement.",
        "accountFeature": {
          "moduleId": "ai_006_smart_timers",
          "featureId": "timer.announcement"
        },
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.ai_smart_timer_announcement"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "baseMessage": "Community night is Friday!",
            "goal": "Friendly"
          }
        }
      ],
      "details": {
        "behavior": "Resolve baseMessage and goal; generate/store ten variations on first run, then send each unused variation in turn. A later run prepares a new batch after exhaustion.",
        "fields": [
          {
            "key": "baseMessage",
            "type": "textarea",
            "label": "Base announcement",
            "placeholder": "Join our community game night every Friday!",
            "maxlength": 500,
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Resolve baseMessage and goal; generate/store ten variations on first run, then send each unused variation in turn. A later run prepares a new batch after exhaustion.",
            "dynamicSource": null
          },
          {
            "key": "goal",
            "type": "text",
            "label": "Optional goal",
            "placeholder": "Friendly and inviting without sounding repetitive",
            "maxlength": 240,
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Resolve baseMessage and goal; generate/store ten variations on first run, then send each unused variation in turn. A later run prepares a new batch after exhaustion.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer"
        ],
        "pickerContexts": [
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "ai_smart_timer_announcement",
            "message": "",
            "platform": "event"
          },
          "timer": {
            "type": "ai_smart_timer_announcement",
            "message": "",
            "platform": "all"
          },
          "command": {
            "type": "ai_smart_timer_announcement",
            "message": "",
            "platform": "event"
          },
          "pad": {
            "type": "ai_smart_timer_announcement",
            "message": "",
            "platform": "all"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category A.I., select Generate scheduled message variations, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.ai_creative_utility",
      "kind": "action",
      "runtimeKey": "ai_creative_utility",
      "label": "Generate with Writing Assistant",
      "category": "A.I.",
      "summary": "Transform source text with a selected writing tool, then send the result to the chosen chat.",
      "status": "gated",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "A.I. creative.generate entitlement and connected chat.",
        "accountFeature": {
          "moduleId": "ai_007_creative_utilities",
          "featureId": "creative.generate"
        },
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.ai_creative_utility"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "mode": "rewrite",
            "text": "Community night is Friday!",
            "platform": "twitch"
          }
        }
      ],
      "details": {
        "behavior": "Resolve source text and guidance; tool defaults to rewrite. targetLanguage is literal and applies to translate. Send generated text to selected targets.",
        "fields": [
          {
            "key": "mode",
            "type": "select",
            "label": "Tool",
            "default": "rewrite",
            "options": [
              {
                "value": "rewrite",
                "label": "Rewrite"
              },
              {
                "value": "hype",
                "label": "Add hype"
              },
              {
                "value": "calm",
                "label": "Calm tone"
              },
              {
                "value": "shorten",
                "label": "Shorten"
              },
              {
                "value": "translate",
                "label": "Translate"
              },
              {
                "value": "poll",
                "label": "Poll draft"
              },
              {
                "value": "stream_title",
                "label": "Stream title"
              },
              {
                "value": "social_post",
                "label": "Social post"
              },
              {
                "value": "clip_caption",
                "label": "Clip caption"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "rewrite",
              "timer": "rewrite",
              "command": "rewrite",
              "pad": "rewrite"
            },
            "runtimeFallbackNote": "Resolve source text and guidance; tool defaults to rewrite. targetLanguage is literal and applies to translate. Send generated text to selected targets.",
            "dynamicSource": null
          },
          {
            "key": "text",
            "type": "textarea",
            "label": "Source text",
            "placeholder": "Write or insert variables to transform",
            "maxlength": 1000,
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Resolve source text and guidance; tool defaults to rewrite. targetLanguage is literal and applies to translate. Send generated text to selected targets.",
            "dynamicSource": null
          },
          {
            "key": "guidance",
            "type": "text",
            "label": "Optional guidance",
            "placeholder": "Keep the important date and call to action",
            "maxlength": 240,
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Resolve source text and guidance; tool defaults to rewrite. targetLanguage is literal and applies to translate. Send generated text to selected targets.",
            "dynamicSource": null
          },
          {
            "key": "targetLanguage",
            "type": "text",
            "label": "Target language",
            "placeholder": "Spanish",
            "maxlength": 80,
            "visibleWhen": {
              "mode": "translate"
            },
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Resolve source text and guidance; tool defaults to rewrite. targetLanguage is literal and applies to translate. Send generated text to selected targets.",
            "dynamicSource": null
          },
          {
            "key": "platform",
            "type": "select",
            "label": "Send to",
            "options": [
              {
                "value": "event",
                "label": "Same platform as event"
              },
              {
                "value": "all",
                "label": "Twitch + YouTube + Kick"
              },
              {
                "value": "twitch",
                "label": "Twitch"
              },
              {
                "value": "youtube",
                "label": "YouTube"
              },
              {
                "value": "kick",
                "label": "Kick"
              },
              {
                "value": "tiktok",
                "label": "TikTok"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "event",
              "timer": "all",
              "command": "event",
              "pad": "all"
            },
            "runtimeFallbackNote": "Resolve source text and guidance; tool defaults to rewrite. targetLanguage is literal and applies to translate. Send generated text to selected targets.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "ai_creative_utility",
            "message": "",
            "platform": "event"
          },
          "timer": {
            "type": "ai_creative_utility",
            "message": "",
            "platform": "all"
          },
          "command": {
            "type": "ai_creative_utility",
            "message": "",
            "platform": "event"
          },
          "pad": {
            "type": "ai_creative_utility",
            "message": "",
            "platform": "all"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category A.I., select Generate with Writing Assistant, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.pause",
      "kind": "action",
      "runtimeKey": "pause",
      "label": "Pause / wait",
      "category": "Utilities",
      "summary": "Wait before continuing to the next action in this sequence.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "No external connection.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.pause"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "seconds": 5
          }
        }
      ],
      "details": {
        "behavior": "Await a pause before the next action. Parse whole seconds; missing/zero/invalid falls back to 5; clamp 1–3600.",
        "fields": [
          {
            "key": "seconds",
            "type": "number",
            "label": "Pause seconds",
            "min": 1,
            "max": 3600,
            "default": 5,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": 5,
              "timer": 5,
              "command": 5,
              "pad": 5
            },
            "runtimeFallbackNote": "Await a pause before the next action. Parse whole seconds; missing/zero/invalid falls back to 5; clamp 1–3600.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "pause",
            "seconds": 5
          },
          "timer": {
            "type": "pause",
            "seconds": 5
          },
          "command": {
            "type": "pause",
            "seconds": 5
          },
          "pad": {
            "type": "pause",
            "seconds": 5
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Utilities, select Pause / wait, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.chat",
      "kind": "action",
      "runtimeKey": "chat",
      "label": "Send chat message",
      "category": "Chat Bot Commands",
      "summary": "Send a message to the event/timer platform. Automations may target all platforms; timers still obey their platform and online-only rules.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected output chat; reply mode also needs the triggering message identity.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.chat"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "message": "Hello {user}!",
            "platform": "event",
            "replyMode": "normal"
          }
        }
      ],
      "details": {
        "behavior": "Resolve message; blank output does nothing. event/missing target uses origin; all means Twitch + YouTube + Kick. Reply style applies only to the originating platform with an actor message ID. Timers scope delivery to their eligible platform.",
        "fields": [
          {
            "key": "message",
            "type": "textarea",
            "label": "Message",
            "placeholder": "Thanks for the raid @{user}! Welcome {viewers} raiders!",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve message; blank output does nothing. event/missing target uses origin; all means Twitch + YouTube + Kick. Reply style applies only to the originating platform with an actor message ID. Timers scope delivery to their eligible platform.",
            "dynamicSource": null
          },
          {
            "key": "platform",
            "type": "select",
            "label": "Send to",
            "options": [
              {
                "value": "event",
                "label": "Same platform as event"
              },
              {
                "value": "all",
                "label": "Twitch + YouTube + Kick"
              },
              {
                "value": "twitch",
                "label": "Twitch only"
              },
              {
                "value": "youtube",
                "label": "YouTube only"
              },
              {
                "value": "kick",
                "label": "Kick only"
              },
              {
                "value": "tiktok",
                "label": "TikTok only"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "event",
              "timer": "all",
              "command": "event",
              "pad": "all"
            },
            "runtimeFallbackNote": "Resolve message; blank output does nothing. event/missing target uses origin; all means Twitch + YouTube + Kick. Reply style applies only to the originating platform with an actor message ID. Timers scope delivery to their eligible platform.",
            "dynamicSource": null
          },
          {
            "key": "replyMode",
            "type": "select",
            "label": "Response style",
            "default": "normal",
            "contexts": [
              "automation",
              "command"
            ],
            "options": [
              {
                "value": "normal",
                "label": "Send normal message"
              },
              {
                "value": "reply",
                "label": "Reply to triggering message where supported"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "normal",
              "timer": "normal",
              "command": "normal",
              "pad": "normal"
            },
            "runtimeFallbackNote": "Resolve message; blank output does nothing. event/missing target uses origin; all means Twitch + YouTube + Kick. Reply style applies only to the originating platform with an actor message ID. Timers scope delivery to their eligible platform.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "chat",
            "message": "",
            "platform": "event"
          },
          "timer": {
            "type": "chat",
            "message": "",
            "platform": "all"
          },
          "command": {
            "type": "chat",
            "message": "",
            "platform": "event"
          },
          "pad": {
            "type": "chat",
            "message": "",
            "platform": "all"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Chat Bot Commands, select Send chat message, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.announcement",
      "kind": "action",
      "runtimeKey": "announcement",
      "label": "Send announcement",
      "category": "Stream Platform Commands",
      "summary": "Send a native Twitch announcement when possible. Other platforms fall back to a normal announcement-style chat message.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected output chat; Twitch announcement permissions for native delivery.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.announcement"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "message": "Community night is Friday!",
            "platform": "twitch",
            "color": "primary"
          }
        }
      ],
      "details": {
        "behavior": "Resolve message; blank does nothing. color falls back to primary. Native Twitch announcement when available; other outputs use announcement-style normal chat.",
        "fields": [
          {
            "key": "message",
            "type": "textarea",
            "label": "Announcement",
            "placeholder": "Important stream update!",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve message; blank does nothing. color falls back to primary. Native Twitch announcement when available; other outputs use announcement-style normal chat.",
            "dynamicSource": null
          },
          {
            "key": "color",
            "type": "select",
            "label": "Twitch color",
            "options": [
              {
                "value": "primary",
                "label": "Primary"
              },
              {
                "value": "blue",
                "label": "Blue"
              },
              {
                "value": "green",
                "label": "Green"
              },
              {
                "value": "orange",
                "label": "Orange"
              },
              {
                "value": "purple",
                "label": "Purple"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "primary",
              "timer": "primary",
              "command": "primary",
              "pad": "primary"
            },
            "runtimeFallbackNote": "Resolve message; blank does nothing. color falls back to primary. Native Twitch announcement when available; other outputs use announcement-style normal chat.",
            "dynamicSource": null
          },
          {
            "key": "platform",
            "type": "select",
            "label": "Send to",
            "options": [
              {
                "value": "event",
                "label": "Same platform as event"
              },
              {
                "value": "all",
                "label": "Twitch + YouTube + Kick"
              },
              {
                "value": "twitch",
                "label": "Twitch"
              },
              {
                "value": "youtube",
                "label": "YouTube"
              },
              {
                "value": "kick",
                "label": "Kick"
              },
              {
                "value": "tiktok",
                "label": "TikTok"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "event",
              "timer": "all",
              "command": "event",
              "pad": "all"
            },
            "runtimeFallbackNote": "Resolve message; blank does nothing. color falls back to primary. Native Twitch announcement when available; other outputs use announcement-style normal chat.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "announcement",
            "message": "",
            "platform": "event",
            "color": "primary"
          },
          "timer": {
            "type": "announcement",
            "message": "",
            "platform": "all",
            "color": "primary"
          },
          "command": {
            "type": "announcement",
            "message": "",
            "platform": "event",
            "color": "primary"
          },
          "pad": {
            "type": "announcement",
            "message": "",
            "platform": "all",
            "color": "primary"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Stream Platform Commands, select Send announcement, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.chat_delay",
      "kind": "action",
      "runtimeKey": "chat_delay",
      "label": "Send chat message (delayed)",
      "category": "Chat Bot Commands",
      "summary": "Send a message after a delay. Useful for countdowns before ad breaks.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected output chat when the scheduled callback runs.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.chat_delay"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "message": "The delay was {delay} seconds.",
            "delay_sec": 30,
            "platform": "twitch"
          }
        }
      ],
      "details": {
        "behavior": "Schedule delivery and immediately continue the sequence. Missing delay_sec is 0 at runtime (editor initializes 30); runtime clamps only the lower bound to 0. Resolve message at delivery with local {delay}. Errors are logged inside the delayed callback.",
        "fields": [
          {
            "key": "message",
            "type": "textarea",
            "label": "Message",
            "placeholder": "⚠️ Ad break in {delay}s!",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Schedule delivery and immediately continue the sequence. Missing delay_sec is 0 at runtime (editor initializes 30); runtime clamps only the lower bound to 0. Resolve message at delivery with local {delay}. Errors are logged inside the delayed callback.",
            "dynamicSource": null
          },
          {
            "key": "delay_sec",
            "type": "number",
            "label": "Delay (seconds)",
            "min": 1,
            "max": 3600,
            "default": 30,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": 30,
              "timer": 30,
              "command": 30,
              "pad": 30
            },
            "runtimeFallbackNote": "Schedule delivery and immediately continue the sequence. Missing delay_sec is 0 at runtime (editor initializes 30); runtime clamps only the lower bound to 0. Resolve message at delivery with local {delay}. Errors are logged inside the delayed callback.",
            "dynamicSource": null
          },
          {
            "key": "platform",
            "type": "select",
            "label": "Send to",
            "options": [
              {
                "value": "event",
                "label": "Same platform as event"
              },
              {
                "value": "all",
                "label": "Twitch + YouTube + Kick"
              },
              {
                "value": "twitch",
                "label": "Twitch only"
              },
              {
                "value": "youtube",
                "label": "YouTube only"
              },
              {
                "value": "kick",
                "label": "Kick only"
              },
              {
                "value": "tiktok",
                "label": "TikTok only"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "event",
              "timer": "all",
              "command": "event",
              "pad": "all"
            },
            "runtimeFallbackNote": "Schedule delivery and immediately continue the sequence. Missing delay_sec is 0 at runtime (editor initializes 30); runtime clamps only the lower bound to 0. Resolve message at delivery with local {delay}. Errors are logged inside the delayed callback.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "chat_delay",
            "message": "",
            "platform": "event",
            "delay_sec": 30
          },
          "timer": {
            "type": "chat_delay",
            "message": "",
            "platform": "all",
            "delay_sec": 30
          },
          "command": {
            "type": "chat_delay",
            "message": "",
            "platform": "event",
            "delay_sec": 30
          },
          "pad": {
            "type": "chat_delay",
            "message": "",
            "platform": "all",
            "delay_sec": 30
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [
          "variable.action.chat_delay.delay"
        ],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Chat Bot Commands, select Send chat message (delayed), and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.shoutout",
      "kind": "action",
      "runtimeKey": "shoutout",
      "label": "Shoutout",
      "category": "Stream Platform Commands",
      "summary": "Send a native Twitch shoutout for the triggering user. Requires an event with a {user}.",
      "status": "supported",
      "contexts": [
        "automation",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Twitch event, connected broadcaster and shoutout permissions/cooldown eligibility.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.shoutout"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Native shoutouts are a Twitch-only API action.",
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "username_override": "ExampleCreator"
          }
        }
      ],
      "details": {
        "behavior": "Native Twitch shoutout only; non-Twitch origin fails. Literal username_override takes precedence over trigger user; no target does nothing. This is separate from generated introductions.",
        "fields": [
          {
            "key": "username_override",
            "type": "text",
            "label": "Username (blank = trigger user)",
            "placeholder": "",
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Native Twitch shoutout only; non-Twitch origin fails. Literal username_override takes precedence over trigger user; no target does nothing. This is separate from generated introductions.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [
          "{user}"
        ],
        "defaultsByContext": {
          "automation": {
            "type": "shoutout",
            "message": "",
            "platform": "event"
          },
          "timer": {
            "type": "shoutout",
            "message": "",
            "platform": "all"
          },
          "command": {
            "type": "shoutout",
            "message": "",
            "platform": "event"
          },
          "pad": {
            "type": "shoutout",
            "message": "",
            "platform": "all"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Stream Platform Commands, select Shoutout, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.song_request",
      "kind": "action",
      "runtimeKey": "song_request",
      "label": "Song request",
      "category": "Music Controls",
      "summary": "Add a song or search query to the song request queue. This works even if the public !sr chat command is disabled.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Song request playback/queue configuration and supported media source.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.song_request"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "query": "Example song",
            "platform": "twitch",
            "sendResponse": false
          }
        }
      ],
      "details": {
        "behavior": "Run registered !sr as an automation actor, even when the public command is disabled. Blank query falls back to event input/message. Responses are suppressed unless sendResponse is true; the default response uses captured command output.",
        "fields": [
          {
            "key": "query",
            "type": "textarea",
            "label": "Song or search text",
            "placeholder": "Never Gonna Give You Up, a YouTube URL, or {message}",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "{message}",
              "timer": "",
              "command": "{message}",
              "pad": ""
            },
            "runtimeFallbackNote": "Run registered !sr as an automation actor, even when the public command is disabled. Blank query falls back to event input/message. Responses are suppressed unless sendResponse is true; the default response uses captured command output.",
            "dynamicSource": null
          },
          {
            "key": "platform",
            "type": "select",
            "label": "Platform",
            "options": [
              {
                "value": "event",
                "label": "Same platform as event"
              },
              {
                "value": "all",
                "label": "Twitch + YouTube + Kick"
              },
              {
                "value": "twitch",
                "label": "Twitch"
              },
              {
                "value": "youtube",
                "label": "YouTube"
              },
              {
                "value": "kick",
                "label": "Kick"
              },
              {
                "value": "tiktok",
                "label": "TikTok"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "event",
              "timer": "all",
              "command": "event",
              "pad": "all"
            },
            "runtimeFallbackNote": "Run registered !sr as an automation actor, even when the public command is disabled. Blank query falls back to event input/message. Responses are suppressed unless sendResponse is true; the default response uses captured command output.",
            "dynamicSource": null
          },
          {
            "key": "sendResponse",
            "type": "checkbox",
            "label": "Send chat response",
            "default": false,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": false,
              "timer": false,
              "command": false,
              "pad": false
            },
            "runtimeFallbackNote": "Run registered !sr as an automation actor, even when the public command is disabled. Blank query falls back to event input/message. Responses are suppressed unless sendResponse is true; the default response uses captured command output.",
            "dynamicSource": null
          },
          {
            "key": "response",
            "type": "textarea",
            "label": "Response",
            "placeholder": "@{user} — \"{title}\" by {artist} added to the queue!",
            "default": "@{user} — \"{title}\" by {artist} added to the queue!",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "@{user} — \"{title}\" by {artist} added to the queue!",
              "timer": "@{user} — \"{title}\" by {artist} added to the queue!",
              "command": "@{user} — \"{title}\" by {artist} added to the queue!",
              "pad": "@{user} — \"{title}\" by {artist} added to the queue!"
            },
            "runtimeFallbackNote": "Run registered !sr as an automation actor, even when the public command is disabled. Blank query falls back to event input/message. Responses are suppressed unless sendResponse is true; the default response uses captured command output.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "song_request",
            "message": "",
            "platform": "event",
            "query": "{message}",
            "sendResponse": false,
            "response": "@{user} — \"{title}\" by {artist} added to the queue!"
          },
          "timer": {
            "type": "song_request",
            "message": "",
            "platform": "all",
            "query": "",
            "sendResponse": false,
            "response": "@{user} — \"{title}\" by {artist} added to the queue!"
          },
          "command": {
            "type": "song_request",
            "message": "",
            "platform": "event",
            "query": "{message}",
            "sendResponse": false,
            "response": "@{user} — \"{title}\" by {artist} added to the queue!"
          },
          "pad": {
            "type": "song_request",
            "message": "",
            "platform": "all",
            "query": "",
            "sendResponse": false,
            "response": "@{user} — \"{title}\" by {artist} added to the queue!"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Music Controls, select Song request, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.song_now_playing",
      "kind": "action",
      "runtimeKey": "song_now_playing",
      "label": "Current song",
      "category": "Music Controls",
      "summary": "Post the currently playing song.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Active song/playback state.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.song_now_playing"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "platform": "twitch",
            "sendResponse": true
          }
        }
      ],
      "details": {
        "behavior": "Run !song silently; only send chat output when sendResponse is true. Default response uses captured output; custom response resolves variables.",
        "fields": [
          {
            "key": "platform",
            "type": "select",
            "label": "Platform",
            "options": [
              {
                "value": "event",
                "label": "Same platform as event"
              },
              {
                "value": "all",
                "label": "Twitch + YouTube + Kick"
              },
              {
                "value": "twitch",
                "label": "Twitch"
              },
              {
                "value": "youtube",
                "label": "YouTube"
              },
              {
                "value": "kick",
                "label": "Kick"
              },
              {
                "value": "tiktok",
                "label": "TikTok"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "event",
              "timer": "all",
              "command": "event",
              "pad": "all"
            },
            "runtimeFallbackNote": "Run !song silently; only send chat output when sendResponse is true. Default response uses captured output; custom response resolves variables.",
            "dynamicSource": null
          },
          {
            "key": "sendResponse",
            "type": "checkbox",
            "label": "Send chat response",
            "default": false,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": false,
              "timer": false,
              "command": false,
              "pad": false
            },
            "runtimeFallbackNote": "Run !song silently; only send chat output when sendResponse is true. Default response uses captured output; custom response resolves variables.",
            "dynamicSource": null
          },
          {
            "key": "response",
            "type": "textarea",
            "label": "Response",
            "placeholder": "Now playing: {title} by {artist}{requested_by}",
            "default": "Now playing: {title} by {artist}{requested_by}",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "Now playing: {title} by {artist}{requested_by}",
              "timer": "Now playing: {title} by {artist}{requested_by}",
              "command": "Now playing: {title} by {artist}{requested_by}",
              "pad": "Now playing: {title} by {artist}{requested_by}"
            },
            "runtimeFallbackNote": "Run !song silently; only send chat output when sendResponse is true. Default response uses captured output; custom response resolves variables.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "song_now_playing",
            "message": "",
            "platform": "event",
            "sendResponse": false,
            "response": "Now playing: {title} by {artist}{requested_by}"
          },
          "timer": {
            "type": "song_now_playing",
            "message": "",
            "platform": "all",
            "sendResponse": false,
            "response": "Now playing: {title} by {artist}{requested_by}"
          },
          "command": {
            "type": "song_now_playing",
            "message": "",
            "platform": "event",
            "sendResponse": false,
            "response": "Now playing: {title} by {artist}{requested_by}"
          },
          "pad": {
            "type": "song_now_playing",
            "message": "",
            "platform": "all",
            "sendResponse": false,
            "response": "Now playing: {title} by {artist}{requested_by}"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Music Controls, select Current song, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.song_queue",
      "kind": "action",
      "runtimeKey": "song_queue",
      "label": "Show song queue",
      "category": "Music Controls",
      "summary": "Post the current song request queue.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Configured song request queue.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.song_queue"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "platform": "twitch",
            "sendResponse": true
          }
        }
      ],
      "details": {
        "behavior": "Run !queue silently; chat output is opt-in via sendResponse. Default response uses captured output.",
        "fields": [
          {
            "key": "platform",
            "type": "select",
            "label": "Platform",
            "options": [
              {
                "value": "event",
                "label": "Same platform as event"
              },
              {
                "value": "all",
                "label": "Twitch + YouTube + Kick"
              },
              {
                "value": "twitch",
                "label": "Twitch"
              },
              {
                "value": "youtube",
                "label": "YouTube"
              },
              {
                "value": "kick",
                "label": "Kick"
              },
              {
                "value": "tiktok",
                "label": "TikTok"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "event",
              "timer": "all",
              "command": "event",
              "pad": "all"
            },
            "runtimeFallbackNote": "Run !queue silently; chat output is opt-in via sendResponse. Default response uses captured output.",
            "dynamicSource": null
          },
          {
            "key": "sendResponse",
            "type": "checkbox",
            "label": "Send chat response",
            "default": false,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": false,
              "timer": false,
              "command": false,
              "pad": false
            },
            "runtimeFallbackNote": "Run !queue silently; chat output is opt-in via sendResponse. Default response uses captured output.",
            "dynamicSource": null
          },
          {
            "key": "response",
            "type": "textarea",
            "label": "Response",
            "placeholder": "Queue: {queue}",
            "default": "Queue: {queue}",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "Queue: {queue}",
              "timer": "Queue: {queue}",
              "command": "Queue: {queue}",
              "pad": "Queue: {queue}"
            },
            "runtimeFallbackNote": "Run !queue silently; chat output is opt-in via sendResponse. Default response uses captured output.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "song_queue",
            "message": "",
            "platform": "event",
            "sendResponse": false,
            "response": "Queue: {queue}"
          },
          "timer": {
            "type": "song_queue",
            "message": "",
            "platform": "all",
            "sendResponse": false,
            "response": "Queue: {queue}"
          },
          "command": {
            "type": "song_queue",
            "message": "",
            "platform": "event",
            "sendResponse": false,
            "response": "Queue: {queue}"
          },
          "pad": {
            "type": "song_queue",
            "message": "",
            "platform": "all",
            "sendResponse": false,
            "response": "Queue: {queue}"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Music Controls, select Show song queue, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.song_skip",
      "kind": "action",
      "runtimeKey": "song_skip",
      "label": "Skip song",
      "category": "Music Controls",
      "summary": "Skip the current song request.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Active song request playback.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.song_skip"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "platform": "twitch",
            "sendResponse": false
          }
        }
      ],
      "details": {
        "behavior": "Run !songskip; chat output is opt-in via sendResponse.",
        "fields": [
          {
            "key": "platform",
            "type": "select",
            "label": "Platform",
            "options": [
              {
                "value": "event",
                "label": "Same platform as event"
              },
              {
                "value": "all",
                "label": "Twitch + YouTube + Kick"
              },
              {
                "value": "twitch",
                "label": "Twitch"
              },
              {
                "value": "youtube",
                "label": "YouTube"
              },
              {
                "value": "kick",
                "label": "Kick"
              },
              {
                "value": "tiktok",
                "label": "TikTok"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "event",
              "timer": "all",
              "command": "event",
              "pad": "all"
            },
            "runtimeFallbackNote": "Run !songskip; chat output is opt-in via sendResponse.",
            "dynamicSource": null
          },
          {
            "key": "sendResponse",
            "type": "checkbox",
            "label": "Send chat response",
            "default": false,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": false,
              "timer": false,
              "command": false,
              "pad": false
            },
            "runtimeFallbackNote": "Run !songskip; chat output is opt-in via sendResponse.",
            "dynamicSource": null
          },
          {
            "key": "response",
            "type": "textarea",
            "label": "Response",
            "placeholder": "@{user} skipped the current song.",
            "default": "@{user} skipped the current song.",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "@{user} skipped the current song.",
              "timer": "@{user} skipped the current song.",
              "command": "@{user} skipped the current song.",
              "pad": "@{user} skipped the current song."
            },
            "runtimeFallbackNote": "Run !songskip; chat output is opt-in via sendResponse.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "song_skip",
            "message": "",
            "platform": "event",
            "sendResponse": false,
            "response": "@{user} skipped the current song."
          },
          "timer": {
            "type": "song_skip",
            "message": "",
            "platform": "all",
            "sendResponse": false,
            "response": "@{user} skipped the current song."
          },
          "command": {
            "type": "song_skip",
            "message": "",
            "platform": "event",
            "sendResponse": false,
            "response": "@{user} skipped the current song."
          },
          "pad": {
            "type": "song_skip",
            "message": "",
            "platform": "all",
            "sendResponse": false,
            "response": "@{user} skipped the current song."
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Music Controls, select Skip song, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.song_pause",
      "kind": "action",
      "runtimeKey": "song_pause",
      "label": "Pause song",
      "category": "Music Controls",
      "summary": "Pause song request playback.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Song request playback.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.song_pause"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "platform": "twitch",
            "sendResponse": false
          }
        }
      ],
      "details": {
        "behavior": "Run !songpause; chat output is opt-in via sendResponse.",
        "fields": [
          {
            "key": "platform",
            "type": "select",
            "label": "Platform",
            "options": [
              {
                "value": "event",
                "label": "Same platform as event"
              },
              {
                "value": "all",
                "label": "Twitch + YouTube + Kick"
              },
              {
                "value": "twitch",
                "label": "Twitch"
              },
              {
                "value": "youtube",
                "label": "YouTube"
              },
              {
                "value": "kick",
                "label": "Kick"
              },
              {
                "value": "tiktok",
                "label": "TikTok"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "event",
              "timer": "all",
              "command": "event",
              "pad": "all"
            },
            "runtimeFallbackNote": "Run !songpause; chat output is opt-in via sendResponse.",
            "dynamicSource": null
          },
          {
            "key": "sendResponse",
            "type": "checkbox",
            "label": "Send chat response",
            "default": false,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": false,
              "timer": false,
              "command": false,
              "pad": false
            },
            "runtimeFallbackNote": "Run !songpause; chat output is opt-in via sendResponse.",
            "dynamicSource": null
          },
          {
            "key": "response",
            "type": "textarea",
            "label": "Response",
            "placeholder": "Playback paused.",
            "default": "Playback paused.",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "Playback paused.",
              "timer": "Playback paused.",
              "command": "Playback paused.",
              "pad": "Playback paused."
            },
            "runtimeFallbackNote": "Run !songpause; chat output is opt-in via sendResponse.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "song_pause",
            "message": "",
            "platform": "event",
            "sendResponse": false,
            "response": "Playback paused."
          },
          "timer": {
            "type": "song_pause",
            "message": "",
            "platform": "all",
            "sendResponse": false,
            "response": "Playback paused."
          },
          "command": {
            "type": "song_pause",
            "message": "",
            "platform": "event",
            "sendResponse": false,
            "response": "Playback paused."
          },
          "pad": {
            "type": "song_pause",
            "message": "",
            "platform": "all",
            "sendResponse": false,
            "response": "Playback paused."
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Music Controls, select Pause song, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.song_resume",
      "kind": "action",
      "runtimeKey": "song_resume",
      "label": "Resume song",
      "category": "Music Controls",
      "summary": "Resume song request playback.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Paused song request playback.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.song_resume"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "platform": "twitch",
            "sendResponse": false
          }
        }
      ],
      "details": {
        "behavior": "Run !songresume; chat output is opt-in via sendResponse.",
        "fields": [
          {
            "key": "platform",
            "type": "select",
            "label": "Platform",
            "options": [
              {
                "value": "event",
                "label": "Same platform as event"
              },
              {
                "value": "all",
                "label": "Twitch + YouTube + Kick"
              },
              {
                "value": "twitch",
                "label": "Twitch"
              },
              {
                "value": "youtube",
                "label": "YouTube"
              },
              {
                "value": "kick",
                "label": "Kick"
              },
              {
                "value": "tiktok",
                "label": "TikTok"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "event",
              "timer": "all",
              "command": "event",
              "pad": "all"
            },
            "runtimeFallbackNote": "Run !songresume; chat output is opt-in via sendResponse.",
            "dynamicSource": null
          },
          {
            "key": "sendResponse",
            "type": "checkbox",
            "label": "Send chat response",
            "default": false,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": false,
              "timer": false,
              "command": false,
              "pad": false
            },
            "runtimeFallbackNote": "Run !songresume; chat output is opt-in via sendResponse.",
            "dynamicSource": null
          },
          {
            "key": "response",
            "type": "textarea",
            "label": "Response",
            "placeholder": "Playback resumed.",
            "default": "Playback resumed.",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "Playback resumed.",
              "timer": "Playback resumed.",
              "command": "Playback resumed.",
              "pad": "Playback resumed."
            },
            "runtimeFallbackNote": "Run !songresume; chat output is opt-in via sendResponse.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "song_resume",
            "message": "",
            "platform": "event",
            "sendResponse": false,
            "response": "Playback resumed."
          },
          "timer": {
            "type": "song_resume",
            "message": "",
            "platform": "all",
            "sendResponse": false,
            "response": "Playback resumed."
          },
          "command": {
            "type": "song_resume",
            "message": "",
            "platform": "event",
            "sendResponse": false,
            "response": "Playback resumed."
          },
          "pad": {
            "type": "song_resume",
            "message": "",
            "platform": "all",
            "sendResponse": false,
            "response": "Playback resumed."
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Music Controls, select Resume song, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.bonus_points",
      "kind": "action",
      "runtimeKey": "bonus_points",
      "label": "Give bonus loyalty",
      "category": "Chat Bot Commands",
      "summary": "Award bonus loyalty currency to a viewer. Blank username uses the triggering viewer when available.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Loyalty enabled and a resolvable viewer identity.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.bonus_points"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "username": "ExampleViewer",
            "amount": "100",
            "platform": "twitch"
          }
        }
      ],
      "details": {
        "behavior": "Blank username uses the event user. Resolve amount; require a positive safe whole number. Award per target platform and send the result. Matching trigger identity is retained only on the originating platform.",
        "fields": [
          {
            "key": "username",
            "type": "text",
            "label": "Username",
            "placeholder": "{user}",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "{user}",
              "timer": "",
              "command": "{user}",
              "pad": ""
            },
            "runtimeFallbackNote": "Blank username uses the event user. Resolve amount; require a positive safe whole number. Award per target platform and send the result. Matching trigger identity is retained only on the originating platform.",
            "dynamicSource": null
          },
          {
            "key": "amount",
            "type": "text",
            "label": "Loyalty amount",
            "placeholder": "500",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "100",
              "timer": "100",
              "command": "100",
              "pad": "100"
            },
            "runtimeFallbackNote": "Blank username uses the event user. Resolve amount; require a positive safe whole number. Award per target platform and send the result. Matching trigger identity is retained only on the originating platform.",
            "dynamicSource": null
          },
          {
            "key": "platform",
            "type": "select",
            "label": "Platform",
            "options": [
              {
                "value": "event",
                "label": "Same platform as event"
              },
              {
                "value": "all",
                "label": "Twitch + YouTube + Kick"
              },
              {
                "value": "twitch",
                "label": "Twitch"
              },
              {
                "value": "youtube",
                "label": "YouTube"
              },
              {
                "value": "kick",
                "label": "Kick"
              },
              {
                "value": "tiktok",
                "label": "TikTok"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "event",
              "timer": "all",
              "command": "event",
              "pad": "all"
            },
            "runtimeFallbackNote": "Blank username uses the event user. Resolve amount; require a positive safe whole number. Award per target platform and send the result. Matching trigger identity is retained only on the originating platform.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "bonus_points",
            "message": "",
            "platform": "event",
            "username": "{user}",
            "amount": "100"
          },
          "timer": {
            "type": "bonus_points",
            "message": "",
            "platform": "all",
            "username": "",
            "amount": "100"
          },
          "command": {
            "type": "bonus_points",
            "message": "",
            "platform": "event",
            "username": "{user}",
            "amount": "100"
          },
          "pad": {
            "type": "bonus_points",
            "message": "",
            "platform": "all",
            "username": "",
            "amount": "100"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Chat Bot Commands, select Give bonus loyalty, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.set_loyalty_point_name",
      "kind": "action",
      "runtimeKey": "set_loyalty_point_name",
      "label": "Set loyalty name",
      "category": "Utilities",
      "summary": "Change the loyalty currency name everywhere in SheevChat without changing viewer balances or other loyalty settings.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Loyalty settings available.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.set_loyalty_point_name"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "pointsName": "stars"
          }
        }
      ],
      "details": {
        "behavior": "Resolve and require a nonempty name; the field allows 32 characters. Changes the displayed currency name without altering balances.",
        "fields": [
          {
            "key": "pointsName",
            "type": "text",
            "label": "Loyalty name",
            "placeholder": "points",
            "maxlength": 32,
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve and require a nonempty name; the field allows 32 characters. Changes the displayed currency name without altering balances.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "set_loyalty_point_name",
            "pointsName": ""
          },
          "timer": {
            "type": "set_loyalty_point_name",
            "pointsName": ""
          },
          "command": {
            "type": "set_loyalty_point_name",
            "pointsName": ""
          },
          "pad": {
            "type": "set_loyalty_point_name",
            "pointsName": ""
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Utilities, select Set loyalty name, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.windows_set_default_playback",
      "kind": "action",
      "runtimeKey": "windows_set_default_playback",
      "label": "Set Windows playback device",
      "category": "Utilities",
      "summary": "Change the Windows default playback endpoint. Console + Multimedia covers normal app audio; Communications is separate for calling apps.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Windows and an available playback endpoint selected from the local list.",
        "accountFeature": null,
        "operatingSystems": [
          "windows"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.windows_set_default_playback"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "deviceId": "fixture-playback",
            "roles": "console_multimedia"
          }
        }
      ],
      "details": {
        "behavior": "Select a local playback endpoint. Roles default to console_multimedia; communications and all are separate choices. Open apps may retain their current audio stream.",
        "fields": [
          {
            "key": "deviceId",
            "type": "windows_audio_device_select",
            "label": "Playback device",
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Select a local playback endpoint. Roles default to console_multimedia; communications and all are separate choices. Open apps may retain their current audio stream.",
            "dynamicSource": "Local Playback device picker; select an existing resource, never invent its ID."
          },
          {
            "key": "roles",
            "type": "select",
            "label": "Windows default roles",
            "default": "console_multimedia",
            "options": [
              {
                "value": "console_multimedia",
                "label": "Console + Multimedia (recommended)"
              },
              {
                "value": "communications",
                "label": "Communications only"
              },
              {
                "value": "all",
                "label": "All roles"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "console_multimedia",
              "timer": "console_multimedia",
              "command": "console_multimedia",
              "pad": "console_multimedia"
            },
            "runtimeFallbackNote": "Select a local playback endpoint. Roles default to console_multimedia; communications and all are separate choices. Open apps may retain their current audio stream.",
            "dynamicSource": null
          },
          {
            "key": "migrationNote",
            "type": "info",
            "label": "Already-open apps may keep their existing device until they reopen their audio stream.",
            "configurable": false,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Select a local playback endpoint. Roles default to console_multimedia; communications and all are separate choices. Open apps may retain their current audio stream.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "windows_set_default_playback",
            "deviceId": "",
            "deviceName": "",
            "roles": "console_multimedia"
          },
          "timer": {
            "type": "windows_set_default_playback",
            "deviceId": "",
            "deviceName": "",
            "roles": "console_multimedia"
          },
          "command": {
            "type": "windows_set_default_playback",
            "deviceId": "",
            "deviceName": "",
            "roles": "console_multimedia"
          },
          "pad": {
            "type": "windows_set_default_playback",
            "deviceId": "",
            "deviceName": "",
            "roles": "console_multimedia"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Utilities, select Set Windows playback device, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.windows_set_default_input",
      "kind": "action",
      "runtimeKey": "windows_set_default_input",
      "label": "Set Windows input device",
      "category": "Utilities",
      "summary": "Change the Windows default microphone or capture endpoint. Console + Multimedia covers normal app input; Communications is separate for calling apps.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Windows and an available recording endpoint selected from the local list.",
        "accountFeature": null,
        "operatingSystems": [
          "windows"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.windows_set_default_input"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "deviceId": "fixture-input",
            "roles": "console_multimedia"
          }
        }
      ],
      "details": {
        "behavior": "Select a local recording endpoint. Roles default to console_multimedia. Open apps may retain the old input until they reopen their stream.",
        "fields": [
          {
            "key": "deviceId",
            "type": "windows_audio_input_device_select",
            "label": "Input device",
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Select a local recording endpoint. Roles default to console_multimedia. Open apps may retain the old input until they reopen their stream.",
            "dynamicSource": "Local Input device picker; select an existing resource, never invent its ID."
          },
          {
            "key": "roles",
            "type": "select",
            "label": "Windows default roles",
            "default": "console_multimedia",
            "options": [
              {
                "value": "console_multimedia",
                "label": "Console + Multimedia (recommended)"
              },
              {
                "value": "communications",
                "label": "Communications only"
              },
              {
                "value": "all",
                "label": "All roles"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "console_multimedia",
              "timer": "console_multimedia",
              "command": "console_multimedia",
              "pad": "console_multimedia"
            },
            "runtimeFallbackNote": "Select a local recording endpoint. Roles default to console_multimedia. Open apps may retain the old input until they reopen their stream.",
            "dynamicSource": null
          },
          {
            "key": "migrationNote",
            "type": "info",
            "label": "Already-open apps may keep their existing input until they reopen their audio stream.",
            "configurable": false,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Select a local recording endpoint. Roles default to console_multimedia. Open apps may retain the old input until they reopen their stream.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "windows_set_default_input",
            "deviceId": "",
            "deviceName": "",
            "roles": "console_multimedia"
          },
          "timer": {
            "type": "windows_set_default_input",
            "deviceId": "",
            "deviceName": "",
            "roles": "console_multimedia"
          },
          "command": {
            "type": "windows_set_default_input",
            "deviceId": "",
            "deviceName": "",
            "roles": "console_multimedia"
          },
          "pad": {
            "type": "windows_set_default_input",
            "deviceId": "",
            "deviceName": "",
            "roles": "console_multimedia"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Utilities, select Set Windows input device, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.windows_set_system_volume",
      "kind": "action",
      "runtimeKey": "windows_set_system_volume",
      "label": "Set Windows system volume",
      "category": "Utilities",
      "summary": "Set the master volume on the current default Multimedia playback device.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Windows audio service and a default Multimedia endpoint.",
        "accountFeature": null,
        "operatingSystems": [
          "windows"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.windows_set_system_volume"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "volume": 50
          }
        }
      ],
      "details": {
        "behavior": "Set current default Multimedia playback master volume; missing volume defaults to 50. Valid UI range is 0–100 percent.",
        "fields": [
          {
            "key": "volume",
            "type": "number",
            "label": "System volume percent",
            "min": 0,
            "max": 100,
            "default": 50,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": 50,
              "timer": 50,
              "command": 50,
              "pad": 50
            },
            "runtimeFallbackNote": "Set current default Multimedia playback master volume; missing volume defaults to 50. Valid UI range is 0–100 percent.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "windows_set_system_volume",
            "volume": 50
          },
          "timer": {
            "type": "windows_set_system_volume",
            "volume": 50
          },
          "command": {
            "type": "windows_set_system_volume",
            "volume": 50
          },
          "pad": {
            "type": "windows_set_system_volume",
            "volume": 50
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Utilities, select Set Windows system volume, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.windows_set_system_mute",
      "kind": "action",
      "runtimeKey": "windows_set_system_mute",
      "label": "Set Windows system mute",
      "category": "Utilities",
      "summary": "Mute, unmute, or toggle the current default Multimedia playback device.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Windows audio service and a default Multimedia endpoint.",
        "accountFeature": null,
        "operatingSystems": [
          "windows"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.windows_set_system_mute"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "mode": "toggle"
          }
        }
      ],
      "details": {
        "behavior": "Mode defaults to toggle; mute/unmute set explicit state on the default Multimedia playback endpoint.",
        "fields": [
          {
            "key": "mode",
            "type": "select",
            "label": "Mute action",
            "default": "toggle",
            "options": [
              {
                "value": "toggle",
                "label": "Toggle mute"
              },
              {
                "value": "mute",
                "label": "Mute"
              },
              {
                "value": "unmute",
                "label": "Unmute"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "toggle",
              "timer": "toggle",
              "command": "toggle",
              "pad": "toggle"
            },
            "runtimeFallbackNote": "Mode defaults to toggle; mute/unmute set explicit state on the default Multimedia playback endpoint.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "windows_set_system_mute",
            "mode": "toggle"
          },
          "timer": {
            "type": "windows_set_system_mute",
            "mode": "toggle"
          },
          "command": {
            "type": "windows_set_system_mute",
            "mode": "toggle"
          },
          "pad": {
            "type": "windows_set_system_mute",
            "mode": "toggle"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Utilities, select Set Windows system mute, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.twitch_snooze_upcoming_ad",
      "kind": "action",
      "runtimeKey": "twitch_snooze_upcoming_ad",
      "label": "Snooze upcoming Twitch ad",
      "category": "Stream Platform Commands",
      "summary": "Use one available Twitch ad snooze. In an Incoming raid Automation, optionally skip this action unless the next ad falls within a chosen window.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Twitch broadcaster ad-management access and an available snooze. Use Incoming raid context for a captured ad window.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.twitch_snooze_upcoming_ad"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Ad snoozing is a Twitch-only API action.",
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "withinMinutes": 0
          }
        }
      ],
      "details": {
        "behavior": "withinMinutes defaults to 0 and clamps 0–180. A positive window skips when the captured upcoming-ad schedule is outside the window or unavailable; 0 attempts a snooze without this test.",
        "fields": [
          {
            "key": "withinMinutes",
            "type": "number",
            "label": "Only if next ad is within minutes (0 = always)",
            "min": 0,
            "max": 180,
            "default": 0,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": 0,
              "timer": 0,
              "command": 0,
              "pad": 0
            },
            "runtimeFallbackNote": "withinMinutes defaults to 0 and clamps 0–180. A positive window skips when the captured upcoming-ad schedule is outside the window or unavailable; 0 attempts a snooze without this test.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "twitch_snooze_upcoming_ad"
          },
          "timer": {
            "type": "twitch_snooze_upcoming_ad"
          },
          "command": {
            "type": "twitch_snooze_upcoming_ad"
          },
          "pad": {
            "type": "twitch_snooze_upcoming_ad"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Stream Platform Commands, select Snooze upcoming Twitch ad, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.top_points",
      "kind": "action",
      "runtimeKey": "top_points",
      "label": "Show top loyalty",
      "category": "Chat Bot Commands",
      "summary": "Post the loyalty leaderboard.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Loyalty enabled.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.top_points"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "platform": "twitch"
          }
        }
      ],
      "details": {
        "behavior": "Run registered !top as an automation actor and post its reply per output target.",
        "fields": [
          {
            "key": "platform",
            "type": "select",
            "label": "Platform",
            "options": [
              {
                "value": "event",
                "label": "Same platform as event"
              },
              {
                "value": "all",
                "label": "Twitch + YouTube + Kick"
              },
              {
                "value": "twitch",
                "label": "Twitch"
              },
              {
                "value": "youtube",
                "label": "YouTube"
              },
              {
                "value": "kick",
                "label": "Kick"
              },
              {
                "value": "tiktok",
                "label": "TikTok"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "event",
              "timer": "all",
              "command": "event",
              "pad": "all"
            },
            "runtimeFallbackNote": "Run registered !top as an automation actor and post its reply per output target.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "top_points",
            "message": "",
            "platform": "event"
          },
          "timer": {
            "type": "top_points",
            "message": "",
            "platform": "all"
          },
          "command": {
            "type": "top_points",
            "message": "",
            "platform": "event"
          },
          "pad": {
            "type": "top_points",
            "message": "",
            "platform": "all"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Chat Bot Commands, select Show top loyalty, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.random_quote",
      "kind": "action",
      "runtimeKey": "random_quote",
      "label": "Post random quote",
      "category": "Chat Bot Commands",
      "summary": "Post a random saved quote, or search if filter text is provided.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "At least one saved quote for a result.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.random_quote"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "filter": "",
            "platform": "twitch"
          }
        }
      ],
      "details": {
        "behavior": "Run !quote with optional resolved filter/ID; blank chooses a random saved quote.",
        "fields": [
          {
            "key": "filter",
            "type": "text",
            "label": "Optional search text or quote ID",
            "placeholder": "",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Run !quote with optional resolved filter/ID; blank chooses a random saved quote.",
            "dynamicSource": null
          },
          {
            "key": "platform",
            "type": "select",
            "label": "Platform",
            "options": [
              {
                "value": "event",
                "label": "Same platform as event"
              },
              {
                "value": "all",
                "label": "Twitch + YouTube + Kick"
              },
              {
                "value": "twitch",
                "label": "Twitch"
              },
              {
                "value": "youtube",
                "label": "YouTube"
              },
              {
                "value": "kick",
                "label": "Kick"
              },
              {
                "value": "tiktok",
                "label": "TikTok"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "event",
              "timer": "all",
              "command": "event",
              "pad": "all"
            },
            "runtimeFallbackNote": "Run !quote with optional resolved filter/ID; blank chooses a random saved quote.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "random_quote",
            "message": "",
            "platform": "event"
          },
          "timer": {
            "type": "random_quote",
            "message": "",
            "platform": "all"
          },
          "command": {
            "type": "random_quote",
            "message": "",
            "platform": "event"
          },
          "pad": {
            "type": "random_quote",
            "message": "",
            "platform": "all"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Chat Bot Commands, select Post random quote, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.add_quote",
      "kind": "action",
      "runtimeKey": "add_quote",
      "label": "Add quote",
      "category": "Chat Bot Commands",
      "summary": "Save a quote to the quote database.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Quote storage available.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.add_quote"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "quote_text": "An example quote",
            "platform": "twitch"
          }
        }
      ],
      "details": {
        "behavior": "Resolve quote_text and pass it to !quoteadd; saves through the normal quote command handler.",
        "fields": [
          {
            "key": "quote_text",
            "type": "textarea",
            "label": "Quote text",
            "placeholder": "{user}: {message}",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "{user}: {message}",
              "timer": "",
              "command": "{user}: {message}",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve quote_text and pass it to !quoteadd; saves through the normal quote command handler.",
            "dynamicSource": null
          },
          {
            "key": "platform",
            "type": "select",
            "label": "Platform",
            "options": [
              {
                "value": "event",
                "label": "Same platform as event"
              },
              {
                "value": "all",
                "label": "Twitch + YouTube + Kick"
              },
              {
                "value": "twitch",
                "label": "Twitch"
              },
              {
                "value": "youtube",
                "label": "YouTube"
              },
              {
                "value": "kick",
                "label": "Kick"
              },
              {
                "value": "tiktok",
                "label": "TikTok"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "event",
              "timer": "all",
              "command": "event",
              "pad": "all"
            },
            "runtimeFallbackNote": "Resolve quote_text and pass it to !quoteadd; saves through the normal quote command handler.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "add_quote",
            "message": "",
            "platform": "event",
            "quote_text": "{user}: {message}"
          },
          "timer": {
            "type": "add_quote",
            "message": "",
            "platform": "all",
            "quote_text": ""
          },
          "command": {
            "type": "add_quote",
            "message": "",
            "platform": "event",
            "quote_text": "{user}: {message}"
          },
          "pad": {
            "type": "add_quote",
            "message": "",
            "platform": "all",
            "quote_text": ""
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Chat Bot Commands, select Add quote, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.increment_counter",
      "kind": "action",
      "runtimeKey": "increment_counter",
      "label": "Increment counter",
      "category": "Chat Bot Commands",
      "summary": "Add to a named counter. Amount defaults to 1.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Named counter or permission to create it through the command handler.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.increment_counter"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "counter_name": "deaths",
            "amount": "1",
            "platform": "twitch"
          }
        }
      ],
      "details": {
        "behavior": "Resolve counter_name and amount; missing amount defaults to 1. Dispatch !count on each chosen platform.",
        "fields": [
          {
            "key": "counter_name",
            "type": "text",
            "label": "Counter name",
            "placeholder": "deaths",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve counter_name and amount; missing amount defaults to 1. Dispatch !count on each chosen platform.",
            "dynamicSource": null
          },
          {
            "key": "amount",
            "type": "text",
            "label": "Amount",
            "placeholder": "1",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "1",
              "timer": "1",
              "command": "1",
              "pad": "1"
            },
            "runtimeFallbackNote": "Resolve counter_name and amount; missing amount defaults to 1. Dispatch !count on each chosen platform.",
            "dynamicSource": null
          },
          {
            "key": "platform",
            "type": "select",
            "label": "Platform",
            "options": [
              {
                "value": "event",
                "label": "Same platform as event"
              },
              {
                "value": "all",
                "label": "Twitch + YouTube + Kick"
              },
              {
                "value": "twitch",
                "label": "Twitch"
              },
              {
                "value": "youtube",
                "label": "YouTube"
              },
              {
                "value": "kick",
                "label": "Kick"
              },
              {
                "value": "tiktok",
                "label": "TikTok"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "event",
              "timer": "all",
              "command": "event",
              "pad": "all"
            },
            "runtimeFallbackNote": "Resolve counter_name and amount; missing amount defaults to 1. Dispatch !count on each chosen platform.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "increment_counter",
            "message": "",
            "platform": "event",
            "counter_name": "",
            "amount": "1"
          },
          "timer": {
            "type": "increment_counter",
            "message": "",
            "platform": "all",
            "counter_name": "",
            "amount": "1"
          },
          "command": {
            "type": "increment_counter",
            "message": "",
            "platform": "event",
            "counter_name": "",
            "amount": "1"
          },
          "pad": {
            "type": "increment_counter",
            "message": "",
            "platform": "all",
            "counter_name": "",
            "amount": "1"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Chat Bot Commands, select Increment counter, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.set_counter",
      "kind": "action",
      "runtimeKey": "set_counter",
      "label": "Set counter",
      "category": "Chat Bot Commands",
      "summary": "Set a named counter to a specific value.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Counter storage available.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.set_counter"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "counter_name": "deaths",
            "value": "5",
            "platform": "twitch"
          }
        }
      ],
      "details": {
        "behavior": "Resolve counter_name and value; missing value defaults to 0. Dispatch !setcounter.",
        "fields": [
          {
            "key": "counter_name",
            "type": "text",
            "label": "Counter name",
            "placeholder": "deaths",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve counter_name and value; missing value defaults to 0. Dispatch !setcounter.",
            "dynamicSource": null
          },
          {
            "key": "value",
            "type": "text",
            "label": "Value",
            "placeholder": "0",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "0",
              "timer": "0",
              "command": "0",
              "pad": "0"
            },
            "runtimeFallbackNote": "Resolve counter_name and value; missing value defaults to 0. Dispatch !setcounter.",
            "dynamicSource": null
          },
          {
            "key": "platform",
            "type": "select",
            "label": "Platform",
            "options": [
              {
                "value": "event",
                "label": "Same platform as event"
              },
              {
                "value": "all",
                "label": "Twitch + YouTube + Kick"
              },
              {
                "value": "twitch",
                "label": "Twitch"
              },
              {
                "value": "youtube",
                "label": "YouTube"
              },
              {
                "value": "kick",
                "label": "Kick"
              },
              {
                "value": "tiktok",
                "label": "TikTok"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "event",
              "timer": "all",
              "command": "event",
              "pad": "all"
            },
            "runtimeFallbackNote": "Resolve counter_name and value; missing value defaults to 0. Dispatch !setcounter.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "set_counter",
            "message": "",
            "platform": "event",
            "counter_name": "",
            "value": "0"
          },
          "timer": {
            "type": "set_counter",
            "message": "",
            "platform": "all",
            "counter_name": "",
            "value": "0"
          },
          "command": {
            "type": "set_counter",
            "message": "",
            "platform": "event",
            "counter_name": "",
            "value": "0"
          },
          "pad": {
            "type": "set_counter",
            "message": "",
            "platform": "all",
            "counter_name": "",
            "value": "0"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Chat Bot Commands, select Set counter, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.reset_counter",
      "kind": "action",
      "runtimeKey": "reset_counter",
      "label": "Reset counter",
      "category": "Chat Bot Commands",
      "summary": "Reset a named counter back to zero.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "A named counter.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.reset_counter"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "counter_name": "deaths",
            "platform": "twitch"
          }
        }
      ],
      "details": {
        "behavior": "Resolve counter name through !resetcounter and reset it to zero.",
        "fields": [
          {
            "key": "counter_name",
            "type": "text",
            "label": "Counter name",
            "placeholder": "deaths",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve counter name through !resetcounter and reset it to zero.",
            "dynamicSource": null
          },
          {
            "key": "platform",
            "type": "select",
            "label": "Platform",
            "options": [
              {
                "value": "event",
                "label": "Same platform as event"
              },
              {
                "value": "all",
                "label": "Twitch + YouTube + Kick"
              },
              {
                "value": "twitch",
                "label": "Twitch"
              },
              {
                "value": "youtube",
                "label": "YouTube"
              },
              {
                "value": "kick",
                "label": "Kick"
              },
              {
                "value": "tiktok",
                "label": "TikTok"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "event",
              "timer": "all",
              "command": "event",
              "pad": "all"
            },
            "runtimeFallbackNote": "Resolve counter name through !resetcounter and reset it to zero.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "reset_counter",
            "message": "",
            "platform": "event",
            "counter_name": ""
          },
          "timer": {
            "type": "reset_counter",
            "message": "",
            "platform": "all",
            "counter_name": ""
          },
          "command": {
            "type": "reset_counter",
            "message": "",
            "platform": "event",
            "counter_name": ""
          },
          "pad": {
            "type": "reset_counter",
            "message": "",
            "platform": "all",
            "counter_name": ""
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Chat Bot Commands, select Reset counter, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.increment_user_counter",
      "kind": "action",
      "runtimeKey": "increment_user_counter",
      "label": "Increment user counter",
      "category": "Chat Bot Commands",
      "summary": "Add to one viewer inside a user counter category. Blank username uses the triggering viewer.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "User counter category and viewer identity.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.increment_user_counter"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "category": "Check In",
            "username": "ExampleViewer",
            "amount": "1",
            "platform": "twitch"
          }
        }
      ],
      "details": {
        "behavior": "Resolve category, username and amount; blank username uses event user, missing amount is 1. Adjust one viewer per target platform.",
        "fields": [
          {
            "key": "category",
            "type": "text",
            "label": "Counter category",
            "placeholder": "Check In",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve category, username and amount; blank username uses event user, missing amount is 1. Adjust one viewer per target platform.",
            "dynamicSource": null
          },
          {
            "key": "username",
            "type": "text",
            "label": "Username",
            "placeholder": "{user}",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "{user}",
              "timer": "",
              "command": "{user}",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve category, username and amount; blank username uses event user, missing amount is 1. Adjust one viewer per target platform.",
            "dynamicSource": null
          },
          {
            "key": "amount",
            "type": "text",
            "label": "Amount",
            "placeholder": "1",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "1",
              "timer": "1",
              "command": "1",
              "pad": "1"
            },
            "runtimeFallbackNote": "Resolve category, username and amount; blank username uses event user, missing amount is 1. Adjust one viewer per target platform.",
            "dynamicSource": null
          },
          {
            "key": "platform",
            "type": "select",
            "label": "Platform",
            "options": [
              {
                "value": "event",
                "label": "Same platform as event"
              },
              {
                "value": "all",
                "label": "Twitch + YouTube + Kick"
              },
              {
                "value": "twitch",
                "label": "Twitch"
              },
              {
                "value": "youtube",
                "label": "YouTube"
              },
              {
                "value": "kick",
                "label": "Kick"
              },
              {
                "value": "tiktok",
                "label": "TikTok"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "event",
              "timer": "all",
              "command": "event",
              "pad": "all"
            },
            "runtimeFallbackNote": "Resolve category, username and amount; blank username uses event user, missing amount is 1. Adjust one viewer per target platform.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "increment_user_counter",
            "message": "",
            "platform": "event",
            "category": "",
            "username": "{user}",
            "amount": "1"
          },
          "timer": {
            "type": "increment_user_counter",
            "message": "",
            "platform": "all",
            "category": "",
            "username": "",
            "amount": "1"
          },
          "command": {
            "type": "increment_user_counter",
            "message": "",
            "platform": "event",
            "category": "",
            "username": "{user}",
            "amount": "1"
          },
          "pad": {
            "type": "increment_user_counter",
            "message": "",
            "platform": "all",
            "category": "",
            "username": "",
            "amount": "1"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Chat Bot Commands, select Increment user counter, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.set_user_counter",
      "kind": "action",
      "runtimeKey": "set_user_counter",
      "label": "Set user counter",
      "category": "Chat Bot Commands",
      "summary": "Set one viewer value inside a user counter category.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "User counter category and viewer identity.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.set_user_counter"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "category": "Check In",
            "username": "ExampleViewer",
            "value": "5",
            "platform": "twitch"
          }
        }
      ],
      "details": {
        "behavior": "Resolve category, username and value; blank username uses event user, missing value is 0. Set the viewer value per target platform.",
        "fields": [
          {
            "key": "category",
            "type": "text",
            "label": "Counter category",
            "placeholder": "Check In",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve category, username and value; blank username uses event user, missing value is 0. Set the viewer value per target platform.",
            "dynamicSource": null
          },
          {
            "key": "username",
            "type": "text",
            "label": "Username",
            "placeholder": "{user}",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "{user}",
              "timer": "",
              "command": "{user}",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve category, username and value; blank username uses event user, missing value is 0. Set the viewer value per target platform.",
            "dynamicSource": null
          },
          {
            "key": "value",
            "type": "text",
            "label": "Value",
            "placeholder": "0",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "0",
              "timer": "0",
              "command": "0",
              "pad": "0"
            },
            "runtimeFallbackNote": "Resolve category, username and value; blank username uses event user, missing value is 0. Set the viewer value per target platform.",
            "dynamicSource": null
          },
          {
            "key": "platform",
            "type": "select",
            "label": "Platform",
            "options": [
              {
                "value": "event",
                "label": "Same platform as event"
              },
              {
                "value": "all",
                "label": "Twitch + YouTube + Kick"
              },
              {
                "value": "twitch",
                "label": "Twitch"
              },
              {
                "value": "youtube",
                "label": "YouTube"
              },
              {
                "value": "kick",
                "label": "Kick"
              },
              {
                "value": "tiktok",
                "label": "TikTok"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "event",
              "timer": "all",
              "command": "event",
              "pad": "all"
            },
            "runtimeFallbackNote": "Resolve category, username and value; blank username uses event user, missing value is 0. Set the viewer value per target platform.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "set_user_counter",
            "message": "",
            "platform": "event",
            "category": "",
            "username": "{user}",
            "value": "0"
          },
          "timer": {
            "type": "set_user_counter",
            "message": "",
            "platform": "all",
            "category": "",
            "username": "",
            "value": "0"
          },
          "command": {
            "type": "set_user_counter",
            "message": "",
            "platform": "event",
            "category": "",
            "username": "{user}",
            "value": "0"
          },
          "pad": {
            "type": "set_user_counter",
            "message": "",
            "platform": "all",
            "category": "",
            "username": "",
            "value": "0"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Chat Bot Commands, select Set user counter, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.reset_user_counter",
      "kind": "action",
      "runtimeKey": "reset_user_counter",
      "label": "Reset user counter",
      "category": "Chat Bot Commands",
      "summary": "Reset one viewer value inside a user counter category.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "User counter category and viewer identity.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.reset_user_counter"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "category": "Check In",
            "username": "ExampleViewer",
            "platform": "twitch"
          }
        }
      ],
      "details": {
        "behavior": "Resolve category and username; blank username uses event user. Set the viewer value to zero per target platform.",
        "fields": [
          {
            "key": "category",
            "type": "text",
            "label": "Counter category",
            "placeholder": "Check In",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve category and username; blank username uses event user. Set the viewer value to zero per target platform.",
            "dynamicSource": null
          },
          {
            "key": "username",
            "type": "text",
            "label": "Username",
            "placeholder": "{user}",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "{user}",
              "timer": "",
              "command": "{user}",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve category and username; blank username uses event user. Set the viewer value to zero per target platform.",
            "dynamicSource": null
          },
          {
            "key": "platform",
            "type": "select",
            "label": "Platform",
            "options": [
              {
                "value": "event",
                "label": "Same platform as event"
              },
              {
                "value": "all",
                "label": "Twitch + YouTube + Kick"
              },
              {
                "value": "twitch",
                "label": "Twitch"
              },
              {
                "value": "youtube",
                "label": "YouTube"
              },
              {
                "value": "kick",
                "label": "Kick"
              },
              {
                "value": "tiktok",
                "label": "TikTok"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "event",
              "timer": "all",
              "command": "event",
              "pad": "all"
            },
            "runtimeFallbackNote": "Resolve category and username; blank username uses event user. Set the viewer value to zero per target platform.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "reset_user_counter",
            "message": "",
            "platform": "event",
            "category": "",
            "username": "{user}"
          },
          "timer": {
            "type": "reset_user_counter",
            "message": "",
            "platform": "all",
            "category": "",
            "username": ""
          },
          "command": {
            "type": "reset_user_counter",
            "message": "",
            "platform": "event",
            "category": "",
            "username": "{user}"
          },
          "pad": {
            "type": "reset_user_counter",
            "message": "",
            "platform": "all",
            "category": "",
            "username": ""
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Chat Bot Commands, select Reset user counter, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.watchtime_lookup",
      "kind": "action",
      "runtimeKey": "watchtime_lookup",
      "label": "Show watchtime",
      "category": "Chat Bot Commands",
      "summary": "Post watchtime for a viewer. Blank username uses the triggering viewer when available.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Tracked viewer watchtime.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.watchtime_lookup"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "username": "ExampleViewer",
            "platform": "twitch"
          }
        }
      ],
      "details": {
        "behavior": "Blank username uses event user. Resolve and run !watchtime as an automation actor.",
        "fields": [
          {
            "key": "username",
            "type": "text",
            "label": "Username",
            "placeholder": "{user}",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "{user}",
              "timer": "",
              "command": "{user}",
              "pad": ""
            },
            "runtimeFallbackNote": "Blank username uses event user. Resolve and run !watchtime as an automation actor.",
            "dynamicSource": null
          },
          {
            "key": "platform",
            "type": "select",
            "label": "Platform",
            "options": [
              {
                "value": "event",
                "label": "Same platform as event"
              },
              {
                "value": "all",
                "label": "Twitch + YouTube + Kick"
              },
              {
                "value": "twitch",
                "label": "Twitch"
              },
              {
                "value": "youtube",
                "label": "YouTube"
              },
              {
                "value": "kick",
                "label": "Kick"
              },
              {
                "value": "tiktok",
                "label": "TikTok"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "event",
              "timer": "all",
              "command": "event",
              "pad": "all"
            },
            "runtimeFallbackNote": "Blank username uses event user. Resolve and run !watchtime as an automation actor.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "watchtime_lookup",
            "message": "",
            "platform": "event",
            "username": "{user}"
          },
          "timer": {
            "type": "watchtime_lookup",
            "message": "",
            "platform": "all",
            "username": ""
          },
          "command": {
            "type": "watchtime_lookup",
            "message": "",
            "platform": "event",
            "username": "{user}"
          },
          "pad": {
            "type": "watchtime_lookup",
            "message": "",
            "platform": "all",
            "username": ""
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Chat Bot Commands, select Show watchtime, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.stop_trivia",
      "kind": "action",
      "runtimeKey": "stop_trivia",
      "label": "Stop trivia",
      "category": "Chat Bot Commands",
      "summary": "Stop the one active unified trivia game on every participating platform.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Trivia runtime; no independent per-platform game is created.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.stop_trivia"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {}
        }
      ],
      "details": {
        "behavior": "Stop the single shared active trivia game across participating platforms; no target fields.",
        "fields": [],
        "declaredContexts": [
          "timer",
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "stop_trivia",
            "message": "",
            "platform": "event"
          },
          "timer": {
            "type": "stop_trivia",
            "message": "",
            "platform": "all"
          },
          "command": {
            "type": "stop_trivia",
            "message": "",
            "platform": "event"
          },
          "pad": {
            "type": "stop_trivia",
            "message": "",
            "platform": "all"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Chat Bot Commands, select Stop trivia, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.set_stream_title",
      "kind": "action",
      "runtimeKey": "set_stream_title",
      "label": "Set stream title",
      "category": "Stream Platform Commands",
      "summary": "Update the stream title on selected platforms. Supports command variables.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected selected broadcaster accounts with metadata update permissions. TikTok title updates are unsupported.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.set_stream_title"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "TikTok does not expose a supported stream-title update API.",
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "title": "Community night",
            "twitch": true,
            "youtube": false,
            "kick": false
          }
        }
      ],
      "details": {
        "behavior": "Resolve title and trim; blank does nothing. Apply to selected Twitch/YouTube/Kick toggles; missing toggles select all three. Timers restrict toggles to the current eligible platform.",
        "fields": [
          {
            "key": "title",
            "type": "textarea",
            "label": "Title",
            "placeholder": "Tonight: {channel.category} with chat",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve title and trim; blank does nothing. Apply to selected Twitch/YouTube/Kick toggles; missing toggles select all three. Timers restrict toggles to the current eligible platform.",
            "dynamicSource": null
          },
          {
            "key": "twitch",
            "type": "checkbox",
            "label": "Twitch",
            "default": true,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": true,
              "timer": true,
              "command": true,
              "pad": true
            },
            "runtimeFallbackNote": "Resolve title and trim; blank does nothing. Apply to selected Twitch/YouTube/Kick toggles; missing toggles select all three. Timers restrict toggles to the current eligible platform.",
            "dynamicSource": null
          },
          {
            "key": "youtube",
            "type": "checkbox",
            "label": "YouTube",
            "default": true,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": true,
              "timer": true,
              "command": true,
              "pad": true
            },
            "runtimeFallbackNote": "Resolve title and trim; blank does nothing. Apply to selected Twitch/YouTube/Kick toggles; missing toggles select all three. Timers restrict toggles to the current eligible platform.",
            "dynamicSource": null
          },
          {
            "key": "kick",
            "type": "checkbox",
            "label": "Kick",
            "default": true,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": true,
              "timer": true,
              "command": true,
              "pad": true
            },
            "runtimeFallbackNote": "Resolve title and trim; blank does nothing. Apply to selected Twitch/YouTube/Kick toggles; missing toggles select all three. Timers restrict toggles to the current eligible platform.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "set_stream_title",
            "title": "",
            "twitch": true,
            "youtube": true,
            "kick": true
          },
          "timer": {
            "type": "set_stream_title",
            "title": "",
            "twitch": true,
            "youtube": true,
            "kick": true
          },
          "command": {
            "type": "set_stream_title",
            "title": "",
            "twitch": true,
            "youtube": true,
            "kick": true
          },
          "pad": {
            "type": "set_stream_title",
            "title": "",
            "twitch": true,
            "youtube": true,
            "kick": true
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Stream Platform Commands, select Set stream title, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.set_stream_category",
      "kind": "action",
      "runtimeKey": "set_stream_category",
      "label": "Set stream category",
      "category": "Stream Platform Commands",
      "summary": "Update the category/game on selected platforms. YouTube also accepts a numeric category ID.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected selected broadcaster accounts with category update permissions. TikTok is unsupported.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.set_stream_category"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "TikTok does not expose a supported stream-category update API.",
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "category": "Just Chatting",
            "twitch": true,
            "youtube": false,
            "kick": false
          }
        }
      ],
      "details": {
        "behavior": "Resolve category and trim; blank does nothing. Apply to selected Twitch/YouTube/Kick toggles; missing toggles select all three. Provider category resolution may fail independently.",
        "fields": [
          {
            "key": "category",
            "type": "text",
            "label": "Category / game",
            "placeholder": "Just Chatting",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve category and trim; blank does nothing. Apply to selected Twitch/YouTube/Kick toggles; missing toggles select all three. Provider category resolution may fail independently.",
            "dynamicSource": null
          },
          {
            "key": "twitch",
            "type": "checkbox",
            "label": "Twitch",
            "default": true,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": true,
              "timer": true,
              "command": true,
              "pad": true
            },
            "runtimeFallbackNote": "Resolve category and trim; blank does nothing. Apply to selected Twitch/YouTube/Kick toggles; missing toggles select all three. Provider category resolution may fail independently.",
            "dynamicSource": null
          },
          {
            "key": "youtube",
            "type": "checkbox",
            "label": "YouTube",
            "default": true,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": true,
              "timer": true,
              "command": true,
              "pad": true
            },
            "runtimeFallbackNote": "Resolve category and trim; blank does nothing. Apply to selected Twitch/YouTube/Kick toggles; missing toggles select all three. Provider category resolution may fail independently.",
            "dynamicSource": null
          },
          {
            "key": "kick",
            "type": "checkbox",
            "label": "Kick",
            "default": true,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": true,
              "timer": true,
              "command": true,
              "pad": true
            },
            "runtimeFallbackNote": "Resolve category and trim; blank does nothing. Apply to selected Twitch/YouTube/Kick toggles; missing toggles select all three. Provider category resolution may fail independently.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "set_stream_category",
            "category": "",
            "twitch": true,
            "youtube": true,
            "kick": true
          },
          "timer": {
            "type": "set_stream_category",
            "category": "",
            "twitch": true,
            "youtube": true,
            "kick": true
          },
          "command": {
            "type": "set_stream_category",
            "category": "",
            "twitch": true,
            "youtube": true,
            "kick": true
          },
          "pad": {
            "type": "set_stream_category",
            "category": "",
            "twitch": true,
            "youtube": true,
            "kick": true
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Stream Platform Commands, select Set stream category, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.change_theme",
      "kind": "action",
      "runtimeKey": "change_theme",
      "label": "Chat Overlay",
      "category": "Change Theme",
      "summary": "Apply a saved Chat Overlay theme preset. Future overlay theme packs will use this same picker.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "A compatible saved chat overlay theme.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.change_theme"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "target": "chat_overlay",
            "presetId": "fixture-theme"
          }
        }
      ],
      "details": {
        "behavior": "Apply a saved chat overlay preset; preset selection is a saved resource ID, not a CSS payload.",
        "fields": [
          {
            "key": "presetId",
            "type": "theme_select",
            "label": "Chat Overlay preset",
            "source": "overlay_presets.chat",
            "labelKey": "presetName",
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Apply a saved chat overlay preset; preset selection is a saved resource ID, not a CSS payload.",
            "dynamicSource": "overlay_presets.chat"
          },
          {
            "key": "transitionStyle",
            "type": "select",
            "label": "Transition",
            "default": "none",
            "options": [
              {
                "value": "none",
                "label": "None"
              },
              {
                "value": "fade",
                "label": "Fade"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "none",
              "timer": "none",
              "command": "none",
              "pad": "none"
            },
            "runtimeFallbackNote": "Apply a saved chat overlay preset; preset selection is a saved resource ID, not a CSS payload.",
            "dynamicSource": null
          },
          {
            "key": "transitionMs",
            "type": "number",
            "label": "Transition time (ms)",
            "default": 0,
            "min": 0,
            "max": 30000,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": 0,
              "timer": 0,
              "command": 0,
              "pad": 0
            },
            "runtimeFallbackNote": "Apply a saved chat overlay preset; preset selection is a saved resource ID, not a CSS payload.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "change_theme",
            "target": "chat_overlay",
            "presetId": "",
            "presetName": ""
          },
          "timer": {
            "type": "change_theme",
            "target": "chat_overlay",
            "presetId": "",
            "presetName": ""
          },
          "command": {
            "type": "change_theme",
            "target": "chat_overlay",
            "presetId": "",
            "presetName": ""
          },
          "pad": {
            "type": "change_theme",
            "target": "chat_overlay",
            "presetId": "",
            "presetName": ""
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Change Theme, select Chat Overlay, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.change_master_overlay",
      "kind": "action",
      "runtimeKey": "change_master_overlay",
      "label": "Master Overlay",
      "category": "Change Theme",
      "summary": "Switch the dynamic Master Overlay source to an existing Overlay Builder overlay.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "A saved Overlay Builder source and running master overlay.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.change_master_overlay"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "overlaySlug": "fixture-overlay",
            "transitionStyle": "none",
            "transitionMs": 0
          }
        }
      ],
      "details": {
        "behavior": "Switch the master overlay to a saved Overlay Builder source with the selected transition; requires a saved source.",
        "fields": [
          {
            "key": "overlaySlug",
            "type": "theme_select",
            "label": "Master Overlay target",
            "source": "overlay_builder.saved_overlays",
            "labelKey": "overlayName",
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Switch the master overlay to a saved Overlay Builder source with the selected transition; requires a saved source.",
            "dynamicSource": "overlay_builder.saved_overlays"
          },
          {
            "key": "transitionStyle",
            "type": "select",
            "label": "Transition",
            "default": "none",
            "options": [
              {
                "value": "none",
                "label": "None"
              },
              {
                "value": "fade",
                "label": "Fade"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "none",
              "timer": "none",
              "command": "none",
              "pad": "none"
            },
            "runtimeFallbackNote": "Switch the master overlay to a saved Overlay Builder source with the selected transition; requires a saved source.",
            "dynamicSource": null
          },
          {
            "key": "transitionMs",
            "type": "number",
            "label": "Transition time (ms)",
            "default": 0,
            "min": 0,
            "max": 30000,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": 0,
              "timer": 0,
              "command": 0,
              "pad": 0
            },
            "runtimeFallbackNote": "Switch the master overlay to a saved Overlay Builder source with the selected transition; requires a saved source.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "change_master_overlay",
            "overlaySlug": "",
            "overlayName": "",
            "transitionStyle": "none",
            "transitionMs": 0
          },
          "timer": {
            "type": "change_master_overlay",
            "overlaySlug": "",
            "overlayName": "",
            "transitionStyle": "none",
            "transitionMs": 0
          },
          "command": {
            "type": "change_master_overlay",
            "overlaySlug": "",
            "overlayName": "",
            "transitionStyle": "none",
            "transitionMs": 0
          },
          "pad": {
            "type": "change_master_overlay",
            "overlaySlug": "",
            "overlayName": "",
            "transitionStyle": "none",
            "transitionMs": 0
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Change Theme, select Master Overlay, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.ui_resizing",
      "kind": "action",
      "runtimeKey": "ui_resizing",
      "label": "UI Resizing",
      "category": "SheevChat",
      "summary": "Adjust SheevChat UI font-size sliders from commands, automations, timers, or SheevPad.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "SheevChat renderer connected.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.ui_resizing"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "target": "all",
            "direction": "increase",
            "amount": 1
          }
        }
      ],
      "details": {
        "behavior": "Adjust the selected app font area by a step clamped 1–8. Missing direction increases; decrease applies a negative step; target defaults to all.",
        "fields": [
          {
            "key": "target",
            "type": "select",
            "label": "Resize",
            "default": "all",
            "options": [
              {
                "value": "all",
                "label": "All UI font sliders"
              },
              {
                "value": "chat",
                "label": "Chat font"
              },
              {
                "value": "events",
                "label": "Events font"
              },
              {
                "value": "viewers",
                "label": "Viewers font"
              },
              {
                "value": "sidebar",
                "label": "Sidebar font"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "all",
              "timer": "all",
              "command": "all",
              "pad": "all"
            },
            "runtimeFallbackNote": "Adjust the selected app font area by a step clamped 1–8. Missing direction increases; decrease applies a negative step; target defaults to all.",
            "dynamicSource": null
          },
          {
            "key": "direction",
            "type": "select",
            "label": "Direction",
            "default": "increase",
            "options": [
              {
                "value": "increase",
                "label": "Increase"
              },
              {
                "value": "decrease",
                "label": "Decrease"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "increase",
              "timer": "increase",
              "command": "increase",
              "pad": "increase"
            },
            "runtimeFallbackNote": "Adjust the selected app font area by a step clamped 1–8. Missing direction increases; decrease applies a negative step; target defaults to all.",
            "dynamicSource": null
          },
          {
            "key": "amount",
            "type": "number",
            "label": "Step size",
            "default": 1,
            "min": 1,
            "max": 8,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": 1,
              "timer": 1,
              "command": 1,
              "pad": 1
            },
            "runtimeFallbackNote": "Adjust the selected app font area by a step clamped 1–8. Missing direction increases; decrease applies a negative step; target defaults to all.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "ui_resizing",
            "target": "all",
            "direction": "increase",
            "amount": 1
          },
          "timer": {
            "type": "ui_resizing",
            "target": "all",
            "direction": "increase",
            "amount": 1
          },
          "command": {
            "type": "ui_resizing",
            "target": "all",
            "direction": "increase",
            "amount": 1
          },
          "pad": {
            "type": "ui_resizing",
            "target": "all",
            "direction": "increase",
            "amount": 1
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category SheevChat, select UI Resizing, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.trigger_alert",
      "kind": "action",
      "runtimeKey": "trigger_alert",
      "label": "Trigger Alert",
      "category": "Send to Overlay",
      "summary": "Send an alert payload to Overlay Builder Alert Box widgets. Event variables from raids, subs, follows, cheers, and custom triggers can be used in the text fields.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Saved Alert Box preset/placement and running Overlay Builder browser source.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.trigger_alert"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "overlaySlug": "fixture-overlay",
            "presetId": "fixture-alert",
            "title": "Hello",
            "message": "Welcome {user}!",
            "durationMs": 8000
          }
        }
      ],
      "details": {
        "behavior": "Resolve title/message, then dispatch to Alert Box placements using selected overlay/preset/media. Blank resource values allow downstream preset/default resolution. Duration is milliseconds; do not treat seconds as milliseconds.",
        "fields": [
          {
            "key": "overlaySlug",
            "type": "theme_select",
            "label": "Overlay source",
            "source": "overlay_builder.overlays",
            "labelKey": "overlayName",
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve title/message, then dispatch to Alert Box placements using selected overlay/preset/media. Blank resource values allow downstream preset/default resolution. Duration is milliseconds; do not treat seconds as milliseconds.",
            "dynamicSource": "overlay_builder.overlays"
          },
          {
            "key": "presetId",
            "type": "theme_select",
            "label": "Alert preset",
            "source": "alert_presets.local",
            "labelKey": "presetName",
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve title/message, then dispatch to Alert Box placements using selected overlay/preset/media. Blank resource values allow downstream preset/default resolution. Duration is milliseconds; do not treat seconds as milliseconds.",
            "dynamicSource": "alert_presets.local"
          },
          {
            "key": "alertType",
            "type": "select",
            "label": "Alert context",
            "default": "custom",
            "options": [
              {
                "value": "custom",
                "label": "Custom"
              },
              {
                "value": "follow",
                "label": "Follow"
              },
              {
                "value": "sub",
                "label": "Subscription"
              },
              {
                "value": "gift_sub",
                "label": "Gift sub"
              },
              {
                "value": "raid",
                "label": "Raid"
              },
              {
                "value": "cheer",
                "label": "Bits / KICKs"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "custom",
              "timer": "custom",
              "command": "custom",
              "pad": "custom"
            },
            "runtimeFallbackNote": "Resolve title/message, then dispatch to Alert Box placements using selected overlay/preset/media. Blank resource values allow downstream preset/default resolution. Duration is milliseconds; do not treat seconds as milliseconds.",
            "dynamicSource": null
          },
          {
            "key": "title",
            "type": "text",
            "label": "Title",
            "placeholder": "Alert",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve title/message, then dispatch to Alert Box placements using selected overlay/preset/media. Blank resource values allow downstream preset/default resolution. Duration is milliseconds; do not treat seconds as milliseconds.",
            "dynamicSource": null
          },
          {
            "key": "message",
            "type": "textarea",
            "label": "Message",
            "placeholder": "{user} triggered an alert!",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve title/message, then dispatch to Alert Box placements using selected overlay/preset/media. Blank resource values allow downstream preset/default resolution. Duration is milliseconds; do not treat seconds as milliseconds.",
            "dynamicSource": null
          },
          {
            "key": "mediaId",
            "type": "media_select",
            "label": "Visual media",
            "mediaTypes": "image,gif,video",
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve title/message, then dispatch to Alert Box placements using selected overlay/preset/media. Blank resource values allow downstream preset/default resolution. Duration is milliseconds; do not treat seconds as milliseconds.",
            "dynamicSource": "Local Visual media picker; select an existing resource, never invent its ID."
          },
          {
            "key": "soundId",
            "type": "media_select",
            "label": "Sound",
            "mediaTypes": "audio",
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve title/message, then dispatch to Alert Box placements using selected overlay/preset/media. Blank resource values allow downstream preset/default resolution. Duration is milliseconds; do not treat seconds as milliseconds.",
            "dynamicSource": "Local Sound picker; select an existing resource, never invent its ID."
          },
          {
            "key": "durationMs",
            "type": "number",
            "label": "Duration (ms)",
            "default": 8000,
            "min": 1000,
            "max": 60000,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": 8000,
              "timer": 8000,
              "command": 8000,
              "pad": 8000
            },
            "runtimeFallbackNote": "Resolve title/message, then dispatch to Alert Box placements using selected overlay/preset/media. Blank resource values allow downstream preset/default resolution. Duration is milliseconds; do not treat seconds as milliseconds.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "trigger_alert",
            "message": "",
            "overlaySlug": "",
            "overlayName": "",
            "presetId": "",
            "presetName": "",
            "title": "",
            "mediaId": "",
            "soundId": ""
          },
          "timer": {
            "type": "trigger_alert",
            "message": "",
            "overlaySlug": "",
            "overlayName": "",
            "presetId": "",
            "presetName": "",
            "title": "",
            "mediaId": "",
            "soundId": ""
          },
          "command": {
            "type": "trigger_alert",
            "message": "",
            "overlaySlug": "",
            "overlayName": "",
            "presetId": "",
            "presetName": "",
            "title": "",
            "mediaId": "",
            "soundId": ""
          },
          "pad": {
            "type": "trigger_alert",
            "message": "",
            "overlaySlug": "",
            "overlayName": "",
            "presetId": "",
            "presetName": "",
            "title": "",
            "mediaId": "",
            "soundId": ""
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Send to Overlay, select Trigger Alert, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.trigger_marketplace_widget",
      "kind": "action",
      "runtimeKey": "trigger_marketplace_widget",
      "label": "Trigger Marketplace Widget",
      "category": "Overlay Widgets",
      "summary": "Send a button/action event to a Marketplace Item widget in Overlay Builder.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Installed active Marketplace widget, placed surface and its declared action contract.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.trigger_marketplace_widget"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "widgetTarget": "fixture-widget",
            "buttonKey": "run",
            "payloadJson": "{}"
          }
        }
      ],
      "details": {
        "behavior": "Resolve buttonKey (runtime blank fallback run; editor initializes spinWheel) and payloadJson. Invalid JSON becomes a message payload rather than a parse failure. Target actions must exist on the installed widget.",
        "fields": [
          {
            "key": "widgetTarget",
            "type": "theme_select",
            "label": "Marketplace widget",
            "source": "overlay_builder.marketplace_widgets",
            "labelKey": "widgetName",
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve buttonKey (runtime blank fallback run; editor initializes spinWheel) and payloadJson. Invalid JSON becomes a message payload rather than a parse failure. Target actions must exist on the installed widget.",
            "dynamicSource": "overlay_builder.marketplace_widgets"
          },
          {
            "key": "buttonKey",
            "type": "text",
            "label": "Widget action",
            "placeholder": "spinWheel",
            "default": "spinWheel",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "spinWheel",
              "timer": "spinWheel",
              "command": "spinWheel",
              "pad": "spinWheel"
            },
            "runtimeFallbackNote": "Resolve buttonKey (runtime blank fallback run; editor initializes spinWheel) and payloadJson. Invalid JSON becomes a message payload rather than a parse failure. Target actions must exist on the installed widget.",
            "dynamicSource": null
          },
          {
            "key": "payloadJson",
            "type": "textarea",
            "label": "Payload JSON",
            "placeholder": "{\"source\":\"channel-point\"}",
            "default": "",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve buttonKey (runtime blank fallback run; editor initializes spinWheel) and payloadJson. Invalid JSON becomes a message payload rather than a parse failure. Target actions must exist on the installed widget.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "trigger_marketplace_widget",
            "widgetTarget": "",
            "widgetName": "",
            "buttonKey": "spinWheel",
            "payloadJson": ""
          },
          "timer": {
            "type": "trigger_marketplace_widget",
            "widgetTarget": "",
            "widgetName": "",
            "buttonKey": "spinWheel",
            "payloadJson": ""
          },
          "command": {
            "type": "trigger_marketplace_widget",
            "widgetTarget": "",
            "widgetName": "",
            "buttonKey": "spinWheel",
            "payloadJson": ""
          },
          "pad": {
            "type": "trigger_marketplace_widget",
            "widgetTarget": "",
            "widgetName": "",
            "buttonKey": "spinWheel",
            "payloadJson": ""
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Overlay Widgets, select Trigger Marketplace Widget, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.send_overlay_tts",
      "kind": "action",
      "runtimeKey": "send_overlay_tts",
      "label": "Send TTS/Text Payload",
      "category": "Send to Overlay",
      "summary": "Speak text through every running Overlay Builder browser source. This does not play desktop TTS audio.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Running Overlay Builder browser source and configured supported TTS voice.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.send_overlay_tts"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "text": "Welcome {user}!",
            "ttsVoice": ""
          }
        }
      ],
      "details": {
        "behavior": "Resolve text; blank does nothing. Speak through running Overlay Builder browser sources, not desktop TTS. Global voice is used unless a supported piper: or kokoro: override is selected.",
        "fields": [
          {
            "key": "text",
            "type": "textarea",
            "label": "Text",
            "placeholder": "{user} redeemed {reward}: {message}",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Resolve text; blank does nothing. Speak through running Overlay Builder browser sources, not desktop TTS. Global voice is used unless a supported piper: or kokoro: override is selected.",
            "dynamicSource": null
          },
          {
            "key": "ttsVoice",
            "type": "tts_voice_select",
            "label": "TTS voice",
            "default": "",
            "helpText": "Use global keeps the TTS voice selected in Settings > Audio. Piper/Kokoro overrides generate OBS/browser-source audio with that voice.",
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve text; blank does nothing. Speak through running Overlay Builder browser sources, not desktop TTS. Global voice is used unless a supported piper: or kokoro: override is selected.",
            "dynamicSource": "Local TTS voice picker; select an existing resource, never invent its ID."
          },
          {
            "key": "overlayAudioInfo",
            "type": "info",
            "label": "Plays automatically through all running Overlay Builder browser sources. No receiver widget or routing setup is required.",
            "configurable": false,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Resolve text; blank does nothing. Speak through running Overlay Builder browser sources, not desktop TTS. Global voice is used unless a supported piper: or kokoro: override is selected.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "send_overlay_tts",
            "message": "",
            "platform": "event"
          },
          "timer": {
            "type": "send_overlay_tts",
            "message": "",
            "platform": "all"
          },
          "command": {
            "type": "send_overlay_tts",
            "message": "",
            "platform": "event"
          },
          "pad": {
            "type": "send_overlay_tts",
            "message": "",
            "platform": "all"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Send to Overlay, select Send TTS/Text Payload, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.send_overlay_audio",
      "kind": "action",
      "runtimeKey": "send_overlay_audio",
      "label": "Play Audio Payload",
      "category": "Send to Overlay",
      "summary": "Play a Media Library audio item through every running Overlay Builder browser source. This does not play desktop audio.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Audio item in Media Library and running Overlay Builder browser source.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.send_overlay_audio"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "mediaId": "fixture-audio",
            "volume": 100
          }
        }
      ],
      "details": {
        "behavior": "Resolve mediaId and require an audio library item. Play in running browser sources, not the desktop window. Volume is a saved percent 0–100, editor default 100.",
        "fields": [
          {
            "key": "mediaId",
            "type": "media_select",
            "label": "Audio",
            "mediaTypes": "audio",
            "emptyHint": "No audio files in Media Library yet. Upload an audio file, then refresh this list.",
            "helpText": "The selected file plays automatically through running Overlay Builder browser sources.",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Resolve mediaId and require an audio library item. Play in running browser sources, not the desktop window. Volume is a saved percent 0–100, editor default 100.",
            "dynamicSource": "Local Audio picker; select an existing resource, never invent its ID."
          },
          {
            "key": "volume",
            "type": "number",
            "label": "Volume (%)",
            "default": 100,
            "min": 0,
            "max": 100,
            "helpText": "Saved on this command, automation, timer, or SheevPad action.",
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": 100,
              "timer": 100,
              "command": 100,
              "pad": 100
            },
            "runtimeFallbackNote": "Resolve mediaId and require an audio library item. Play in running browser sources, not the desktop window. Volume is a saved percent 0–100, editor default 100.",
            "dynamicSource": null
          },
          {
            "key": "audioInfo",
            "type": "info",
            "label": "No receiver widget or routing setup is required. This does not play through the SheevChat desktop window.",
            "configurable": false,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Resolve mediaId and require an audio library item. Play in running browser sources, not the desktop window. Volume is a saved percent 0–100, editor default 100.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "send_overlay_audio",
            "message": "",
            "platform": "event"
          },
          "timer": {
            "type": "send_overlay_audio",
            "message": "",
            "platform": "all"
          },
          "command": {
            "type": "send_overlay_audio",
            "message": "",
            "platform": "event"
          },
          "pad": {
            "type": "send_overlay_audio",
            "message": "",
            "platform": "all"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Send to Overlay, select Play Audio Payload, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.send_overlay_text",
      "kind": "action",
      "runtimeKey": "send_overlay_text",
      "label": "Send Text Payload",
      "category": "Send to Overlay",
      "summary": "Send a generic text payload to overlay widgets. Useful for custom widgets that display queue, prompt, or status text.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "A running compatible overlay receiver subscribed to the selected routing channel.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.send_overlay_text"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "text": "Community night",
            "targetMode": "broadcast",
            "channel": "text",
            "priority": 0,
            "ttlMs": 300000
          }
        }
      ],
      "details": {
        "behavior": "Resolve text; blank does nothing. Publish to receivers using targetMode (default broadcast), channel (text), selected overlay/widget, priority and TTL.",
        "fields": [
          {
            "key": "text",
            "type": "textarea",
            "label": "Text",
            "placeholder": "Overlay message with {variables}",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Resolve text; blank does nothing. Publish to receivers using targetMode (default broadcast), channel (text), selected overlay/widget, priority and TTL.",
            "dynamicSource": null
          },
          {
            "key": "channel",
            "type": "select",
            "label": "Payload channel",
            "default": "text",
            "options": [
              {
                "value": "tts",
                "label": "TTS"
              },
              {
                "value": "audio",
                "label": "Audio"
              },
              {
                "value": "text",
                "label": "Text"
              },
              {
                "value": "default",
                "label": "Default"
              },
              {
                "value": "alerts",
                "label": "Alerts"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "text",
              "timer": "text",
              "command": "text",
              "pad": "text"
            },
            "runtimeFallbackNote": "Resolve text; blank does nothing. Publish to receivers using targetMode (default broadcast), channel (text), selected overlay/widget, priority and TTL.",
            "dynamicSource": null
          },
          {
            "key": "targetMode",
            "type": "select",
            "label": "Send to",
            "default": "broadcast",
            "options": [
              {
                "value": "broadcast",
                "label": "All listening overlay widgets"
              },
              {
                "value": "overlay",
                "label": "Specific overlay"
              },
              {
                "value": "widget",
                "label": "Specific widget"
              },
              {
                "value": "channel",
                "label": "Matching channel only"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "broadcast",
              "timer": "broadcast",
              "command": "broadcast",
              "pad": "broadcast"
            },
            "runtimeFallbackNote": "Resolve text; blank does nothing. Publish to receivers using targetMode (default broadcast), channel (text), selected overlay/widget, priority and TTL.",
            "dynamicSource": null
          },
          {
            "key": "overlaySlug",
            "type": "theme_select",
            "label": "Overlay",
            "source": "overlay_builder.overlays",
            "labelKey": "overlayName",
            "visibleWhen": {
              "targetMode": "overlay"
            },
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Resolve text; blank does nothing. Publish to receivers using targetMode (default broadcast), channel (text), selected overlay/widget, priority and TTL.",
            "dynamicSource": "overlay_builder.overlays"
          },
          {
            "key": "widgetId",
            "type": "text",
            "label": "Widget ID",
            "placeholder": "overlay widget id",
            "visibleWhen": {
              "targetMode": "widget"
            },
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Resolve text; blank does nothing. Publish to receivers using targetMode (default broadcast), channel (text), selected overlay/widget, priority and TTL.",
            "dynamicSource": null
          },
          {
            "key": "priority",
            "type": "number",
            "label": "Priority",
            "default": 0,
            "min": 0,
            "max": 100,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": 0,
              "timer": 0,
              "command": 0,
              "pad": 0
            },
            "runtimeFallbackNote": "Resolve text; blank does nothing. Publish to receivers using targetMode (default broadcast), channel (text), selected overlay/widget, priority and TTL.",
            "dynamicSource": null
          },
          {
            "key": "ttlMs",
            "type": "number",
            "label": "Expires after (ms)",
            "default": 300000,
            "min": 1000,
            "max": 3600000,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": 300000,
              "timer": 300000,
              "command": 300000,
              "pad": 300000
            },
            "runtimeFallbackNote": "Resolve text; blank does nothing. Publish to receivers using targetMode (default broadcast), channel (text), selected overlay/widget, priority and TTL.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "send_overlay_text",
            "message": "",
            "platform": "event"
          },
          "timer": {
            "type": "send_overlay_text",
            "message": "",
            "platform": "all"
          },
          "command": {
            "type": "send_overlay_text",
            "message": "",
            "platform": "event"
          },
          "pad": {
            "type": "send_overlay_text",
            "message": "",
            "platform": "all"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Send to Overlay, select Send Text Payload, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.create_twitch_clip",
      "kind": "action",
      "runtimeKey": "create_twitch_clip",
      "label": "Create Twitch Clip",
      "category": "Stream Platform Commands",
      "summary": "Create a clip from the connected Twitch broadcaster stream. Twitch supports requested lengths from 5 to 60 seconds.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Live connected Twitch broadcaster with clip creation access.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.create_twitch_clip"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "duration": 30,
            "postToChat": false
          }
        }
      ],
      "details": {
        "behavior": "Request a Twitch clip from the broadcaster stream; allowed length 5–60 seconds, editor default 60. postToChat defaults true unless false or string false.",
        "fields": [
          {
            "key": "duration",
            "type": "number",
            "label": "Clip length (seconds)",
            "default": 60,
            "min": 5,
            "max": 60,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": 60,
              "timer": 60,
              "command": 60,
              "pad": 60
            },
            "runtimeFallbackNote": "Request a Twitch clip from the broadcaster stream; allowed length 5–60 seconds, editor default 60. postToChat defaults true unless false or string false.",
            "dynamicSource": null
          },
          {
            "key": "postToChat",
            "type": "checkbox",
            "label": "Post clip link to Twitch chat",
            "default": true,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": true,
              "timer": true,
              "command": true,
              "pad": true
            },
            "runtimeFallbackNote": "Request a Twitch clip from the broadcaster stream; allowed length 5–60 seconds, editor default 60. postToChat defaults true unless false or string false.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "create_twitch_clip",
            "duration": 60,
            "postToChat": true
          },
          "timer": {
            "type": "create_twitch_clip",
            "duration": 60,
            "postToChat": true
          },
          "command": {
            "type": "create_twitch_clip",
            "duration": 60,
            "postToChat": true
          },
          "pad": {
            "type": "create_twitch_clip",
            "duration": 60,
            "postToChat": true
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Stream Platform Commands, select Create Twitch Clip, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.queue_clip",
      "kind": "action",
      "runtimeKey": "queue_clip",
      "label": "Queue Clip",
      "category": "Queue Video",
      "summary": "Queue a supported short-form clip URL for the Clip Overlay. Supports variables, so channel point messages can be passed in.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Supported short-video URL, required clip tools and Clip Overlay.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.queue_clip"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "url": "https://www.twitch.tv/example/clip/ExampleClip"
          }
        }
      ],
      "details": {
        "behavior": "Resolve URL or fall back to event input/message; blank fails. Queue a supported short video for the Clip Overlay; media downloading/validation is handled by clip tools.",
        "fields": [
          {
            "key": "url",
            "type": "textarea",
            "label": "Clip URL",
            "placeholder": "{message}",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "{message}",
              "timer": "",
              "command": "{message}",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve URL or fall back to event input/message; blank fails. Queue a supported short video for the Clip Overlay; media downloading/validation is handled by clip tools.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "queue_clip",
            "url": "{message}"
          },
          "timer": {
            "type": "queue_clip",
            "url": ""
          },
          "command": {
            "type": "queue_clip",
            "url": "{message}"
          },
          "pad": {
            "type": "queue_clip",
            "url": ""
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Queue Video, select Queue Clip, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.queue_tiktok_clip",
      "kind": "action",
      "runtimeKey": "queue_tiktok_clip",
      "label": "Queue Clip",
      "category": "Queue Video",
      "summary": "Legacy action name. Queue a supported clip URL for the Clip Overlay.",
      "status": "legacy",
      "contexts": [],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Same requirements as Queue Clip.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.queue_tiktok_clip"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "action.queue_clip"
      ],
      "examples": [],
      "details": {
        "behavior": "Legacy ID delegates to Queue Clip; it is not restricted to TikTok. Hidden from new-action selection.",
        "fields": [
          {
            "key": "url",
            "type": "textarea",
            "label": "Clip URL",
            "placeholder": "{message}",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "{message}",
              "timer": "",
              "command": "{message}",
              "pad": ""
            },
            "runtimeFallbackNote": "Legacy ID delegates to Queue Clip; it is not restricted to TikTok. Hidden from new-action selection.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [],
        "hiddenFromPicker": true,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "queue_tiktok_clip",
            "url": "{message}"
          },
          "timer": {
            "type": "queue_tiktok_clip",
            "url": ""
          },
          "command": {
            "type": "queue_tiktok_clip",
            "url": "{message}"
          },
          "pad": {
            "type": "queue_tiktok_clip",
            "url": ""
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "This action is hidden from new-action selection. Consult its limitations and replacement entry; do not instruct users to select it in Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.skip_current_clip",
      "kind": "action",
      "runtimeKey": "skip_current_clip",
      "label": "Skip Current Clip",
      "category": "Queue Video",
      "summary": "Skip the active Clip Overlay video and continue to the next ready clip.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Clip queue runtime.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.skip_current_clip"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {}
        }
      ],
      "details": {
        "behavior": "Skip the active clip and advance to the next ready queued item.",
        "fields": [],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "skip_current_clip"
          },
          "timer": {
            "type": "skip_current_clip"
          },
          "command": {
            "type": "skip_current_clip"
          },
          "pad": {
            "type": "skip_current_clip"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Queue Video, select Skip Current Clip, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.clear_clip_queue",
      "kind": "action",
      "runtimeKey": "clear_clip_queue",
      "label": "Clear Clip Queue",
      "category": "Queue Video",
      "summary": "Clear pending clip downloads, ready clips, and the active Clip Overlay playback.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Clip queue runtime.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.clear_clip_queue"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {}
        }
      ],
      "details": {
        "behavior": "Clear pending downloads, ready clips and active playback.",
        "fields": [],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "clear_clip_queue"
          },
          "timer": {
            "type": "clear_clip_queue"
          },
          "command": {
            "type": "clear_clip_queue"
          },
          "pad": {
            "type": "clear_clip_queue"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Queue Video, select Clear Clip Queue, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.set_clip_command_enabled",
      "kind": "action",
      "runtimeKey": "set_clip_command_enabled",
      "label": "Set Clip Command Enabled",
      "category": "Queue Video",
      "summary": "Enable or disable the !playclip chat command.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Clip command configuration.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.set_clip_command_enabled"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "enabled": "true"
          }
        }
      ],
      "details": {
        "behavior": "Set !playclip enabled state; missing enabled defaults true. String false disables.",
        "fields": [
          {
            "key": "enabled",
            "type": "select",
            "label": "State",
            "default": "true",
            "options": [
              {
                "value": "true",
                "label": "Enabled"
              },
              {
                "value": "false",
                "label": "Disabled"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "true",
              "timer": "true",
              "command": "true",
              "pad": "true"
            },
            "runtimeFallbackNote": "Set !playclip enabled state; missing enabled defaults true. String false disables.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "set_clip_command_enabled",
            "enabled": "true"
          },
          "timer": {
            "type": "set_clip_command_enabled",
            "enabled": "true"
          },
          "command": {
            "type": "set_clip_command_enabled",
            "enabled": "true"
          },
          "pad": {
            "type": "set_clip_command_enabled",
            "enabled": "true"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Queue Video, select Set Clip Command Enabled, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.toggle_clip_command_enabled",
      "kind": "action",
      "runtimeKey": "toggle_clip_command_enabled",
      "label": "Toggle Clip Command Enabled",
      "category": "Queue Video",
      "summary": "Toggle the !playclip chat command on or off.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Clip command configuration.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.toggle_clip_command_enabled"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {}
        }
      ],
      "details": {
        "behavior": "Invert !playclip enabled state.",
        "fields": [],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "toggle_clip_command_enabled"
          },
          "timer": {
            "type": "toggle_clip_command_enabled"
          },
          "command": {
            "type": "toggle_clip_command_enabled"
          },
          "pad": {
            "type": "toggle_clip_command_enabled"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Queue Video, select Toggle Clip Command Enabled, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.clear_tiktok_queue",
      "kind": "action",
      "runtimeKey": "clear_tiktok_queue",
      "label": "Clear Clip Queue",
      "category": "Queue Video",
      "summary": "Legacy action name. Clear pending clip downloads, ready clips, and active Clip Overlay playback.",
      "status": "legacy",
      "contexts": [],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Clip queue runtime.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.clear_tiktok_queue"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "action.clear_clip_queue"
      ],
      "examples": [],
      "details": {
        "behavior": "Legacy ID delegates to Clear Clip Queue. Hidden from new-action selection.",
        "fields": [],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [],
        "hiddenFromPicker": true,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "clear_tiktok_queue"
          },
          "timer": {
            "type": "clear_tiktok_queue"
          },
          "command": {
            "type": "clear_tiktok_queue"
          },
          "pad": {
            "type": "clear_tiktok_queue"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "This action is hidden from new-action selection. Consult its limitations and replacement entry; do not instruct users to select it in Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.obs_control",
      "kind": "action",
      "runtimeKey": "obs_control",
      "label": "OBS Studio Control",
      "category": "OBS Studio Control",
      "summary": "Run an OBS Studio WebSocket action. Uses the OBS settings from Settings > Connect.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "OBS Studio WebSocket connection configured in Settings > Connect.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.obs_control"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "operation": "get_current_scene"
          }
        }
      ],
      "details": {
        "behavior": "Execute only in the OBS Studio lane. Operation defaults get_status. Variable substitution covers scene/source names, URL and raw request fields. Return values are not automatically exported as template variables.",
        "fields": [
          {
            "key": "operation",
            "type": "select",
            "label": "OBS action",
            "options": [
              {
                "value": "get_status",
                "label": "Connection - Get status"
              },
              {
                "value": "refresh_browser_sources",
                "label": "Connection - Refresh SheevChat browser sources"
              },
              {
                "value": "get_current_scene",
                "label": "Scenes - Get current scene"
              },
              {
                "value": "set_current_scene",
                "label": "Scenes - Set scene"
              },
              {
                "value": "previous_scene",
                "label": "Scenes - Return to previous scene"
              },
              {
                "value": "source_visibility",
                "label": "Sources - Toggle / set source visibility"
              },
              {
                "value": "source_mute",
                "label": "Audio - Toggle / set source mute"
              },
              {
                "value": "stream_toggle",
                "label": "Stream / Record - Toggle streaming"
              },
              {
                "value": "stream_start",
                "label": "Stream / Record - Start streaming"
              },
              {
                "value": "stream_stop",
                "label": "Stream / Record - Stop streaming"
              },
              {
                "value": "record_toggle",
                "label": "Stream / Record - Toggle recording"
              },
              {
                "value": "record_start",
                "label": "Stream / Record - Start recording"
              },
              {
                "value": "record_stop",
                "label": "Stream / Record - Stop recording"
              },
              {
                "value": "replay_toggle",
                "label": "Stream / Record - Toggle replay buffer"
              },
              {
                "value": "replay_start",
                "label": "Stream / Record - Start replay buffer"
              },
              {
                "value": "replay_stop",
                "label": "Stream / Record - Stop replay buffer"
              },
              {
                "value": "replay_save",
                "label": "Stream / Record - Save replay"
              },
              {
                "value": "browser_url",
                "label": "Advanced - Set browser source URL"
              },
              {
                "value": "raw_request",
                "label": "Advanced - Raw OBS request"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "get_status",
              "timer": "get_status",
              "command": "get_status",
              "pad": "get_status"
            },
            "runtimeFallbackNote": "Execute only in the OBS Studio lane. Operation defaults get_status. Variable substitution covers scene/source names, URL and raw request fields. Return values are not automatically exported as template variables.",
            "dynamicSource": null
          },
          {
            "key": "sceneName",
            "type": "text",
            "label": "Scene name",
            "placeholder": "Select scene",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Execute only in the OBS Studio lane. Operation defaults get_status. Variable substitution covers scene/source names, URL and raw request fields. Return values are not automatically exported as template variables.",
            "dynamicSource": null
          },
          {
            "key": "sourceName",
            "type": "text",
            "label": "Source name",
            "placeholder": "Select source",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Execute only in the OBS Studio lane. Operation defaults get_status. Variable substitution covers scene/source names, URL and raw request fields. Return values are not automatically exported as template variables.",
            "dynamicSource": null
          },
          {
            "key": "enabled",
            "type": "select",
            "label": "State",
            "options": [
              {
                "value": "true",
                "label": "On / visible / muted"
              },
              {
                "value": "false",
                "label": "Off / hidden / unmuted"
              },
              {
                "value": "toggle",
                "label": "Toggle"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Execute only in the OBS Studio lane. Operation defaults get_status. Variable substitution covers scene/source names, URL and raw request fields. Return values are not automatically exported as template variables.",
            "dynamicSource": null
          },
          {
            "key": "url",
            "type": "text",
            "label": "Browser URL",
            "placeholder": "http://localhost:3000/overlay",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Execute only in the OBS Studio lane. Operation defaults get_status. Variable substitution covers scene/source names, URL and raw request fields. Return values are not automatically exported as template variables.",
            "dynamicSource": null
          },
          {
            "key": "requestType",
            "type": "text",
            "label": "Raw request type",
            "placeholder": "GetVersion",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Execute only in the OBS Studio lane. Operation defaults get_status. Variable substitution covers scene/source names, URL and raw request fields. Return values are not automatically exported as template variables.",
            "dynamicSource": null
          },
          {
            "key": "requestData",
            "type": "textarea",
            "label": "Raw request data JSON",
            "placeholder": "{\"sceneName\":\"Starting Soon\"}",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Execute only in the OBS Studio lane. Operation defaults get_status. Variable substitution covers scene/source names, URL and raw request fields. Return values are not automatically exported as template variables.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "obs_control",
            "operation": "get_status"
          },
          "timer": {
            "type": "obs_control",
            "operation": "get_status"
          },
          "command": {
            "type": "obs_control",
            "operation": "get_status"
          },
          "pad": {
            "type": "obs_control",
            "operation": "get_status"
          }
        },
        "variants": [
          {
            "value": "get_status",
            "label": "Connection - Get status",
            "fields": [],
            "behavior": "Read connection/output status. Does not create a template variable."
          },
          {
            "value": "refresh_browser_sources",
            "label": "Connection - Refresh SheevChat browser sources",
            "fields": [],
            "behavior": "OBS only: refresh SheevChat browser sources using the OBS refresh path."
          },
          {
            "value": "get_current_scene",
            "label": "Scenes - Get current scene",
            "fields": [],
            "behavior": "Read current program scene. Does not create a template variable."
          },
          {
            "value": "set_current_scene",
            "label": "Scenes - Set scene",
            "fields": [
              "sceneName"
            ],
            "behavior": "Select a current scene and remember the previous scene for return."
          },
          {
            "value": "previous_scene",
            "label": "Scenes - Return to previous scene",
            "fields": [],
            "behavior": "Return to the remembered previous scene; fail if none is available."
          },
          {
            "value": "source_visibility",
            "label": "Sources - Toggle / set source visibility",
            "fields": [
              "sceneName",
              "sourceName",
              "enabled"
            ],
            "behavior": "Resolve an exact scene item, including grouped items when reported. A saved sceneItemId/sourceSceneName disambiguates selection."
          },
          {
            "value": "source_mute",
            "label": "Audio - Toggle / set source mute",
            "fields": [
              "sourceName",
              "enabled"
            ],
            "behavior": "Mute/unmute the selected audio source; missing state toggles."
          },
          {
            "value": "stream_toggle",
            "label": "Stream / Record - Toggle streaming",
            "fields": [],
            "behavior": "Control the named output in this provider only; start/stop/toggle/save have their literal meanings. Replay save requires an active replay buffer."
          },
          {
            "value": "stream_start",
            "label": "Stream / Record - Start streaming",
            "fields": [],
            "behavior": "Control the named output in this provider only; start/stop/toggle/save have their literal meanings. Replay save requires an active replay buffer."
          },
          {
            "value": "stream_stop",
            "label": "Stream / Record - Stop streaming",
            "fields": [],
            "behavior": "Control the named output in this provider only; start/stop/toggle/save have their literal meanings. Replay save requires an active replay buffer."
          },
          {
            "value": "record_toggle",
            "label": "Stream / Record - Toggle recording",
            "fields": [],
            "behavior": "Control the named output in this provider only; start/stop/toggle/save have their literal meanings. Replay save requires an active replay buffer."
          },
          {
            "value": "record_start",
            "label": "Stream / Record - Start recording",
            "fields": [],
            "behavior": "Control the named output in this provider only; start/stop/toggle/save have their literal meanings. Replay save requires an active replay buffer."
          },
          {
            "value": "record_stop",
            "label": "Stream / Record - Stop recording",
            "fields": [],
            "behavior": "Control the named output in this provider only; start/stop/toggle/save have their literal meanings. Replay save requires an active replay buffer."
          },
          {
            "value": "replay_toggle",
            "label": "Stream / Record - Toggle replay buffer",
            "fields": [],
            "behavior": "Control the named output in this provider only; start/stop/toggle/save have their literal meanings. Replay save requires an active replay buffer."
          },
          {
            "value": "replay_start",
            "label": "Stream / Record - Start replay buffer",
            "fields": [],
            "behavior": "Control the named output in this provider only; start/stop/toggle/save have their literal meanings. Replay save requires an active replay buffer."
          },
          {
            "value": "replay_stop",
            "label": "Stream / Record - Stop replay buffer",
            "fields": [],
            "behavior": "Control the named output in this provider only; start/stop/toggle/save have their literal meanings. Replay save requires an active replay buffer."
          },
          {
            "value": "replay_save",
            "label": "Stream / Record - Save replay",
            "fields": [],
            "behavior": "Control the named output in this provider only; start/stop/toggle/save have their literal meanings. Replay save requires an active replay buffer."
          },
          {
            "value": "browser_url",
            "label": "Advanced - Set browser source URL",
            "fields": [
              "sourceName",
              "url"
            ],
            "behavior": "Require source and nonempty URL; update browser source URL."
          },
          {
            "value": "raw_request",
            "label": "Advanced - Raw OBS request",
            "fields": [
              "requestType",
              "requestData"
            ],
            "behavior": "Require request type; blank JSON is {}; invalid JSON fails."
          }
        ],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category OBS Studio Control, select OBS Studio Control, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.streamlabs_control",
      "kind": "action",
      "runtimeKey": "streamlabs_control",
      "label": "Streamlabs Desktop Control",
      "category": "Streamlabs Desktop Control",
      "summary": "Run a Streamlabs Desktop local API action. Uses the Streamlabs Desktop settings from Settings > Connect.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Streamlabs Desktop local API connection configured in Settings > Connect.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.streamlabs_control"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "operation": "get_current_scene"
          }
        }
      ],
      "details": {
        "behavior": "Execute only in the Streamlabs Desktop lane. Operation defaults get_status. Linked source visibility updates all instances; item visibility updates the selected scene item. Return values are not automatically exported as template variables.",
        "fields": [
          {
            "key": "operation",
            "type": "select",
            "label": "Streamlabs action",
            "options": [
              {
                "value": "get_status",
                "label": "Connection - Get status"
              },
              {
                "value": "refresh_catalog",
                "label": "Connection - Refresh scene/source catalog"
              },
              {
                "value": "get_current_scene",
                "label": "Scenes - Get current scene"
              },
              {
                "value": "set_current_scene",
                "label": "Scenes - Set scene"
              },
              {
                "value": "previous_scene",
                "label": "Scenes - Return to previous scene"
              },
              {
                "value": "source_visibility",
                "label": "Sources - Toggle / set source visibility"
              },
              {
                "value": "source_mute",
                "label": "Audio - Toggle / set source mute"
              },
              {
                "value": "stream_toggle",
                "label": "Stream / Record - Toggle streaming"
              },
              {
                "value": "stream_start",
                "label": "Stream / Record - Start streaming"
              },
              {
                "value": "stream_stop",
                "label": "Stream / Record - Stop streaming"
              },
              {
                "value": "record_toggle",
                "label": "Stream / Record - Toggle recording"
              },
              {
                "value": "record_start",
                "label": "Stream / Record - Start recording"
              },
              {
                "value": "record_stop",
                "label": "Stream / Record - Stop recording"
              },
              {
                "value": "replay_toggle",
                "label": "Stream / Record - Toggle replay buffer"
              },
              {
                "value": "replay_start",
                "label": "Stream / Record - Start replay buffer"
              },
              {
                "value": "replay_stop",
                "label": "Stream / Record - Stop replay buffer"
              },
              {
                "value": "replay_save",
                "label": "Stream / Record - Save replay"
              },
              {
                "value": "browser_url",
                "label": "Advanced - Set browser source URL"
              },
              {
                "value": "raw_request",
                "label": "Advanced - Raw Streamlabs request"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "get_status",
              "timer": "get_status",
              "command": "get_status",
              "pad": "get_status"
            },
            "runtimeFallbackNote": "Execute only in the Streamlabs Desktop lane. Operation defaults get_status. Linked source visibility updates all instances; item visibility updates the selected scene item. Return values are not automatically exported as template variables.",
            "dynamicSource": null
          },
          {
            "key": "sceneName",
            "type": "text",
            "label": "Scene name",
            "placeholder": "Select scene",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Execute only in the Streamlabs Desktop lane. Operation defaults get_status. Linked source visibility updates all instances; item visibility updates the selected scene item. Return values are not automatically exported as template variables.",
            "dynamicSource": null
          },
          {
            "key": "sourceName",
            "type": "text",
            "label": "Source name",
            "placeholder": "Select source",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Execute only in the Streamlabs Desktop lane. Operation defaults get_status. Linked source visibility updates all instances; item visibility updates the selected scene item. Return values are not automatically exported as template variables.",
            "dynamicSource": null
          },
          {
            "key": "visibilityTarget",
            "type": "select",
            "label": "Visibility target",
            "options": [
              {
                "value": "linked",
                "label": "Linked source — all instances"
              },
              {
                "value": "item",
                "label": "Selected scene item only"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Execute only in the Streamlabs Desktop lane. Operation defaults get_status. Linked source visibility updates all instances; item visibility updates the selected scene item. Return values are not automatically exported as template variables.",
            "dynamicSource": null
          },
          {
            "key": "enabled",
            "type": "select",
            "label": "State",
            "options": [
              {
                "value": "true",
                "label": "On / visible / muted"
              },
              {
                "value": "false",
                "label": "Off / hidden / unmuted"
              },
              {
                "value": "toggle",
                "label": "Toggle"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Execute only in the Streamlabs Desktop lane. Operation defaults get_status. Linked source visibility updates all instances; item visibility updates the selected scene item. Return values are not automatically exported as template variables.",
            "dynamicSource": null
          },
          {
            "key": "url",
            "type": "text",
            "label": "Browser URL",
            "placeholder": "http://localhost:3000/overlay",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Execute only in the Streamlabs Desktop lane. Operation defaults get_status. Linked source visibility updates all instances; item visibility updates the selected scene item. Return values are not automatically exported as template variables.",
            "dynamicSource": null
          },
          {
            "key": "resource",
            "type": "text",
            "label": "Raw resource",
            "placeholder": "ScenesService",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Execute only in the Streamlabs Desktop lane. Operation defaults get_status. Linked source visibility updates all instances; item visibility updates the selected scene item. Return values are not automatically exported as template variables.",
            "dynamicSource": null
          },
          {
            "key": "method",
            "type": "text",
            "label": "Raw method",
            "placeholder": "getScenes",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Execute only in the Streamlabs Desktop lane. Operation defaults get_status. Linked source visibility updates all instances; item visibility updates the selected scene item. Return values are not automatically exported as template variables.",
            "dynamicSource": null
          },
          {
            "key": "argsJson",
            "type": "textarea",
            "label": "Raw args JSON",
            "placeholder": "[]",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Execute only in the Streamlabs Desktop lane. Operation defaults get_status. Linked source visibility updates all instances; item visibility updates the selected scene item. Return values are not automatically exported as template variables.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "streamlabs_control",
            "operation": "get_status"
          },
          "timer": {
            "type": "streamlabs_control",
            "operation": "get_status"
          },
          "command": {
            "type": "streamlabs_control",
            "operation": "get_status"
          },
          "pad": {
            "type": "streamlabs_control",
            "operation": "get_status"
          }
        },
        "variants": [
          {
            "value": "get_status",
            "label": "Connection - Get status",
            "fields": [],
            "behavior": "Read connection/output status. Does not create a template variable."
          },
          {
            "value": "refresh_catalog",
            "label": "Connection - Refresh scene/source catalog",
            "fields": [],
            "behavior": "Streamlabs only: refresh scene/source catalog; not the OBS browser refresh action."
          },
          {
            "value": "get_current_scene",
            "label": "Scenes - Get current scene",
            "fields": [],
            "behavior": "Read current program scene. Does not create a template variable."
          },
          {
            "value": "set_current_scene",
            "label": "Scenes - Set scene",
            "fields": [
              "sceneName"
            ],
            "behavior": "Select a current scene and remember the previous scene for return."
          },
          {
            "value": "previous_scene",
            "label": "Scenes - Return to previous scene",
            "fields": [],
            "behavior": "Return to the remembered previous scene; fail if none is available."
          },
          {
            "value": "source_visibility",
            "label": "Sources - Toggle / set source visibility",
            "fields": [
              "sceneName",
              "sourceName",
              "visibilityTarget",
              "enabled"
            ],
            "behavior": "linked (default) changes all instances of the source; item changes only selected itemResourceId. Select targets from the Streamlabs catalog."
          },
          {
            "value": "source_mute",
            "label": "Audio - Toggle / set source mute",
            "fields": [
              "sourceName",
              "enabled"
            ],
            "behavior": "Mute/unmute the selected audio source; missing state toggles."
          },
          {
            "value": "stream_toggle",
            "label": "Stream / Record - Toggle streaming",
            "fields": [],
            "behavior": "Control the named output in this provider only; start/stop/toggle/save have their literal meanings. Replay save requires an active replay buffer."
          },
          {
            "value": "stream_start",
            "label": "Stream / Record - Start streaming",
            "fields": [],
            "behavior": "Control the named output in this provider only; start/stop/toggle/save have their literal meanings. Replay save requires an active replay buffer."
          },
          {
            "value": "stream_stop",
            "label": "Stream / Record - Stop streaming",
            "fields": [],
            "behavior": "Control the named output in this provider only; start/stop/toggle/save have their literal meanings. Replay save requires an active replay buffer."
          },
          {
            "value": "record_toggle",
            "label": "Stream / Record - Toggle recording",
            "fields": [],
            "behavior": "Control the named output in this provider only; start/stop/toggle/save have their literal meanings. Replay save requires an active replay buffer."
          },
          {
            "value": "record_start",
            "label": "Stream / Record - Start recording",
            "fields": [],
            "behavior": "Control the named output in this provider only; start/stop/toggle/save have their literal meanings. Replay save requires an active replay buffer."
          },
          {
            "value": "record_stop",
            "label": "Stream / Record - Stop recording",
            "fields": [],
            "behavior": "Control the named output in this provider only; start/stop/toggle/save have their literal meanings. Replay save requires an active replay buffer."
          },
          {
            "value": "replay_toggle",
            "label": "Stream / Record - Toggle replay buffer",
            "fields": [],
            "behavior": "Control the named output in this provider only; start/stop/toggle/save have their literal meanings. Replay save requires an active replay buffer."
          },
          {
            "value": "replay_start",
            "label": "Stream / Record - Start replay buffer",
            "fields": [],
            "behavior": "Control the named output in this provider only; start/stop/toggle/save have their literal meanings. Replay save requires an active replay buffer."
          },
          {
            "value": "replay_stop",
            "label": "Stream / Record - Stop replay buffer",
            "fields": [],
            "behavior": "Control the named output in this provider only; start/stop/toggle/save have their literal meanings. Replay save requires an active replay buffer."
          },
          {
            "value": "replay_save",
            "label": "Stream / Record - Save replay",
            "fields": [],
            "behavior": "Control the named output in this provider only; start/stop/toggle/save have their literal meanings. Replay save requires an active replay buffer."
          },
          {
            "value": "browser_url",
            "label": "Advanced - Set browser source URL",
            "fields": [
              "sourceName",
              "url"
            ],
            "behavior": "Require source and nonempty URL; update browser source URL."
          },
          {
            "value": "raw_request",
            "label": "Advanced - Raw Streamlabs request",
            "fields": [
              "resource",
              "method",
              "argsJson"
            ],
            "behavior": "Require resource/method; blank args JSON is []; invalid JSON fails."
          }
        ],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Streamlabs Desktop Control, select Streamlabs Desktop Control, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.roll_credits",
      "kind": "action",
      "runtimeKey": "roll_credits",
      "label": "Roll Credits",
      "category": "Credits",
      "summary": "Start the Credits overlay scroll for the current stream credits session.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Running Credits overlay.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.roll_credits"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "mode": "roll"
          }
        }
      ],
      "details": {
        "behavior": "Mode reset returns the overlay to waiting; every other/missing mode rolls the current session.",
        "fields": [
          {
            "key": "mode",
            "type": "select",
            "label": "Credits mode",
            "options": [
              {
                "value": "roll",
                "label": "Roll credits now"
              },
              {
                "value": "reset",
                "label": "Reset overlay to waiting"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "roll",
              "timer": "roll",
              "command": "roll",
              "pad": "roll"
            },
            "runtimeFallbackNote": "Mode reset returns the overlay to waiting; every other/missing mode rolls the current session.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "roll_credits",
            "mode": "roll"
          },
          "timer": {
            "type": "roll_credits",
            "mode": "roll"
          },
          "command": {
            "type": "roll_credits",
            "mode": "roll"
          },
          "pad": {
            "type": "roll_credits",
            "mode": "roll"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Credits, select Roll Credits, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.clear_credits_session",
      "kind": "action",
      "runtimeKey": "clear_credits_session",
      "label": "Clear Credits Session",
      "category": "Credits",
      "summary": "Clear the current stream credits session and save a restore point for Undo Clear.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Credits session storage.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.clear_credits_session"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {}
        }
      ],
      "details": {
        "behavior": "Clear the current stream credits session and retain a restore point.",
        "fields": [],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "clear_credits_session",
            "message": "",
            "platform": "event"
          },
          "timer": {
            "type": "clear_credits_session",
            "message": "",
            "platform": "all"
          },
          "command": {
            "type": "clear_credits_session",
            "message": "",
            "platform": "event"
          },
          "pad": {
            "type": "clear_credits_session",
            "message": "",
            "platform": "all"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Credits, select Clear Credits Session, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.undo_clear_credits_session",
      "kind": "action",
      "runtimeKey": "undo_clear_credits_session",
      "label": "Undo Clear Credits Session",
      "category": "Credits",
      "summary": "Restore the most recently cleared current stream credits session.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "An available credits restore point.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.undo_clear_credits_session"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {}
        }
      ],
      "details": {
        "behavior": "Restore the latest credits-session clear restore point.",
        "fields": [],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "undo_clear_credits_session",
            "message": "",
            "platform": "event"
          },
          "timer": {
            "type": "undo_clear_credits_session",
            "message": "",
            "platform": "all"
          },
          "command": {
            "type": "undo_clear_credits_session",
            "message": "",
            "platform": "event"
          },
          "pad": {
            "type": "undo_clear_credits_session",
            "message": "",
            "platform": "all"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Credits, select Undo Clear Credits Session, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.send_keystrokes",
      "kind": "action",
      "runtimeKey": "send_keystrokes",
      "label": "Send keystrokes",
      "category": "Utilities",
      "summary": "Send a Windows keyboard macro to the active app. Use ^ for Ctrl, + for Shift, % for Alt. Supports {ENTER}, {TAB}, and {WAIT 500} on separate lines.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Windows and the intended application focused.",
        "accountFeature": null,
        "operatingSystems": [
          "windows"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.send_keystrokes"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "keys": "{F13}"
          }
        }
      ],
      "details": {
        "behavior": "Resolve the keyboard macro and send it to the active Windows application. ^ is Ctrl, + Shift, % Alt. Special keys and separate {WAIT 500} lines use SendKeys syntax, not template variable syntax.",
        "fields": [
          {
            "key": "keys",
            "type": "textarea",
            "label": "Keystroke macro",
            "placeholder": "^+s\n{WAIT 250}\n%{TAB}",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve the keyboard macro and send it to the active Windows application. ^ is Ctrl, + Shift, % Alt. Special keys and separate {WAIT 500} lines use SendKeys syntax, not template variable syntax.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "send_keystrokes",
            "keys": ""
          },
          "timer": {
            "type": "send_keystrokes",
            "keys": ""
          },
          "command": {
            "type": "send_keystrokes",
            "keys": ""
          },
          "pad": {
            "type": "send_keystrokes",
            "keys": ""
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Utilities, select Send keystrokes, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.launch_application",
      "kind": "action",
      "runtimeKey": "launch_application",
      "label": "Launch application",
      "category": "Launch Application/Game",
      "summary": "Open a local app or file on the SheevChat PC. Optional arguments are split like a normal command line.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Locally installed application and a valid selectable executable/path.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.launch_application"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "path": "C:\\Example\\Example.exe",
            "args": "",
            "workingDir": ""
          }
        }
      ],
      "details": {
        "behavior": "Resolve path, args and workingDir; blank path does nothing. Uses the existing application-launch guard. Existing generic app processes are not started twice.",
        "fields": [
          {
            "key": "path",
            "type": "text",
            "label": "Application or file path",
            "placeholder": "C:\\Program Files\\App\\App.exe",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve path, args and workingDir; blank path does nothing. Uses the existing application-launch guard. Existing generic app processes are not started twice.",
            "dynamicSource": null
          },
          {
            "key": "args",
            "type": "text",
            "label": "Arguments",
            "placeholder": "",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve path, args and workingDir; blank path does nothing. Uses the existing application-launch guard. Existing generic app processes are not started twice.",
            "dynamicSource": null
          },
          {
            "key": "workingDir",
            "type": "text",
            "label": "Working folder",
            "placeholder": "",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve path, args and workingDir; blank path does nothing. Uses the existing application-launch guard. Existing generic app processes are not started twice.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "launch_application",
            "path": "",
            "args": "",
            "workingDir": ""
          },
          "timer": {
            "type": "launch_application",
            "path": "",
            "args": "",
            "workingDir": ""
          },
          "command": {
            "type": "launch_application",
            "path": "",
            "args": "",
            "workingDir": ""
          },
          "pad": {
            "type": "launch_application",
            "path": "",
            "args": "",
            "workingDir": ""
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Launch Application/Game, select Launch application, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.launch_steam_game",
      "kind": "action",
      "runtimeKey": "launch_steam_game",
      "label": "Launch Steam Game",
      "category": "Launch Application/Game",
      "summary": "Launch an installed Steam game on the SheevChat PC using its Steam AppID.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Installed Steam game selected from local discovery.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.launch_steam_game"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "appId": "fixture-steam-game"
          }
        }
      ],
      "details": {
        "behavior": "Resolve appId, require selection and invoke Steam launch.",
        "fields": [
          {
            "key": "appId",
            "type": "steam_game_select",
            "label": "Game",
            "labelKey": "gameName",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve appId, require selection and invoke Steam launch.",
            "dynamicSource": "Local Game picker; select an existing resource, never invent its ID."
          }
        ],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "launch_steam_game",
            "appId": "",
            "gameName": ""
          },
          "timer": {
            "type": "launch_steam_game",
            "appId": "",
            "gameName": ""
          },
          "command": {
            "type": "launch_steam_game",
            "appId": "",
            "gameName": ""
          },
          "pad": {
            "type": "launch_steam_game",
            "appId": "",
            "gameName": ""
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Launch Application/Game, select Launch Steam Game, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.launch_epic_game",
      "kind": "action",
      "runtimeKey": "launch_epic_game",
      "label": "Launch Epic Game",
      "category": "Launch Application/Game",
      "summary": "Launch an installed Epic Games title using Epic Games Launcher. Direct title launch is experimental until verified per machine.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Installed Epic game and launcher.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.launch_epic_game"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "gameId": "fixture-epic-game"
          }
        }
      ],
      "details": {
        "behavior": "Resolve gameId, require selection and invoke Epic Games Launcher. Direct title launch remains experimental per machine.",
        "fields": [
          {
            "key": "gameId",
            "type": "epic_game_select",
            "label": "Game",
            "labelKey": "gameName",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve gameId, require selection and invoke Epic Games Launcher. Direct title launch remains experimental per machine.",
            "dynamicSource": "Local Game picker; select an existing resource, never invent its ID."
          }
        ],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "launch_epic_game",
            "gameId": "",
            "gameName": ""
          },
          "timer": {
            "type": "launch_epic_game",
            "gameId": "",
            "gameName": ""
          },
          "command": {
            "type": "launch_epic_game",
            "gameId": "",
            "gameName": ""
          },
          "pad": {
            "type": "launch_epic_game",
            "gameId": "",
            "gameName": ""
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Launch Application/Game, select Launch Epic Game, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.launch_ubisoft_game",
      "kind": "action",
      "runtimeKey": "launch_ubisoft_game",
      "label": "Launch Ubisoft Game",
      "category": "Launch Application/Game",
      "summary": "Launch an installed Ubisoft Connect game using a verified local Ubisoft game ID.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Installed Ubisoft game and Ubisoft Connect.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.launch_ubisoft_game"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "gameId": "fixture-ubisoft-game"
          }
        }
      ],
      "details": {
        "behavior": "Resolve gameId, require selection and use the discovered local Ubisoft ID.",
        "fields": [
          {
            "key": "gameId",
            "type": "ubisoft_game_select",
            "label": "Game",
            "labelKey": "gameName",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve gameId, require selection and use the discovered local Ubisoft ID.",
            "dynamicSource": "Local Game picker; select an existing resource, never invent its ID."
          }
        ],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "launch_ubisoft_game",
            "gameId": "",
            "gameName": ""
          },
          "timer": {
            "type": "launch_ubisoft_game",
            "gameId": "",
            "gameName": ""
          },
          "command": {
            "type": "launch_ubisoft_game",
            "gameId": "",
            "gameName": ""
          },
          "pad": {
            "type": "launch_ubisoft_game",
            "gameId": "",
            "gameName": ""
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Launch Application/Game, select Launch Ubisoft Game, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.launch_ea_game",
      "kind": "action",
      "runtimeKey": "launch_ea_game",
      "label": "Launch EA Game",
      "category": "Launch Application/Game",
      "summary": "Launch an installed EA game directly when an executable is available, otherwise open the EA app.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Installed EA game and EA app.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.launch_ea_game"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "gameId": "fixture-ea-game"
          }
        }
      ],
      "details": {
        "behavior": "Resolve gameId; launch the installed executable when available, otherwise open the EA app.",
        "fields": [
          {
            "key": "gameId",
            "type": "ea_game_select",
            "label": "Game",
            "labelKey": "gameName",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve gameId; launch the installed executable when available, otherwise open the EA app.",
            "dynamicSource": "Local Game picker; select an existing resource, never invent its ID."
          }
        ],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "launch_ea_game",
            "gameId": "",
            "gameName": ""
          },
          "timer": {
            "type": "launch_ea_game",
            "gameId": "",
            "gameName": ""
          },
          "command": {
            "type": "launch_ea_game",
            "gameId": "",
            "gameName": ""
          },
          "pad": {
            "type": "launch_ea_game",
            "gameId": "",
            "gameName": ""
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Launch Application/Game, select Launch EA Game, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.launch_battlenet_game",
      "kind": "action",
      "runtimeKey": "launch_battlenet_game",
      "label": "Launch Battle.net Game",
      "category": "Launch Application/Game",
      "summary": "Launch an installed Battle.net game through the Battle.net desktop app.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Installed Battle.net game and launcher.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.launch_battlenet_game"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "gameId": "fixture-battlenet-game"
          }
        }
      ],
      "details": {
        "behavior": "Resolve gameId; launch through the Battle.net desktop app.",
        "fields": [
          {
            "key": "gameId",
            "type": "battlenet_game_select",
            "label": "Game",
            "labelKey": "gameName",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Resolve gameId; launch through the Battle.net desktop app.",
            "dynamicSource": "Local Game picker; select an existing resource, never invent its ID."
          }
        ],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "launch_battlenet_game",
            "gameId": "",
            "gameName": ""
          },
          "timer": {
            "type": "launch_battlenet_game",
            "gameId": "",
            "gameName": ""
          },
          "command": {
            "type": "launch_battlenet_game",
            "gameId": "",
            "gameName": ""
          },
          "pad": {
            "type": "launch_battlenet_game",
            "gameId": "",
            "gameName": ""
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Launch Application/Game, select Launch Battle.net Game, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.run_command",
      "kind": "action",
      "runtimeKey": "run_command",
      "label": "Advanced: run command text",
      "category": "Chat Bot Commands",
      "summary": "Advanced fallback for power users. Prefer the friendly bot actions above when possible.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "An existing supported command on the selected platform; no TikTok option is offered.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.run_command"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Arbitrary command text does not have one safe TikTok response contract; use the corresponding friendly action instead.",
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "command": "!quote",
            "platform": "twitch"
          }
        }
      ],
      "details": {
        "behavior": "Resolve command text; blank does nothing. Dispatch a registered command first, then full command routing for custom/Marketplace commands. Uses broadcaster automation authority, bypassing public-command enabled/platform checks where supported. This is not a shell or arbitrary script action.",
        "fields": [
          {
            "key": "command",
            "type": "text",
            "label": "Command text",
            "placeholder": "!quote or !sr {message}",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Resolve command text; blank does nothing. Dispatch a registered command first, then full command routing for custom/Marketplace commands. Uses broadcaster automation authority, bypassing public-command enabled/platform checks where supported. This is not a shell or arbitrary script action.",
            "dynamicSource": null
          },
          {
            "key": "platform",
            "type": "select",
            "label": "Platform",
            "options": [
              {
                "value": "event",
                "label": "Same platform as event"
              },
              {
                "value": "twitch",
                "label": "Twitch"
              },
              {
                "value": "youtube",
                "label": "YouTube"
              },
              {
                "value": "kick",
                "label": "Kick"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "event",
              "timer": "all",
              "command": "event",
              "pad": "all"
            },
            "runtimeFallbackNote": "Resolve command text; blank does nothing. Dispatch a registered command first, then full command routing for custom/Marketplace commands. Uses broadcaster automation authority, bypassing public-command enabled/platform checks where supported. This is not a shell or arbitrary script action.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "run_command",
            "message": "",
            "platform": "event"
          },
          "timer": {
            "type": "run_command",
            "message": "",
            "platform": "all"
          },
          "command": {
            "type": "run_command",
            "message": "",
            "platform": "event"
          },
          "pad": {
            "type": "run_command",
            "message": "",
            "platform": "all"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Chat Bot Commands, select Advanced: run command text, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.trivia",
      "kind": "action",
      "runtimeKey": "trivia",
      "label": "Start trivia",
      "category": "Chat Bot Commands",
      "summary": "Start one shared trivia game across the base target and any additional selected platforms.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Configured trivia runtime/question source.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.trivia"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "platform": "twitch",
            "twitch": false,
            "youtube": false,
            "kick": false,
            "tiktok": false
          }
        }
      ],
      "details": {
        "behavior": "Start one shared trivia game across base target plus explicitly checked extra platforms. Base defaults event; none means extras only; all retains Twitch + YouTube + Kick. Missing runtime dependency does nothing.",
        "fields": [
          {
            "key": "platform",
            "type": "select",
            "label": "Base target",
            "options": [
              {
                "value": "event",
                "label": "Same platform as event / timer"
              },
              {
                "value": "none",
                "label": "Selected platforms only"
              },
              {
                "value": "twitch",
                "label": "Twitch"
              },
              {
                "value": "youtube",
                "label": "YouTube"
              },
              {
                "value": "kick",
                "label": "Kick"
              },
              {
                "value": "tiktok",
                "label": "TikTok"
              },
              {
                "value": "all",
                "label": "Twitch + YouTube + Kick"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "event",
              "timer": "all",
              "command": "event",
              "pad": "all"
            },
            "runtimeFallbackNote": "Start one shared trivia game across base target plus explicitly checked extra platforms. Base defaults event; none means extras only; all retains Twitch + YouTube + Kick. Missing runtime dependency does nothing.",
            "dynamicSource": null
          },
          {
            "key": "twitch",
            "type": "checkbox",
            "label": "Also run on Twitch",
            "default": false,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": false,
              "timer": false,
              "command": false,
              "pad": false
            },
            "runtimeFallbackNote": "Start one shared trivia game across base target plus explicitly checked extra platforms. Base defaults event; none means extras only; all retains Twitch + YouTube + Kick. Missing runtime dependency does nothing.",
            "dynamicSource": null
          },
          {
            "key": "youtube",
            "type": "checkbox",
            "label": "Also run on YouTube",
            "default": false,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": false,
              "timer": false,
              "command": false,
              "pad": false
            },
            "runtimeFallbackNote": "Start one shared trivia game across base target plus explicitly checked extra platforms. Base defaults event; none means extras only; all retains Twitch + YouTube + Kick. Missing runtime dependency does nothing.",
            "dynamicSource": null
          },
          {
            "key": "kick",
            "type": "checkbox",
            "label": "Also run on Kick",
            "default": false,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": false,
              "timer": false,
              "command": false,
              "pad": false
            },
            "runtimeFallbackNote": "Start one shared trivia game across base target plus explicitly checked extra platforms. Base defaults event; none means extras only; all retains Twitch + YouTube + Kick. Missing runtime dependency does nothing.",
            "dynamicSource": null
          },
          {
            "key": "tiktok",
            "type": "checkbox",
            "label": "Also run on TikTok",
            "default": false,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": false,
              "timer": false,
              "command": false,
              "pad": false
            },
            "runtimeFallbackNote": "Start one shared trivia game across base target plus explicitly checked extra platforms. Base defaults event; none means extras only; all retains Twitch + YouTube + Kick. Missing runtime dependency does nothing.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "trivia",
            "message": "",
            "platform": "event"
          },
          "timer": {
            "type": "trivia",
            "message": "",
            "platform": "all"
          },
          "command": {
            "type": "trivia",
            "message": "",
            "platform": "event"
          },
          "pad": {
            "type": "trivia",
            "message": "",
            "platform": "all"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Chat Bot Commands, select Start trivia, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.ai_prompt",
      "kind": "action",
      "runtimeKey": "ai_prompt",
      "label": "AI prompt (coming soon)",
      "category": "Utilities",
      "summary": "Send the event context to an AI and use the response in chat.",
      "status": "unavailable",
      "contexts": [],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Not implemented.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.ai_prompt"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "action.ai_creative_utility"
      ],
      "examples": [],
      "details": {
        "behavior": "Unavailable placeholder: logs that integration is not implemented. Hidden from the action picker. Use a supported entitled A.I. action instead.",
        "fields": [
          {
            "key": "prompt",
            "type": "textarea",
            "label": "Prompt template",
            "placeholder": "A viewer named {user} just raided with {viewers} viewers. Write a short, hype welcome message.",
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Unavailable placeholder: logs that integration is not implemented. Hidden from the action picker. Use a supported entitled A.I. action instead.",
            "dynamicSource": null
          },
          {
            "key": "_stub",
            "type": "info",
            "label": "AI integration coming in a future update.",
            "configurable": false,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Unavailable placeholder: logs that integration is not implemented. Hidden from the action picker. Use a supported entitled A.I. action instead.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation"
        ],
        "pickerContexts": [],
        "hiddenFromPicker": true,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "ai_prompt",
            "message": "",
            "platform": "event"
          },
          "timer": {
            "type": "ai_prompt",
            "message": "",
            "platform": "all"
          },
          "command": {
            "type": "ai_prompt",
            "message": "",
            "platform": "event"
          },
          "pad": {
            "type": "ai_prompt",
            "message": "",
            "platform": "all"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "This action is hidden from new-action selection. Consult its limitations and replacement entry; do not instruct users to select it in Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.fetch_webhook",
      "kind": "action",
      "runtimeKey": "fetch_webhook",
      "label": "Fetch webhook",
      "category": "Utilities",
      "summary": "Send an HTTP request to a URL. Useful for triggering external services, n8n/Zapier webhooks, or home automation. Variable substitution supported in URL and body.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "A reachable endpoint you control; correct authentication/JSON supplied explicitly.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.fetch_webhook"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "url": "https://example.com/webhook",
            "method": "POST",
            "body": "{\"user\":\"{user}\"}",
            "headers": "{}"
          }
        }
      ],
      "details": {
        "behavior": "Resolve URL/body through the provided global variable resolver; the simple event-key fallback is used only when that resolver is absent. Blank URL does nothing; method defaults GET. POST/PUT may send body; headers are literal JSON and malformed headers are ignored. Request failures are logged; response body is not exposed to later actions.",
        "fields": [
          {
            "key": "url",
            "type": "text",
            "label": "URL",
            "placeholder": "https://hooks.zapier.com/hooks/catch/...",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Resolve URL/body through the provided global variable resolver; the simple event-key fallback is used only when that resolver is absent. Blank URL does nothing; method defaults GET. POST/PUT may send body; headers are literal JSON and malformed headers are ignored. Request failures are logged; response body is not exposed to later actions.",
            "dynamicSource": null
          },
          {
            "key": "method",
            "type": "select",
            "label": "Method",
            "options": [
              {
                "value": "GET",
                "label": "GET"
              },
              {
                "value": "POST",
                "label": "POST"
              },
              {
                "value": "PUT",
                "label": "PUT"
              }
            ],
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Resolve URL/body through the provided global variable resolver; the simple event-key fallback is used only when that resolver is absent. Blank URL does nothing; method defaults GET. POST/PUT may send body; headers are literal JSON and malformed headers are ignored. Request failures are logged; response body is not exposed to later actions.",
            "dynamicSource": null
          },
          {
            "key": "body",
            "type": "textarea",
            "label": "Body (POST/PUT only)",
            "placeholder": "{\"user\":\"{user}\",\"event\":\"{message}\"}",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Resolve URL/body through the provided global variable resolver; the simple event-key fallback is used only when that resolver is absent. Blank URL does nothing; method defaults GET. POST/PUT may send body; headers are literal JSON and malformed headers are ignored. Request failures are logged; response body is not exposed to later actions.",
            "dynamicSource": null
          },
          {
            "key": "headers",
            "type": "text",
            "label": "Extra headers (JSON)",
            "placeholder": "{\"Authorization\":\"Bearer token123\"}",
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": null,
              "timer": null,
              "command": null,
              "pad": null
            },
            "runtimeFallbackNote": "Resolve URL/body through the provided global variable resolver; the simple event-key fallback is used only when that resolver is absent. Blank URL does nothing; method defaults GET. POST/PUT may send body; headers are literal JSON and malformed headers are ignored. Request failures are logged; response body is not exposed to later actions.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "fetch_webhook",
            "message": "",
            "platform": "event"
          },
          "timer": {
            "type": "fetch_webhook",
            "message": "",
            "platform": "all"
          },
          "command": {
            "type": "fetch_webhook",
            "message": "",
            "platform": "event"
          },
          "pad": {
            "type": "fetch_webhook",
            "message": "",
            "platform": "all"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Utilities, select Fetch webhook, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "action.streamerbot_action",
      "kind": "action",
      "runtimeKey": "streamerbot_action",
      "label": "Run Streamer.bot Action",
      "category": "Utilities",
      "summary": "Runs a Streamer.bot action through a local WebSocket connection. Used by Streamer.bot command migration.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Streamer.bot WebSocket server enabled and a valid action ID/name.",
        "accountFeature": null,
        "operatingSystems": []
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.streamerbot_action"
        },
        {
          "path": "public/index.html",
          "symbol": "getBuilderActionEntries / createDefaultAction"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Picker availability does not supply missing event variables. Check prerequisites and originating provider.",
        "An action return value is not automatically a sequence variable. Only documented producers create template outputs."
      ],
      "relatedIds": [
        "context.automation",
        "context.timer",
        "context.command",
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "editor-fields",
          "value": {
            "host": "127.0.0.1",
            "port": 8080,
            "actionId": "fixture-action",
            "argsJson": "{}"
          }
        }
      ],
      "details": {
        "behavior": "Run a Streamer.bot action over local WebSocket, preferring actionId with actionName fallback. argsJson resolves through the global variable engine and must parse as JSON; simple event substitution is only a resolver-error fallback. User/username/platform/message arguments are supplied and can be overridden by parsed args. Host/port defaults are 127.0.0.1:8080.",
        "fields": [
          {
            "key": "host",
            "type": "text",
            "label": "Host",
            "placeholder": "127.0.0.1",
            "default": "127.0.0.1",
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "127.0.0.1",
              "timer": "127.0.0.1",
              "command": "127.0.0.1",
              "pad": "127.0.0.1"
            },
            "runtimeFallbackNote": "Run a Streamer.bot action over local WebSocket, preferring actionId with actionName fallback. argsJson resolves through the global variable engine and must parse as JSON; simple event substitution is only a resolver-error fallback. User/username/platform/message arguments are supplied and can be overridden by parsed args. Host/port defaults are 127.0.0.1:8080.",
            "dynamicSource": null
          },
          {
            "key": "port",
            "type": "number",
            "label": "Port",
            "min": 1,
            "max": 65535,
            "default": 8080,
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": 8080,
              "timer": 8080,
              "command": 8080,
              "pad": 8080
            },
            "runtimeFallbackNote": "Run a Streamer.bot action over local WebSocket, preferring actionId with actionName fallback. argsJson resolves through the global variable engine and must parse as JSON; simple event substitution is only a resolver-error fallback. User/username/platform/message arguments are supplied and can be overridden by parsed args. Host/port defaults are 127.0.0.1:8080.",
            "dynamicSource": null
          },
          {
            "key": "actionId",
            "type": "text",
            "label": "Action ID",
            "placeholder": "Preferred when available",
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Run a Streamer.bot action over local WebSocket, preferring actionId with actionName fallback. argsJson resolves through the global variable engine and must parse as JSON; simple event substitution is only a resolver-error fallback. User/username/platform/message arguments are supplied and can be overridden by parsed args. Host/port defaults are 127.0.0.1:8080.",
            "dynamicSource": null
          },
          {
            "key": "actionName",
            "type": "text",
            "label": "Action Name",
            "placeholder": "Fallback if ID is not available",
            "configurable": true,
            "supportsVariables": false,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "",
              "timer": "",
              "command": "",
              "pad": ""
            },
            "runtimeFallbackNote": "Run a Streamer.bot action over local WebSocket, preferring actionId with actionName fallback. argsJson resolves through the global variable engine and must parse as JSON; simple event substitution is only a resolver-error fallback. User/username/platform/message arguments are supplied and can be overridden by parsed args. Host/port defaults are 127.0.0.1:8080.",
            "dynamicSource": null
          },
          {
            "key": "argsJson",
            "type": "textarea",
            "label": "Arguments JSON",
            "placeholder": "{\"user\":\"{user}\",\"platform\":\"{platform}\"}",
            "configurable": true,
            "supportsVariables": true,
            "required": false,
            "requirementNote": "Required metadata is supplemented by the action behavior and operation requirements; blank input may skip or fail as described.",
            "editorDefaults": {
              "automation": "{}",
              "timer": "{}",
              "command": "{}",
              "pad": "{}"
            },
            "runtimeFallbackNote": "Run a Streamer.bot action over local WebSocket, preferring actionId with actionName fallback. argsJson resolves through the global variable engine and must parse as JSON; simple event substitution is only a resolver-error fallback. User/username/platform/message arguments are supplied and can be overridden by parsed args. Host/port defaults are 127.0.0.1:8080.",
            "dynamicSource": null
          }
        ],
        "declaredContexts": [
          "timer",
          "automation",
          "command",
          "pad"
        ],
        "pickerContexts": [
          "automation",
          "timer",
          "command",
          "pad"
        ],
        "hiddenFromPicker": false,
        "requiredVariables": [],
        "defaultsByContext": {
          "automation": {
            "type": "streamerbot_action",
            "host": "127.0.0.1",
            "port": 8080,
            "actionId": "",
            "actionName": "",
            "argsJson": "{}"
          },
          "timer": {
            "type": "streamerbot_action",
            "host": "127.0.0.1",
            "port": 8080,
            "actionId": "",
            "actionName": "",
            "argsJson": "{}"
          },
          "command": {
            "type": "streamerbot_action",
            "host": "127.0.0.1",
            "port": 8080,
            "actionId": "",
            "actionName": "",
            "argsJson": "{}"
          },
          "pad": {
            "type": "streamerbot_action",
            "host": "127.0.0.1",
            "port": 8080,
            "actionId": "",
            "actionName": "",
            "argsJson": "{}"
          }
        },
        "variants": [],
        "failureBehavior": "See the behavior for local skips/errors and context entries for sequence continuation.",
        "outputs": [],
        "ui": {
          "path": [
            "Do",
            "Advanced Actions (commands only)",
            "Add action"
          ],
          "initialFields": [],
          "steps": [
            "Choose action category Utilities, select Run Streamer.bot Action, and click Add action.",
            "Expand the action card. Configure the Fields below; check Editor defaults for your context and any operation-dependent fields.",
            "Choose resource values from real app pickers. Set output Platform separately from the trigger Where setting when the action offers it.",
            "Use Move action up / Move action down to position this action, then save the containing command, automation, timer or SheevPad button."
          ]
        }
      }
    },
    {
      "id": "trigger.first_chat",
      "kind": "trigger",
      "runtimeKey": "first_chat",
      "label": "First chat ever",
      "category": "When",
      "summary": "Fires the very first time a viewer sends a chat message on any platform.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected supported event provider; enabled automation and matching filters.",
        "inboundProviders": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.first_chat"
        },
        {
          "path": "src/features/automation-provider-capabilities.js",
          "symbol": "AUTOMATION_TRIGGER_PLATFORMS.first_chat"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "variable.trigger.first_chat.user",
        "variable.trigger.first_chat.platform",
        "variable.trigger.first_chat.username",
        "variable.trigger.first_chat.displayName",
        "variable.trigger.first_chat.userId",
        "variable.trigger.first_chat.eventId",
        "variable.trigger.first_chat.roomId",
        "context.automation"
      ],
      "examples": [
        {
          "purpose": "Trigger selection and filter defaults; supply a real target/pattern when required.",
          "format": "configuration",
          "value": {
            "triggerType": "first_chat",
            "triggerPlatform": "all",
            "triggerFilters": {}
          }
        }
      ],
      "details": {
        "behavior": "Matches the first-chat-ever flag; the viewer has not previously chatted in tracked history.",
        "filters": [],
        "variableIds": [
          "variable.trigger.first_chat.user",
          "variable.trigger.first_chat.platform",
          "variable.trigger.first_chat.username",
          "variable.trigger.first_chat.displayName",
          "variable.trigger.first_chat.userId",
          "variable.trigger.first_chat.eventId",
          "variable.trigger.first_chat.roomId"
        ],
        "cooldown": "Automation cooldownSec defaults 0; keyed by automation ID and event platform; held in memory until restart.",
        "delay": "No additional trigger delay.",
        "ui": {
          "path": [
            "Bot",
            "Automations",
            "+ New",
            "When"
          ],
          "initialFields": [],
          "steps": [
            "Choose Trigger category: Chat & viewers.",
            "Choose Trigger event: First chat ever.",
            "Fill the Trigger filters below, set Cooldown (seconds), then open Where and choose a supported Platform.",
            "Open Do, add actions, then Create Automation or Save Changes."
          ]
        }
      }
    },
    {
      "id": "variable.trigger.first_chat.user",
      "kind": "variable",
      "runtimeKey": "trigger.first_chat.user",
      "label": "{user}",
      "category": "Event variables",
      "summary": "Viewer display name/username supplied by this event; outgoing raids use destination identity.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.first_chat.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.first_chat"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{user}"
        }
      ],
      "details": {
        "syntax": "{user}",
        "canonicalKey": "user",
        "aliases": [],
        "producer": "trigger.first_chat",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Matches the first-chat-ever flag; the viewer has not previously chatted in tracked history."
      }
    },
    {
      "id": "variable.trigger.first_chat.platform",
      "kind": "variable",
      "runtimeKey": "trigger.first_chat.platform",
      "label": "{platform}",
      "category": "Event variables",
      "summary": "Originating provider, including obs/streamlabs for local events; not necessarily a chat destination.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.first_chat.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.first_chat"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{platform}"
        }
      ],
      "details": {
        "syntax": "{platform}",
        "canonicalKey": "platform",
        "aliases": [],
        "producer": "trigger.first_chat",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": null,
        "behavior": "Matches the first-chat-ever flag; the viewer has not previously chatted in tracked history."
      }
    },
    {
      "id": "variable.trigger.first_chat.username",
      "kind": "variable",
      "runtimeKey": "trigger.first_chat.username",
      "label": "{username}",
      "category": "Event variables",
      "summary": "Normalized or provider-supplied event username, not an arbitrary command argument.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.first_chat.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.first_chat"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{username}"
        }
      ],
      "details": {
        "syntax": "{username}",
        "canonicalKey": "username",
        "aliases": [],
        "producer": "trigger.first_chat",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Matches the first-chat-ever flag; the viewer has not previously chatted in tracked history."
      }
    },
    {
      "id": "variable.trigger.first_chat.displayName",
      "kind": "variable",
      "runtimeKey": "trigger.first_chat.displayName",
      "label": "{displayName}",
      "category": "Event variables",
      "summary": "Event display name with username fallback.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.first_chat.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.first_chat"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{displayName}"
        }
      ],
      "details": {
        "syntax": "{displayName}",
        "canonicalKey": "displayName",
        "aliases": [],
        "producer": "trigger.first_chat",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Matches the first-chat-ever flag; the viewer has not previously chatted in tracked history."
      }
    },
    {
      "id": "variable.trigger.first_chat.userId",
      "kind": "variable",
      "runtimeKey": "trigger.first_chat.userId",
      "label": "{userId}",
      "category": "Event variables",
      "summary": "Provider user ID when supplied; otherwise empty.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.first_chat.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.first_chat"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{userId}"
        }
      ],
      "details": {
        "syntax": "{userId}",
        "canonicalKey": "userId",
        "aliases": [],
        "producer": "trigger.first_chat",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Matches the first-chat-ever flag; the viewer has not previously chatted in tracked history."
      }
    },
    {
      "id": "variable.trigger.first_chat.eventId",
      "kind": "variable",
      "runtimeKey": "trigger.first_chat.eventId",
      "label": "{eventId}",
      "category": "Event variables",
      "summary": "Event/message identity when supplied; otherwise empty.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.first_chat.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.first_chat"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{eventId}"
        }
      ],
      "details": {
        "syntax": "{eventId}",
        "canonicalKey": "eventId",
        "aliases": [],
        "producer": "trigger.first_chat",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Matches the first-chat-ever flag; the viewer has not previously chatted in tracked history."
      }
    },
    {
      "id": "variable.trigger.first_chat.roomId",
      "kind": "variable",
      "runtimeKey": "trigger.first_chat.roomId",
      "label": "{roomId}",
      "category": "Event variables",
      "summary": "Provider room identifier when supplied; otherwise empty.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.first_chat.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.first_chat"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{roomId}"
        }
      ],
      "details": {
        "syntax": "{roomId}",
        "canonicalKey": "roomId",
        "aliases": [],
        "producer": "trigger.first_chat",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Matches the first-chat-ever flag; the viewer has not previously chatted in tracked history."
      }
    },
    {
      "id": "trigger.viewer_join",
      "kind": "trigger",
      "runtimeKey": "viewer_join",
      "label": "First chat this stream (Welcome Back)",
      "category": "When",
      "summary": "Fires the first time a viewer sends a message this stream session — the same event that shows the Welcome Back badge. Optionally filter to specific usernames.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected supported event provider; enabled automation and matching filters.",
        "inboundProviders": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.viewer_join"
        },
        {
          "path": "src/features/automation-provider-capabilities.js",
          "symbol": "AUTOMATION_TRIGGER_PLATFORMS.viewer_join"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "variable.trigger.viewer_join.user",
        "variable.trigger.viewer_join.platform",
        "variable.trigger.viewer_join.username",
        "variable.trigger.viewer_join.displayName",
        "variable.trigger.viewer_join.userId",
        "variable.trigger.viewer_join.eventId",
        "variable.trigger.viewer_join.roomId",
        "context.automation"
      ],
      "examples": [
        {
          "purpose": "Trigger selection and filter defaults; supply a real target/pattern when required.",
          "format": "configuration",
          "value": {
            "triggerType": "viewer_join",
            "triggerPlatform": "all",
            "triggerFilters": {
              "usernames": ""
            }
          }
        }
      ],
      "details": {
        "behavior": "Requires the dedicated viewer_join event, first-session flag and not first-ever. Optional usernames are trimmed, case-insensitive, one per line.",
        "filters": [
          {
            "key": "usernames",
            "type": "textarea",
            "label": "Usernames (one per line)",
            "placeholder": "StreamerBot\nMyFriend\n..."
          }
        ],
        "variableIds": [
          "variable.trigger.viewer_join.user",
          "variable.trigger.viewer_join.platform",
          "variable.trigger.viewer_join.username",
          "variable.trigger.viewer_join.displayName",
          "variable.trigger.viewer_join.userId",
          "variable.trigger.viewer_join.eventId",
          "variable.trigger.viewer_join.roomId"
        ],
        "cooldown": "Automation cooldownSec defaults 0; keyed by automation ID and event platform; held in memory until restart.",
        "delay": "No additional trigger delay.",
        "ui": {
          "path": [
            "Bot",
            "Automations",
            "+ New",
            "When"
          ],
          "initialFields": [],
          "steps": [
            "Choose Trigger category: Chat & viewers.",
            "Choose Trigger event: First chat this stream (Welcome Back).",
            "Fill the Trigger filters below, set Cooldown (seconds), then open Where and choose a supported Platform.",
            "Open Do, add actions, then Create Automation or Save Changes."
          ]
        }
      }
    },
    {
      "id": "variable.trigger.viewer_join.user",
      "kind": "variable",
      "runtimeKey": "trigger.viewer_join.user",
      "label": "{user}",
      "category": "Event variables",
      "summary": "Viewer display name/username supplied by this event; outgoing raids use destination identity.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.viewer_join.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.viewer_join"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{user}"
        }
      ],
      "details": {
        "syntax": "{user}",
        "canonicalKey": "user",
        "aliases": [],
        "producer": "trigger.viewer_join",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Requires the dedicated viewer_join event, first-session flag and not first-ever. Optional usernames are trimmed, case-insensitive, one per line."
      }
    },
    {
      "id": "variable.trigger.viewer_join.platform",
      "kind": "variable",
      "runtimeKey": "trigger.viewer_join.platform",
      "label": "{platform}",
      "category": "Event variables",
      "summary": "Originating provider, including obs/streamlabs for local events; not necessarily a chat destination.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.viewer_join.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.viewer_join"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{platform}"
        }
      ],
      "details": {
        "syntax": "{platform}",
        "canonicalKey": "platform",
        "aliases": [],
        "producer": "trigger.viewer_join",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": null,
        "behavior": "Requires the dedicated viewer_join event, first-session flag and not first-ever. Optional usernames are trimmed, case-insensitive, one per line."
      }
    },
    {
      "id": "variable.trigger.viewer_join.username",
      "kind": "variable",
      "runtimeKey": "trigger.viewer_join.username",
      "label": "{username}",
      "category": "Event variables",
      "summary": "Normalized or provider-supplied event username, not an arbitrary command argument.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.viewer_join.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.viewer_join"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{username}"
        }
      ],
      "details": {
        "syntax": "{username}",
        "canonicalKey": "username",
        "aliases": [],
        "producer": "trigger.viewer_join",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Requires the dedicated viewer_join event, first-session flag and not first-ever. Optional usernames are trimmed, case-insensitive, one per line."
      }
    },
    {
      "id": "variable.trigger.viewer_join.displayName",
      "kind": "variable",
      "runtimeKey": "trigger.viewer_join.displayName",
      "label": "{displayName}",
      "category": "Event variables",
      "summary": "Event display name with username fallback.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.viewer_join.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.viewer_join"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{displayName}"
        }
      ],
      "details": {
        "syntax": "{displayName}",
        "canonicalKey": "displayName",
        "aliases": [],
        "producer": "trigger.viewer_join",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Requires the dedicated viewer_join event, first-session flag and not first-ever. Optional usernames are trimmed, case-insensitive, one per line."
      }
    },
    {
      "id": "variable.trigger.viewer_join.userId",
      "kind": "variable",
      "runtimeKey": "trigger.viewer_join.userId",
      "label": "{userId}",
      "category": "Event variables",
      "summary": "Provider user ID when supplied; otherwise empty.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.viewer_join.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.viewer_join"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{userId}"
        }
      ],
      "details": {
        "syntax": "{userId}",
        "canonicalKey": "userId",
        "aliases": [],
        "producer": "trigger.viewer_join",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Requires the dedicated viewer_join event, first-session flag and not first-ever. Optional usernames are trimmed, case-insensitive, one per line."
      }
    },
    {
      "id": "variable.trigger.viewer_join.eventId",
      "kind": "variable",
      "runtimeKey": "trigger.viewer_join.eventId",
      "label": "{eventId}",
      "category": "Event variables",
      "summary": "Event/message identity when supplied; otherwise empty.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.viewer_join.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.viewer_join"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{eventId}"
        }
      ],
      "details": {
        "syntax": "{eventId}",
        "canonicalKey": "eventId",
        "aliases": [],
        "producer": "trigger.viewer_join",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Requires the dedicated viewer_join event, first-session flag and not first-ever. Optional usernames are trimmed, case-insensitive, one per line."
      }
    },
    {
      "id": "variable.trigger.viewer_join.roomId",
      "kind": "variable",
      "runtimeKey": "trigger.viewer_join.roomId",
      "label": "{roomId}",
      "category": "Event variables",
      "summary": "Provider room identifier when supplied; otherwise empty.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.viewer_join.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.viewer_join"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{roomId}"
        }
      ],
      "details": {
        "syntax": "{roomId}",
        "canonicalKey": "roomId",
        "aliases": [],
        "producer": "trigger.viewer_join",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Requires the dedicated viewer_join event, first-session flag and not first-ever. Optional usernames are trimmed, case-insensitive, one per line."
      }
    },
    {
      "id": "trigger.viewer_first_message",
      "kind": "trigger",
      "runtimeKey": "viewer_first_message",
      "label": "First message this stream",
      "category": "When",
      "summary": "Fires on a viewer’s first message of the stream, including their first-ever message. Optionally filter to specific usernames.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected supported event provider; enabled automation and matching filters.",
        "inboundProviders": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.viewer_first_message"
        },
        {
          "path": "src/features/automation-provider-capabilities.js",
          "symbol": "AUTOMATION_TRIGGER_PLATFORMS.viewer_first_message"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "variable.trigger.viewer_first_message.user",
        "variable.trigger.viewer_first_message.platform",
        "variable.trigger.viewer_first_message.username",
        "variable.trigger.viewer_first_message.displayName",
        "variable.trigger.viewer_first_message.userId",
        "variable.trigger.viewer_first_message.eventId",
        "variable.trigger.viewer_first_message.roomId",
        "context.automation"
      ],
      "examples": [
        {
          "purpose": "Trigger selection and filter defaults; supply a real target/pattern when required.",
          "format": "configuration",
          "value": {
            "triggerType": "viewer_first_message",
            "triggerPlatform": "all",
            "triggerFilters": {
              "usernames": ""
            }
          }
        }
      ],
      "details": {
        "behavior": "Requires viewer_first_message and first-session flag. Optional usernames are trimmed, case-insensitive, one per line. Separate from Welcome Back.",
        "filters": [
          {
            "key": "usernames",
            "type": "textarea",
            "label": "Usernames (one per line)",
            "placeholder": "StreamerBot\nMyFriend\n..."
          }
        ],
        "variableIds": [
          "variable.trigger.viewer_first_message.user",
          "variable.trigger.viewer_first_message.platform",
          "variable.trigger.viewer_first_message.username",
          "variable.trigger.viewer_first_message.displayName",
          "variable.trigger.viewer_first_message.userId",
          "variable.trigger.viewer_first_message.eventId",
          "variable.trigger.viewer_first_message.roomId"
        ],
        "cooldown": "Automation cooldownSec defaults 0; keyed by automation ID and event platform; held in memory until restart.",
        "delay": "No additional trigger delay.",
        "ui": {
          "path": [
            "Bot",
            "Automations",
            "+ New",
            "When"
          ],
          "initialFields": [],
          "steps": [
            "Choose Trigger category: Chat & viewers.",
            "Choose Trigger event: First message this stream.",
            "Fill the Trigger filters below, set Cooldown (seconds), then open Where and choose a supported Platform.",
            "Open Do, add actions, then Create Automation or Save Changes."
          ]
        }
      }
    },
    {
      "id": "variable.trigger.viewer_first_message.user",
      "kind": "variable",
      "runtimeKey": "trigger.viewer_first_message.user",
      "label": "{user}",
      "category": "Event variables",
      "summary": "Viewer display name/username supplied by this event; outgoing raids use destination identity.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.viewer_first_message.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.viewer_first_message"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{user}"
        }
      ],
      "details": {
        "syntax": "{user}",
        "canonicalKey": "user",
        "aliases": [],
        "producer": "trigger.viewer_first_message",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Requires viewer_first_message and first-session flag. Optional usernames are trimmed, case-insensitive, one per line. Separate from Welcome Back."
      }
    },
    {
      "id": "variable.trigger.viewer_first_message.platform",
      "kind": "variable",
      "runtimeKey": "trigger.viewer_first_message.platform",
      "label": "{platform}",
      "category": "Event variables",
      "summary": "Originating provider, including obs/streamlabs for local events; not necessarily a chat destination.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.viewer_first_message.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.viewer_first_message"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{platform}"
        }
      ],
      "details": {
        "syntax": "{platform}",
        "canonicalKey": "platform",
        "aliases": [],
        "producer": "trigger.viewer_first_message",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": null,
        "behavior": "Requires viewer_first_message and first-session flag. Optional usernames are trimmed, case-insensitive, one per line. Separate from Welcome Back."
      }
    },
    {
      "id": "variable.trigger.viewer_first_message.username",
      "kind": "variable",
      "runtimeKey": "trigger.viewer_first_message.username",
      "label": "{username}",
      "category": "Event variables",
      "summary": "Normalized or provider-supplied event username, not an arbitrary command argument.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.viewer_first_message.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.viewer_first_message"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{username}"
        }
      ],
      "details": {
        "syntax": "{username}",
        "canonicalKey": "username",
        "aliases": [],
        "producer": "trigger.viewer_first_message",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Requires viewer_first_message and first-session flag. Optional usernames are trimmed, case-insensitive, one per line. Separate from Welcome Back."
      }
    },
    {
      "id": "variable.trigger.viewer_first_message.displayName",
      "kind": "variable",
      "runtimeKey": "trigger.viewer_first_message.displayName",
      "label": "{displayName}",
      "category": "Event variables",
      "summary": "Event display name with username fallback.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.viewer_first_message.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.viewer_first_message"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{displayName}"
        }
      ],
      "details": {
        "syntax": "{displayName}",
        "canonicalKey": "displayName",
        "aliases": [],
        "producer": "trigger.viewer_first_message",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Requires viewer_first_message and first-session flag. Optional usernames are trimmed, case-insensitive, one per line. Separate from Welcome Back."
      }
    },
    {
      "id": "variable.trigger.viewer_first_message.userId",
      "kind": "variable",
      "runtimeKey": "trigger.viewer_first_message.userId",
      "label": "{userId}",
      "category": "Event variables",
      "summary": "Provider user ID when supplied; otherwise empty.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.viewer_first_message.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.viewer_first_message"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{userId}"
        }
      ],
      "details": {
        "syntax": "{userId}",
        "canonicalKey": "userId",
        "aliases": [],
        "producer": "trigger.viewer_first_message",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Requires viewer_first_message and first-session flag. Optional usernames are trimmed, case-insensitive, one per line. Separate from Welcome Back."
      }
    },
    {
      "id": "variable.trigger.viewer_first_message.eventId",
      "kind": "variable",
      "runtimeKey": "trigger.viewer_first_message.eventId",
      "label": "{eventId}",
      "category": "Event variables",
      "summary": "Event/message identity when supplied; otherwise empty.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.viewer_first_message.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.viewer_first_message"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{eventId}"
        }
      ],
      "details": {
        "syntax": "{eventId}",
        "canonicalKey": "eventId",
        "aliases": [],
        "producer": "trigger.viewer_first_message",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Requires viewer_first_message and first-session flag. Optional usernames are trimmed, case-insensitive, one per line. Separate from Welcome Back."
      }
    },
    {
      "id": "variable.trigger.viewer_first_message.roomId",
      "kind": "variable",
      "runtimeKey": "trigger.viewer_first_message.roomId",
      "label": "{roomId}",
      "category": "Event variables",
      "summary": "Provider room identifier when supplied; otherwise empty.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.viewer_first_message.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.viewer_first_message"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{roomId}"
        }
      ],
      "details": {
        "syntax": "{roomId}",
        "canonicalKey": "roomId",
        "aliases": [],
        "producer": "trigger.viewer_first_message",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Requires viewer_first_message and first-session flag. Optional usernames are trimmed, case-insensitive, one per line. Separate from Welcome Back."
      }
    },
    {
      "id": "trigger.first_chat_today",
      "kind": "trigger",
      "runtimeKey": "first_chat_today",
      "label": "First chat of the day",
      "category": "When",
      "summary": "Fires on a viewer's first chat message of the calendar day (resets at midnight). Good for daily greetings or announcing daily loyalty bonuses.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected supported event provider; enabled automation and matching filters.",
        "inboundProviders": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.first_chat_today"
        },
        {
          "path": "src/features/automation-provider-capabilities.js",
          "symbol": "AUTOMATION_TRIGGER_PLATFORMS.first_chat_today"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "variable.trigger.first_chat_today.user",
        "variable.trigger.first_chat_today.platform",
        "context.automation"
      ],
      "examples": [
        {
          "purpose": "Trigger selection and filter defaults; supply a real target/pattern when required.",
          "format": "configuration",
          "value": {
            "triggerType": "first_chat_today",
            "triggerPlatform": "all",
            "triggerFilters": {}
          }
        }
      ],
      "details": {
        "behavior": "Matches the first-today flag supplied by viewer tracking; day boundaries follow the app tracking calendar.",
        "filters": [],
        "variableIds": [
          "variable.trigger.first_chat_today.user",
          "variable.trigger.first_chat_today.platform"
        ],
        "cooldown": "Automation cooldownSec defaults 0; keyed by automation ID and event platform; held in memory until restart.",
        "delay": "No additional trigger delay.",
        "ui": {
          "path": [
            "Bot",
            "Automations",
            "+ New",
            "When"
          ],
          "initialFields": [],
          "steps": [
            "Choose Trigger category: Chat & viewers.",
            "Choose Trigger event: First chat of the day.",
            "Fill the Trigger filters below, set Cooldown (seconds), then open Where and choose a supported Platform.",
            "Open Do, add actions, then Create Automation or Save Changes."
          ]
        }
      }
    },
    {
      "id": "variable.trigger.first_chat_today.user",
      "kind": "variable",
      "runtimeKey": "trigger.first_chat_today.user",
      "label": "{user}",
      "category": "Event variables",
      "summary": "Viewer display name/username supplied by this event; outgoing raids use destination identity.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.first_chat_today.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.first_chat_today"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{user}"
        }
      ],
      "details": {
        "syntax": "{user}",
        "canonicalKey": "user",
        "aliases": [],
        "producer": "trigger.first_chat_today",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": null,
        "behavior": "Matches the first-today flag supplied by viewer tracking; day boundaries follow the app tracking calendar."
      }
    },
    {
      "id": "variable.trigger.first_chat_today.platform",
      "kind": "variable",
      "runtimeKey": "trigger.first_chat_today.platform",
      "label": "{platform}",
      "category": "Event variables",
      "summary": "Originating provider, including obs/streamlabs for local events; not necessarily a chat destination.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.first_chat_today.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.first_chat_today"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{platform}"
        }
      ],
      "details": {
        "syntax": "{platform}",
        "canonicalKey": "platform",
        "aliases": [],
        "producer": "trigger.first_chat_today",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": null,
        "behavior": "Matches the first-today flag supplied by viewer tracking; day boundaries follow the app tracking calendar."
      }
    },
    {
      "id": "trigger.is_birthday",
      "kind": "trigger",
      "runtimeKey": "is_birthday",
      "label": "Viewer birthday",
      "category": "When",
      "summary": "Fires once per stream session when a viewer with a saved birthday chats on their birthday.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected supported event provider; enabled automation and matching filters.",
        "inboundProviders": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.is_birthday"
        },
        {
          "path": "src/features/automation-provider-capabilities.js",
          "symbol": "AUTOMATION_TRIGGER_PLATFORMS.is_birthday"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "variable.trigger.is_birthday.user",
        "variable.trigger.is_birthday.platform",
        "variable.trigger.is_birthday.birthday",
        "variable.trigger.is_birthday.birthdayAge",
        "variable.trigger.is_birthday.age",
        "variable.trigger.is_birthday.agemessage",
        "context.automation"
      ],
      "examples": [
        {
          "purpose": "Trigger selection and filter defaults; supply a real target/pattern when required.",
          "format": "configuration",
          "value": {
            "triggerType": "is_birthday",
            "triggerPlatform": "all",
            "triggerFilters": {}
          }
        }
      ],
      "details": {
        "behavior": "Requires the birthday event and birthday flag. Saved birthday and once-per-stream viewer tracking are prerequisites; age may be blank without a birth year.",
        "filters": [],
        "variableIds": [
          "variable.trigger.is_birthday.user",
          "variable.trigger.is_birthday.platform",
          "variable.trigger.is_birthday.birthday",
          "variable.trigger.is_birthday.birthdayAge",
          "variable.trigger.is_birthday.age",
          "variable.trigger.is_birthday.agemessage"
        ],
        "cooldown": "Automation cooldownSec defaults 0; keyed by automation ID and event platform; held in memory until restart.",
        "delay": "No additional trigger delay.",
        "ui": {
          "path": [
            "Bot",
            "Automations",
            "+ New",
            "When"
          ],
          "initialFields": [],
          "steps": [
            "Choose Trigger category: Chat & viewers.",
            "Choose Trigger event: Viewer birthday.",
            "Fill the Trigger filters below, set Cooldown (seconds), then open Where and choose a supported Platform.",
            "Open Do, add actions, then Create Automation or Save Changes."
          ]
        }
      }
    },
    {
      "id": "variable.trigger.is_birthday.user",
      "kind": "variable",
      "runtimeKey": "trigger.is_birthday.user",
      "label": "{user}",
      "category": "Event variables",
      "summary": "Viewer display name/username supplied by this event; outgoing raids use destination identity.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.is_birthday.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.is_birthday"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{user}"
        }
      ],
      "details": {
        "syntax": "{user}",
        "canonicalKey": "user",
        "aliases": [],
        "producer": "trigger.is_birthday",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": null,
        "behavior": "Requires the birthday event and birthday flag. Saved birthday and once-per-stream viewer tracking are prerequisites; age may be blank without a birth year."
      }
    },
    {
      "id": "variable.trigger.is_birthday.platform",
      "kind": "variable",
      "runtimeKey": "trigger.is_birthday.platform",
      "label": "{platform}",
      "category": "Event variables",
      "summary": "Originating provider, including obs/streamlabs for local events; not necessarily a chat destination.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.is_birthday.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.is_birthday"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{platform}"
        }
      ],
      "details": {
        "syntax": "{platform}",
        "canonicalKey": "platform",
        "aliases": [],
        "producer": "trigger.is_birthday",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": null,
        "behavior": "Requires the birthday event and birthday flag. Saved birthday and once-per-stream viewer tracking are prerequisites; age may be blank without a birth year."
      }
    },
    {
      "id": "variable.trigger.is_birthday.birthday",
      "kind": "variable",
      "runtimeKey": "trigger.is_birthday.birthday",
      "label": "{birthday}",
      "category": "Event variables",
      "summary": "Saved formatted birthday.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.is_birthday.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.is_birthday"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{birthday}"
        }
      ],
      "details": {
        "syntax": "{birthday}",
        "canonicalKey": "birthday",
        "aliases": [],
        "producer": "trigger.is_birthday",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Requires the birthday event and birthday flag. Saved birthday and once-per-stream viewer tracking are prerequisites; age may be blank without a birth year."
      }
    },
    {
      "id": "variable.trigger.is_birthday.birthdayAge",
      "kind": "variable",
      "runtimeKey": "trigger.is_birthday.birthdayAge",
      "label": "{birthdayAge}",
      "category": "Event variables",
      "summary": "Birthday age when a birth year is known; otherwise empty.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.is_birthday.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.is_birthday"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{birthdayAge}"
        }
      ],
      "details": {
        "syntax": "{birthdayAge}",
        "canonicalKey": "birthdayAge",
        "aliases": [],
        "producer": "trigger.is_birthday",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Requires the birthday event and birthday flag. Saved birthday and once-per-stream viewer tracking are prerequisites; age may be blank without a birth year."
      }
    },
    {
      "id": "variable.trigger.is_birthday.age",
      "kind": "variable",
      "runtimeKey": "trigger.is_birthday.age",
      "label": "{age}",
      "category": "Event variables",
      "summary": "Birthday age, with birthdayAge fallback.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.is_birthday.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.is_birthday"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{age}"
        }
      ],
      "details": {
        "syntax": "{age}",
        "canonicalKey": "age",
        "aliases": [],
        "producer": "trigger.is_birthday",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Requires the birthday event and birthday flag. Saved birthday and once-per-stream viewer tracking are prerequisites; age may be blank without a birth year."
      }
    },
    {
      "id": "variable.trigger.is_birthday.agemessage",
      "kind": "variable",
      "runtimeKey": "trigger.is_birthday.agemessage",
      "label": "{agemessage}",
      "category": "Event variables",
      "summary": "Optional birthday age message; empty when unavailable.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.is_birthday.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.is_birthday"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{agemessage}"
        }
      ],
      "details": {
        "syntax": "{agemessage}",
        "canonicalKey": "agemessage",
        "aliases": [],
        "producer": "trigger.is_birthday",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Requires the birthday event and birthday flag. Saved birthday and once-per-stream viewer tracking are prerequisites; age may be blank without a birth year."
      }
    },
    {
      "id": "trigger.follow",
      "kind": "trigger",
      "runtimeKey": "follow",
      "label": "New follow",
      "category": "When",
      "summary": "Fires when a viewer follows on Twitch, Kick, or TikTok. YouTube does not expose a live follow event.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected supported event provider; enabled automation and matching filters.",
        "inboundProviders": [
          "twitch",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.follow"
        },
        {
          "path": "src/features/automation-provider-capabilities.js",
          "symbol": "AUTOMATION_TRIGGER_PLATFORMS.follow"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "variable.trigger.follow.user",
        "variable.trigger.follow.username",
        "variable.trigger.follow.displayName",
        "variable.trigger.follow.userId",
        "variable.trigger.follow.eventId",
        "variable.trigger.follow.roomId",
        "context.automation"
      ],
      "examples": [
        {
          "purpose": "Trigger selection and filter defaults; supply a real target/pattern when required.",
          "format": "configuration",
          "value": {
            "triggerType": "follow",
            "triggerPlatform": "twitch",
            "triggerFilters": {}
          }
        }
      ],
      "details": {
        "behavior": "Matches New follow from Twitch, Kick or TikTok; no YouTube follow event exists.",
        "filters": [],
        "variableIds": [
          "variable.trigger.follow.user",
          "variable.trigger.follow.username",
          "variable.trigger.follow.displayName",
          "variable.trigger.follow.userId",
          "variable.trigger.follow.eventId",
          "variable.trigger.follow.roomId"
        ],
        "cooldown": "Automation cooldownSec defaults 0; keyed by automation ID and event platform; held in memory until restart.",
        "delay": "No additional trigger delay.",
        "ui": {
          "path": [
            "Bot",
            "Automations",
            "+ New",
            "When"
          ],
          "initialFields": [],
          "steps": [
            "Choose Trigger category: Platform events.",
            "Choose the incoming Platform first.",
            "Choose Trigger event: New follow.",
            "Fill the Trigger filters below, set Cooldown (seconds), then open Where and choose a supported Platform.",
            "Open Do, add actions, then Create Automation or Save Changes."
          ]
        }
      }
    },
    {
      "id": "variable.trigger.follow.user",
      "kind": "variable",
      "runtimeKey": "trigger.follow.user",
      "label": "{user}",
      "category": "Event variables",
      "summary": "Viewer display name/username supplied by this event; outgoing raids use destination identity.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.follow.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.follow"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{user}"
        }
      ],
      "details": {
        "syntax": "{user}",
        "canonicalKey": "user",
        "aliases": [],
        "producer": "trigger.follow",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Matches New follow from Twitch, Kick or TikTok; no YouTube follow event exists."
      }
    },
    {
      "id": "variable.trigger.follow.username",
      "kind": "variable",
      "runtimeKey": "trigger.follow.username",
      "label": "{username}",
      "category": "Event variables",
      "summary": "Normalized or provider-supplied event username, not an arbitrary command argument.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.follow.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.follow"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{username}"
        }
      ],
      "details": {
        "syntax": "{username}",
        "canonicalKey": "username",
        "aliases": [],
        "producer": "trigger.follow",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Matches New follow from Twitch, Kick or TikTok; no YouTube follow event exists."
      }
    },
    {
      "id": "variable.trigger.follow.displayName",
      "kind": "variable",
      "runtimeKey": "trigger.follow.displayName",
      "label": "{displayName}",
      "category": "Event variables",
      "summary": "Event display name with username fallback.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.follow.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.follow"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{displayName}"
        }
      ],
      "details": {
        "syntax": "{displayName}",
        "canonicalKey": "displayName",
        "aliases": [],
        "producer": "trigger.follow",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Matches New follow from Twitch, Kick or TikTok; no YouTube follow event exists."
      }
    },
    {
      "id": "variable.trigger.follow.userId",
      "kind": "variable",
      "runtimeKey": "trigger.follow.userId",
      "label": "{userId}",
      "category": "Event variables",
      "summary": "Provider user ID when supplied; otherwise empty.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.follow.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.follow"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{userId}"
        }
      ],
      "details": {
        "syntax": "{userId}",
        "canonicalKey": "userId",
        "aliases": [],
        "producer": "trigger.follow",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Matches New follow from Twitch, Kick or TikTok; no YouTube follow event exists."
      }
    },
    {
      "id": "variable.trigger.follow.eventId",
      "kind": "variable",
      "runtimeKey": "trigger.follow.eventId",
      "label": "{eventId}",
      "category": "Event variables",
      "summary": "Event/message identity when supplied; otherwise empty.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.follow.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.follow"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{eventId}"
        }
      ],
      "details": {
        "syntax": "{eventId}",
        "canonicalKey": "eventId",
        "aliases": [],
        "producer": "trigger.follow",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Matches New follow from Twitch, Kick or TikTok; no YouTube follow event exists."
      }
    },
    {
      "id": "variable.trigger.follow.roomId",
      "kind": "variable",
      "runtimeKey": "trigger.follow.roomId",
      "label": "{roomId}",
      "category": "Event variables",
      "summary": "Provider room identifier when supplied; otherwise empty.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.follow.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.follow"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{roomId}"
        }
      ],
      "details": {
        "syntax": "{roomId}",
        "canonicalKey": "roomId",
        "aliases": [],
        "producer": "trigger.follow",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Matches New follow from Twitch, Kick or TikTok; no YouTube follow event exists."
      }
    },
    {
      "id": "trigger.subscribe",
      "kind": "trigger",
      "runtimeKey": "subscribe",
      "label": "Subscription",
      "category": "When",
      "summary": "Fires on a new subscription or resub.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected supported event provider; enabled automation and matching filters.",
        "inboundProviders": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.subscribe"
        },
        {
          "path": "src/features/automation-provider-capabilities.js",
          "symbol": "AUTOMATION_TRIGGER_PLATFORMS.subscribe"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "variable.trigger.subscribe.user",
        "variable.trigger.subscribe.username",
        "variable.trigger.subscribe.displayName",
        "variable.trigger.subscribe.userId",
        "variable.trigger.subscribe.eventId",
        "variable.trigger.subscribe.roomId",
        "variable.trigger.subscribe.months",
        "variable.trigger.subscribe.tier",
        "variable.trigger.subscribe.message",
        "variable.trigger.subscribe.count",
        "variable.trigger.subscribe.subscriptionKind",
        "context.automation"
      ],
      "examples": [
        {
          "purpose": "Trigger selection and filter defaults; supply a real target/pattern when required.",
          "format": "configuration",
          "value": {
            "triggerType": "subscribe",
            "triggerPlatform": "twitch",
            "triggerFilters": {
              "min_months": 0,
              "min_count": 0,
              "subscription_kind": ""
            }
          }
        }
      ],
      "details": {
        "behavior": "Subscription months/count must meet both minimums. Missing event months/count are treated as 1. A nonblank TikTok type filter matches subscriptionKind exactly, including gifted subscriptions.",
        "filters": [
          {
            "key": "min_months",
            "type": "number",
            "label": "Minimum months (0 = any)",
            "min": 0,
            "default": 0
          },
          {
            "key": "min_count",
            "type": "number",
            "label": "Minimum count (0 = any)",
            "min": 0,
            "default": 0
          },
          {
            "key": "subscription_kind",
            "type": "select",
            "label": "TikTok subscription type",
            "options": [
              {
                "value": "",
                "label": "Any type"
              },
              {
                "value": "subscribe",
                "label": "New subscription"
              },
              {
                "value": "resubscribe",
                "label": "Resubscription"
              },
              {
                "value": "subscription_gift",
                "label": "Gifted subscription"
              },
              {
                "value": "super_fan",
                "label": "Super Fan"
              }
            ]
          }
        ],
        "variableIds": [
          "variable.trigger.subscribe.user",
          "variable.trigger.subscribe.username",
          "variable.trigger.subscribe.displayName",
          "variable.trigger.subscribe.userId",
          "variable.trigger.subscribe.eventId",
          "variable.trigger.subscribe.roomId",
          "variable.trigger.subscribe.months",
          "variable.trigger.subscribe.tier",
          "variable.trigger.subscribe.message",
          "variable.trigger.subscribe.count",
          "variable.trigger.subscribe.subscriptionKind"
        ],
        "cooldown": "Automation cooldownSec defaults 0; keyed by automation ID and event platform; held in memory until restart.",
        "delay": "No additional trigger delay.",
        "ui": {
          "path": [
            "Bot",
            "Automations",
            "+ New",
            "When"
          ],
          "initialFields": [],
          "steps": [
            "Choose Trigger category: Monetization.",
            "Choose Trigger event: Subscription.",
            "Fill the Trigger filters below, set Cooldown (seconds), then open Where and choose a supported Platform.",
            "Open Do, add actions, then Create Automation or Save Changes."
          ]
        }
      }
    },
    {
      "id": "variable.trigger.subscribe.user",
      "kind": "variable",
      "runtimeKey": "trigger.subscribe.user",
      "label": "{user}",
      "category": "Event variables",
      "summary": "Viewer display name/username supplied by this event; outgoing raids use destination identity.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.subscribe.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.subscribe"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{user}"
        }
      ],
      "details": {
        "syntax": "{user}",
        "canonicalKey": "user",
        "aliases": [],
        "producer": "trigger.subscribe",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Subscription months/count must meet both minimums. Missing event months/count are treated as 1. A nonblank TikTok type filter matches subscriptionKind exactly, including gifted subscriptions."
      }
    },
    {
      "id": "variable.trigger.subscribe.username",
      "kind": "variable",
      "runtimeKey": "trigger.subscribe.username",
      "label": "{username}",
      "category": "Event variables",
      "summary": "Normalized or provider-supplied event username, not an arbitrary command argument.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.subscribe.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.subscribe"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{username}"
        }
      ],
      "details": {
        "syntax": "{username}",
        "canonicalKey": "username",
        "aliases": [],
        "producer": "trigger.subscribe",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Subscription months/count must meet both minimums. Missing event months/count are treated as 1. A nonblank TikTok type filter matches subscriptionKind exactly, including gifted subscriptions."
      }
    },
    {
      "id": "variable.trigger.subscribe.displayName",
      "kind": "variable",
      "runtimeKey": "trigger.subscribe.displayName",
      "label": "{displayName}",
      "category": "Event variables",
      "summary": "Event display name with username fallback.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.subscribe.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.subscribe"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{displayName}"
        }
      ],
      "details": {
        "syntax": "{displayName}",
        "canonicalKey": "displayName",
        "aliases": [],
        "producer": "trigger.subscribe",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Subscription months/count must meet both minimums. Missing event months/count are treated as 1. A nonblank TikTok type filter matches subscriptionKind exactly, including gifted subscriptions."
      }
    },
    {
      "id": "variable.trigger.subscribe.userId",
      "kind": "variable",
      "runtimeKey": "trigger.subscribe.userId",
      "label": "{userId}",
      "category": "Event variables",
      "summary": "Provider user ID when supplied; otherwise empty.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.subscribe.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.subscribe"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{userId}"
        }
      ],
      "details": {
        "syntax": "{userId}",
        "canonicalKey": "userId",
        "aliases": [],
        "producer": "trigger.subscribe",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Subscription months/count must meet both minimums. Missing event months/count are treated as 1. A nonblank TikTok type filter matches subscriptionKind exactly, including gifted subscriptions."
      }
    },
    {
      "id": "variable.trigger.subscribe.eventId",
      "kind": "variable",
      "runtimeKey": "trigger.subscribe.eventId",
      "label": "{eventId}",
      "category": "Event variables",
      "summary": "Event/message identity when supplied; otherwise empty.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.subscribe.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.subscribe"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{eventId}"
        }
      ],
      "details": {
        "syntax": "{eventId}",
        "canonicalKey": "eventId",
        "aliases": [],
        "producer": "trigger.subscribe",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Subscription months/count must meet both minimums. Missing event months/count are treated as 1. A nonblank TikTok type filter matches subscriptionKind exactly, including gifted subscriptions."
      }
    },
    {
      "id": "variable.trigger.subscribe.roomId",
      "kind": "variable",
      "runtimeKey": "trigger.subscribe.roomId",
      "label": "{roomId}",
      "category": "Event variables",
      "summary": "Provider room identifier when supplied; otherwise empty.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.subscribe.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.subscribe"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{roomId}"
        }
      ],
      "details": {
        "syntax": "{roomId}",
        "canonicalKey": "roomId",
        "aliases": [],
        "producer": "trigger.subscribe",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Subscription months/count must meet both minimums. Missing event months/count are treated as 1. A nonblank TikTok type filter matches subscriptionKind exactly, including gifted subscriptions."
      }
    },
    {
      "id": "variable.trigger.subscribe.months",
      "kind": "variable",
      "runtimeKey": "trigger.subscribe.months",
      "label": "{months}",
      "category": "Event variables",
      "summary": "Subscription month count; missing value defaults to 1.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.subscribe.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.subscribe"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{months}"
        }
      ],
      "details": {
        "syntax": "{months}",
        "canonicalKey": "months",
        "aliases": [],
        "producer": "trigger.subscribe",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": 1,
        "behavior": "Subscription months/count must meet both minimums. Missing event months/count are treated as 1. A nonblank TikTok type filter matches subscriptionKind exactly, including gifted subscriptions."
      }
    },
    {
      "id": "variable.trigger.subscribe.tier",
      "kind": "variable",
      "runtimeKey": "trigger.subscribe.tier",
      "label": "{tier}",
      "category": "Event variables",
      "summary": "Provider subscription tier; missing value defaults to 1000.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.subscribe.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.subscribe"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{tier}"
        }
      ],
      "details": {
        "syntax": "{tier}",
        "canonicalKey": "tier",
        "aliases": [],
        "producer": "trigger.subscribe",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "1000",
        "behavior": "Subscription months/count must meet both minimums. Missing event months/count are treated as 1. A nonblank TikTok type filter matches subscriptionKind exactly, including gifted subscriptions."
      }
    },
    {
      "id": "variable.trigger.subscribe.message",
      "kind": "variable",
      "runtimeKey": "trigger.subscribe.message",
      "label": "{message}",
      "category": "Event variables",
      "summary": "Event text; reward redemptions use viewer input, TikTok questions use the question text.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.subscribe.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.subscribe"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{message}"
        }
      ],
      "details": {
        "syntax": "{message}",
        "canonicalKey": "message",
        "aliases": [],
        "producer": "trigger.subscribe",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Subscription months/count must meet both minimums. Missing event months/count are treated as 1. A nonblank TikTok type filter matches subscriptionKind exactly, including gifted subscriptions."
      }
    },
    {
      "id": "variable.trigger.subscribe.count",
      "kind": "variable",
      "runtimeKey": "trigger.subscribe.count",
      "label": "{count}",
      "category": "Event variables",
      "summary": "Subscription/gift count from the event; extraction defaults to 1.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.subscribe.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.subscribe"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{count}"
        }
      ],
      "details": {
        "syntax": "{count}",
        "canonicalKey": "count",
        "aliases": [],
        "producer": "trigger.subscribe",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": 1,
        "behavior": "Subscription months/count must meet both minimums. Missing event months/count are treated as 1. A nonblank TikTok type filter matches subscriptionKind exactly, including gifted subscriptions."
      }
    },
    {
      "id": "variable.trigger.subscribe.subscriptionKind",
      "kind": "variable",
      "runtimeKey": "trigger.subscribe.subscriptionKind",
      "label": "{subscriptionKind}",
      "category": "Event variables",
      "summary": "TikTok subscription subtype, empty when absent.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.subscribe.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.subscribe"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{subscriptionKind}"
        }
      ],
      "details": {
        "syntax": "{subscriptionKind}",
        "canonicalKey": "subscriptionKind",
        "aliases": [],
        "producer": "trigger.subscribe",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Subscription months/count must meet both minimums. Missing event months/count are treated as 1. A nonblank TikTok type filter matches subscriptionKind exactly, including gifted subscriptions."
      }
    },
    {
      "id": "trigger.tiktok_gift",
      "kind": "trigger",
      "runtimeKey": "tiktok_gift",
      "label": "TikTok gift",
      "category": "When",
      "summary": "Fires once when a TikTok gift or gift streak is finalized.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected supported event provider; enabled automation and matching filters.",
        "inboundProviders": [
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_gift"
        },
        {
          "path": "src/features/automation-provider-capabilities.js",
          "symbol": "AUTOMATION_TRIGGER_PLATFORMS.tiktok_gift"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "variable.trigger.tiktok_gift.user",
        "variable.trigger.tiktok_gift.username",
        "variable.trigger.tiktok_gift.displayName",
        "variable.trigger.tiktok_gift.userId",
        "variable.trigger.tiktok_gift.eventId",
        "variable.trigger.tiktok_gift.roomId",
        "variable.trigger.tiktok_gift.gift",
        "variable.trigger.tiktok_gift.giftId",
        "variable.trigger.tiktok_gift.count",
        "variable.trigger.tiktok_gift.diamonds",
        "variable.trigger.tiktok_gift.amount",
        "context.automation"
      ],
      "examples": [
        {
          "purpose": "Trigger selection and filter defaults; supply a real target/pattern when required.",
          "format": "configuration",
          "value": {
            "triggerType": "tiktok_gift",
            "triggerPlatform": "tiktok",
            "triggerFilters": {
              "gift_name": "",
              "min_count": 0,
              "min_diamonds": 0
            }
          }
        }
      ],
      "details": {
        "behavior": "Finalized gift/streak only; optional gift name is exact case-insensitive. Count and diamond thresholds both apply.",
        "filters": [
          {
            "key": "gift_name",
            "type": "text",
            "label": "Gift name (blank = any)"
          },
          {
            "key": "min_count",
            "type": "number",
            "label": "Minimum count (0 = any)",
            "min": 0,
            "default": 0
          },
          {
            "key": "min_diamonds",
            "type": "number",
            "label": "Minimum diamonds (0 = any)",
            "min": 0,
            "default": 0
          }
        ],
        "variableIds": [
          "variable.trigger.tiktok_gift.user",
          "variable.trigger.tiktok_gift.username",
          "variable.trigger.tiktok_gift.displayName",
          "variable.trigger.tiktok_gift.userId",
          "variable.trigger.tiktok_gift.eventId",
          "variable.trigger.tiktok_gift.roomId",
          "variable.trigger.tiktok_gift.gift",
          "variable.trigger.tiktok_gift.giftId",
          "variable.trigger.tiktok_gift.count",
          "variable.trigger.tiktok_gift.diamonds",
          "variable.trigger.tiktok_gift.amount"
        ],
        "cooldown": "Automation cooldownSec defaults 0; keyed by automation ID and event platform; held in memory until restart.",
        "delay": "No additional trigger delay.",
        "ui": {
          "path": [
            "Bot",
            "Automations",
            "+ New",
            "When"
          ],
          "initialFields": [],
          "steps": [
            "Choose Trigger category: Monetization.",
            "Choose Trigger event: TikTok gift.",
            "Fill the Trigger filters below, set Cooldown (seconds), then open Where and choose a supported Platform.",
            "Open Do, add actions, then Create Automation or Save Changes."
          ]
        }
      }
    },
    {
      "id": "variable.trigger.tiktok_gift.user",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_gift.user",
      "label": "{user}",
      "category": "Event variables",
      "summary": "Viewer display name/username supplied by this event; outgoing raids use destination identity.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_gift.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_gift"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{user}"
        }
      ],
      "details": {
        "syntax": "{user}",
        "canonicalKey": "user",
        "aliases": [],
        "producer": "trigger.tiktok_gift",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Finalized gift/streak only; optional gift name is exact case-insensitive. Count and diamond thresholds both apply."
      }
    },
    {
      "id": "variable.trigger.tiktok_gift.username",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_gift.username",
      "label": "{username}",
      "category": "Event variables",
      "summary": "Normalized or provider-supplied event username, not an arbitrary command argument.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_gift.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_gift"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{username}"
        }
      ],
      "details": {
        "syntax": "{username}",
        "canonicalKey": "username",
        "aliases": [],
        "producer": "trigger.tiktok_gift",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Finalized gift/streak only; optional gift name is exact case-insensitive. Count and diamond thresholds both apply."
      }
    },
    {
      "id": "variable.trigger.tiktok_gift.displayName",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_gift.displayName",
      "label": "{displayName}",
      "category": "Event variables",
      "summary": "Event display name with username fallback.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_gift.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_gift"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{displayName}"
        }
      ],
      "details": {
        "syntax": "{displayName}",
        "canonicalKey": "displayName",
        "aliases": [],
        "producer": "trigger.tiktok_gift",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Finalized gift/streak only; optional gift name is exact case-insensitive. Count and diamond thresholds both apply."
      }
    },
    {
      "id": "variable.trigger.tiktok_gift.userId",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_gift.userId",
      "label": "{userId}",
      "category": "Event variables",
      "summary": "Provider user ID when supplied; otherwise empty.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_gift.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_gift"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{userId}"
        }
      ],
      "details": {
        "syntax": "{userId}",
        "canonicalKey": "userId",
        "aliases": [],
        "producer": "trigger.tiktok_gift",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Finalized gift/streak only; optional gift name is exact case-insensitive. Count and diamond thresholds both apply."
      }
    },
    {
      "id": "variable.trigger.tiktok_gift.eventId",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_gift.eventId",
      "label": "{eventId}",
      "category": "Event variables",
      "summary": "Event/message identity when supplied; otherwise empty.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_gift.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_gift"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{eventId}"
        }
      ],
      "details": {
        "syntax": "{eventId}",
        "canonicalKey": "eventId",
        "aliases": [],
        "producer": "trigger.tiktok_gift",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Finalized gift/streak only; optional gift name is exact case-insensitive. Count and diamond thresholds both apply."
      }
    },
    {
      "id": "variable.trigger.tiktok_gift.roomId",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_gift.roomId",
      "label": "{roomId}",
      "category": "Event variables",
      "summary": "Provider room identifier when supplied; otherwise empty.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_gift.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_gift"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{roomId}"
        }
      ],
      "details": {
        "syntax": "{roomId}",
        "canonicalKey": "roomId",
        "aliases": [],
        "producer": "trigger.tiktok_gift",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Finalized gift/streak only; optional gift name is exact case-insensitive. Count and diamond thresholds both apply."
      }
    },
    {
      "id": "variable.trigger.tiktok_gift.gift",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_gift.gift",
      "label": "{gift}",
      "category": "Event variables",
      "summary": "TikTok gift name.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_gift.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_gift"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{gift}"
        }
      ],
      "details": {
        "syntax": "{gift}",
        "canonicalKey": "gift",
        "aliases": [],
        "producer": "trigger.tiktok_gift",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Finalized gift/streak only; optional gift name is exact case-insensitive. Count and diamond thresholds both apply."
      }
    },
    {
      "id": "variable.trigger.tiktok_gift.giftId",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_gift.giftId",
      "label": "{giftId}",
      "category": "Event variables",
      "summary": "TikTok gift identifier.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_gift.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_gift"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{giftId}"
        }
      ],
      "details": {
        "syntax": "{giftId}",
        "canonicalKey": "giftId",
        "aliases": [],
        "producer": "trigger.tiktok_gift",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Finalized gift/streak only; optional gift name is exact case-insensitive. Count and diamond thresholds both apply."
      }
    },
    {
      "id": "variable.trigger.tiktok_gift.count",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_gift.count",
      "label": "{count}",
      "category": "Event variables",
      "summary": "Subscription/gift count from the event; extraction defaults to 1.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_gift.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_gift"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{count}"
        }
      ],
      "details": {
        "syntax": "{count}",
        "canonicalKey": "count",
        "aliases": [],
        "producer": "trigger.tiktok_gift",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": 1,
        "behavior": "Finalized gift/streak only; optional gift name is exact case-insensitive. Count and diamond thresholds both apply."
      }
    },
    {
      "id": "variable.trigger.tiktok_gift.diamonds",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_gift.diamonds",
      "label": "{diamonds}",
      "category": "Event variables",
      "summary": "Finalized gift diamond count, or 0.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_gift.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_gift"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{diamonds}"
        }
      ],
      "details": {
        "syntax": "{diamonds}",
        "canonicalKey": "diamonds",
        "aliases": [],
        "producer": "trigger.tiktok_gift",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": 0,
        "behavior": "Finalized gift/streak only; optional gift name is exact case-insensitive. Count and diamond thresholds both apply."
      }
    },
    {
      "id": "variable.trigger.tiktok_gift.amount",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_gift.amount",
      "label": "{amount}",
      "category": "Event variables",
      "summary": "Provider-normalized gift amount or Super Chat amount; do not assume cross-provider currency equivalence.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_gift.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_gift"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{amount}"
        }
      ],
      "details": {
        "syntax": "{amount}",
        "canonicalKey": "amount",
        "aliases": [],
        "producer": "trigger.tiktok_gift",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": 0,
        "behavior": "Finalized gift/streak only; optional gift name is exact case-insensitive. Count and diamond thresholds both apply."
      }
    },
    {
      "id": "trigger.tiktok_share",
      "kind": "trigger",
      "runtimeKey": "tiktok_share",
      "label": "TikTok share",
      "category": "When",
      "summary": "Fires when a viewer shares the TikTok LIVE.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected supported event provider; enabled automation and matching filters.",
        "inboundProviders": [
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_share"
        },
        {
          "path": "src/features/automation-provider-capabilities.js",
          "symbol": "AUTOMATION_TRIGGER_PLATFORMS.tiktok_share"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "variable.trigger.tiktok_share.user",
        "variable.trigger.tiktok_share.username",
        "variable.trigger.tiktok_share.displayName",
        "variable.trigger.tiktok_share.userId",
        "variable.trigger.tiktok_share.eventId",
        "variable.trigger.tiktok_share.roomId",
        "variable.trigger.tiktok_share.shareCount",
        "context.automation"
      ],
      "examples": [
        {
          "purpose": "Trigger selection and filter defaults; supply a real target/pattern when required.",
          "format": "configuration",
          "value": {
            "triggerType": "tiktok_share",
            "triggerPlatform": "tiktok",
            "triggerFilters": {}
          }
        }
      ],
      "details": {
        "behavior": "One mapped share event; shareCount is the provider value or 0.",
        "filters": [],
        "variableIds": [
          "variable.trigger.tiktok_share.user",
          "variable.trigger.tiktok_share.username",
          "variable.trigger.tiktok_share.displayName",
          "variable.trigger.tiktok_share.userId",
          "variable.trigger.tiktok_share.eventId",
          "variable.trigger.tiktok_share.roomId",
          "variable.trigger.tiktok_share.shareCount"
        ],
        "cooldown": "Automation cooldownSec defaults 0; keyed by automation ID and event platform; held in memory until restart.",
        "delay": "No additional trigger delay.",
        "ui": {
          "path": [
            "Bot",
            "Automations",
            "+ New",
            "When"
          ],
          "initialFields": [],
          "steps": [
            "Choose Trigger category: Platform events.",
            "Choose the incoming Platform first.",
            "Choose Trigger event: TikTok share.",
            "Fill the Trigger filters below, set Cooldown (seconds), then open Where and choose a supported Platform.",
            "Open Do, add actions, then Create Automation or Save Changes."
          ]
        }
      }
    },
    {
      "id": "variable.trigger.tiktok_share.user",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_share.user",
      "label": "{user}",
      "category": "Event variables",
      "summary": "Viewer display name/username supplied by this event; outgoing raids use destination identity.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_share.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_share"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{user}"
        }
      ],
      "details": {
        "syntax": "{user}",
        "canonicalKey": "user",
        "aliases": [],
        "producer": "trigger.tiktok_share",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "One mapped share event; shareCount is the provider value or 0."
      }
    },
    {
      "id": "variable.trigger.tiktok_share.username",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_share.username",
      "label": "{username}",
      "category": "Event variables",
      "summary": "Normalized or provider-supplied event username, not an arbitrary command argument.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_share.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_share"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{username}"
        }
      ],
      "details": {
        "syntax": "{username}",
        "canonicalKey": "username",
        "aliases": [],
        "producer": "trigger.tiktok_share",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "One mapped share event; shareCount is the provider value or 0."
      }
    },
    {
      "id": "variable.trigger.tiktok_share.displayName",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_share.displayName",
      "label": "{displayName}",
      "category": "Event variables",
      "summary": "Event display name with username fallback.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_share.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_share"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{displayName}"
        }
      ],
      "details": {
        "syntax": "{displayName}",
        "canonicalKey": "displayName",
        "aliases": [],
        "producer": "trigger.tiktok_share",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "One mapped share event; shareCount is the provider value or 0."
      }
    },
    {
      "id": "variable.trigger.tiktok_share.userId",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_share.userId",
      "label": "{userId}",
      "category": "Event variables",
      "summary": "Provider user ID when supplied; otherwise empty.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_share.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_share"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{userId}"
        }
      ],
      "details": {
        "syntax": "{userId}",
        "canonicalKey": "userId",
        "aliases": [],
        "producer": "trigger.tiktok_share",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "One mapped share event; shareCount is the provider value or 0."
      }
    },
    {
      "id": "variable.trigger.tiktok_share.eventId",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_share.eventId",
      "label": "{eventId}",
      "category": "Event variables",
      "summary": "Event/message identity when supplied; otherwise empty.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_share.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_share"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{eventId}"
        }
      ],
      "details": {
        "syntax": "{eventId}",
        "canonicalKey": "eventId",
        "aliases": [],
        "producer": "trigger.tiktok_share",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "One mapped share event; shareCount is the provider value or 0."
      }
    },
    {
      "id": "variable.trigger.tiktok_share.roomId",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_share.roomId",
      "label": "{roomId}",
      "category": "Event variables",
      "summary": "Provider room identifier when supplied; otherwise empty.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_share.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_share"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{roomId}"
        }
      ],
      "details": {
        "syntax": "{roomId}",
        "canonicalKey": "roomId",
        "aliases": [],
        "producer": "trigger.tiktok_share",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "One mapped share event; shareCount is the provider value or 0."
      }
    },
    {
      "id": "variable.trigger.tiktok_share.shareCount",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_share.shareCount",
      "label": "{shareCount}",
      "category": "Event variables",
      "summary": "TikTok share counter supplied by event, or 0.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_share.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_share"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{shareCount}"
        }
      ],
      "details": {
        "syntax": "{shareCount}",
        "canonicalKey": "shareCount",
        "aliases": [],
        "producer": "trigger.tiktok_share",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": 0,
        "behavior": "One mapped share event; shareCount is the provider value or 0."
      }
    },
    {
      "id": "trigger.tiktok_like",
      "kind": "trigger",
      "runtimeKey": "tiktok_like",
      "label": "TikTok likes",
      "category": "When",
      "summary": "Fires for a TikTok like batch.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected supported event provider; enabled automation and matching filters.",
        "inboundProviders": [
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_like"
        },
        {
          "path": "src/features/automation-provider-capabilities.js",
          "symbol": "AUTOMATION_TRIGGER_PLATFORMS.tiktok_like"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "variable.trigger.tiktok_like.user",
        "variable.trigger.tiktok_like.username",
        "variable.trigger.tiktok_like.displayName",
        "variable.trigger.tiktok_like.userId",
        "variable.trigger.tiktok_like.eventId",
        "variable.trigger.tiktok_like.roomId",
        "variable.trigger.tiktok_like.likes",
        "variable.trigger.tiktok_like.totalLikes",
        "context.automation"
      ],
      "examples": [
        {
          "purpose": "Trigger selection and filter defaults; supply a real target/pattern when required.",
          "format": "configuration",
          "value": {
            "triggerType": "tiktok_like",
            "triggerPlatform": "tiktok",
            "triggerFilters": {
              "min_likes": 1
            }
          }
        }
      ],
      "details": {
        "behavior": "Match a like batch with likes >= min_likes (default 1); totalLikes is a separate stream counter.",
        "filters": [
          {
            "key": "min_likes",
            "type": "number",
            "label": "Minimum likes in batch",
            "min": 1,
            "default": 1
          }
        ],
        "variableIds": [
          "variable.trigger.tiktok_like.user",
          "variable.trigger.tiktok_like.username",
          "variable.trigger.tiktok_like.displayName",
          "variable.trigger.tiktok_like.userId",
          "variable.trigger.tiktok_like.eventId",
          "variable.trigger.tiktok_like.roomId",
          "variable.trigger.tiktok_like.likes",
          "variable.trigger.tiktok_like.totalLikes"
        ],
        "cooldown": "Automation cooldownSec defaults 0; keyed by automation ID and event platform; held in memory until restart.",
        "delay": "No additional trigger delay.",
        "ui": {
          "path": [
            "Bot",
            "Automations",
            "+ New",
            "When"
          ],
          "initialFields": [],
          "steps": [
            "Choose Trigger category: Platform events.",
            "Choose the incoming Platform first.",
            "Choose Trigger event: TikTok likes.",
            "Fill the Trigger filters below, set Cooldown (seconds), then open Where and choose a supported Platform.",
            "Open Do, add actions, then Create Automation or Save Changes."
          ]
        }
      }
    },
    {
      "id": "variable.trigger.tiktok_like.user",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_like.user",
      "label": "{user}",
      "category": "Event variables",
      "summary": "Viewer display name/username supplied by this event; outgoing raids use destination identity.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_like.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_like"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{user}"
        }
      ],
      "details": {
        "syntax": "{user}",
        "canonicalKey": "user",
        "aliases": [],
        "producer": "trigger.tiktok_like",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Match a like batch with likes >= min_likes (default 1); totalLikes is a separate stream counter."
      }
    },
    {
      "id": "variable.trigger.tiktok_like.username",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_like.username",
      "label": "{username}",
      "category": "Event variables",
      "summary": "Normalized or provider-supplied event username, not an arbitrary command argument.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_like.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_like"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{username}"
        }
      ],
      "details": {
        "syntax": "{username}",
        "canonicalKey": "username",
        "aliases": [],
        "producer": "trigger.tiktok_like",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Match a like batch with likes >= min_likes (default 1); totalLikes is a separate stream counter."
      }
    },
    {
      "id": "variable.trigger.tiktok_like.displayName",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_like.displayName",
      "label": "{displayName}",
      "category": "Event variables",
      "summary": "Event display name with username fallback.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_like.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_like"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{displayName}"
        }
      ],
      "details": {
        "syntax": "{displayName}",
        "canonicalKey": "displayName",
        "aliases": [],
        "producer": "trigger.tiktok_like",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Match a like batch with likes >= min_likes (default 1); totalLikes is a separate stream counter."
      }
    },
    {
      "id": "variable.trigger.tiktok_like.userId",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_like.userId",
      "label": "{userId}",
      "category": "Event variables",
      "summary": "Provider user ID when supplied; otherwise empty.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_like.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_like"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{userId}"
        }
      ],
      "details": {
        "syntax": "{userId}",
        "canonicalKey": "userId",
        "aliases": [],
        "producer": "trigger.tiktok_like",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Match a like batch with likes >= min_likes (default 1); totalLikes is a separate stream counter."
      }
    },
    {
      "id": "variable.trigger.tiktok_like.eventId",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_like.eventId",
      "label": "{eventId}",
      "category": "Event variables",
      "summary": "Event/message identity when supplied; otherwise empty.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_like.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_like"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{eventId}"
        }
      ],
      "details": {
        "syntax": "{eventId}",
        "canonicalKey": "eventId",
        "aliases": [],
        "producer": "trigger.tiktok_like",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Match a like batch with likes >= min_likes (default 1); totalLikes is a separate stream counter."
      }
    },
    {
      "id": "variable.trigger.tiktok_like.roomId",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_like.roomId",
      "label": "{roomId}",
      "category": "Event variables",
      "summary": "Provider room identifier when supplied; otherwise empty.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_like.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_like"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{roomId}"
        }
      ],
      "details": {
        "syntax": "{roomId}",
        "canonicalKey": "roomId",
        "aliases": [],
        "producer": "trigger.tiktok_like",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Match a like batch with likes >= min_likes (default 1); totalLikes is a separate stream counter."
      }
    },
    {
      "id": "variable.trigger.tiktok_like.likes",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_like.likes",
      "label": "{likes}",
      "category": "Event variables",
      "summary": "Likes in the current TikTok batch, or 0.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_like.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_like"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{likes}"
        }
      ],
      "details": {
        "syntax": "{likes}",
        "canonicalKey": "likes",
        "aliases": [],
        "producer": "trigger.tiktok_like",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": 0,
        "behavior": "Match a like batch with likes >= min_likes (default 1); totalLikes is a separate stream counter."
      }
    },
    {
      "id": "variable.trigger.tiktok_like.totalLikes",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_like.totalLikes",
      "label": "{totalLikes}",
      "category": "Event variables",
      "summary": "TikTok stream total likes, or 0.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_like.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_like"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{totalLikes}"
        }
      ],
      "details": {
        "syntax": "{totalLikes}",
        "canonicalKey": "totalLikes",
        "aliases": [],
        "producer": "trigger.tiktok_like",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": 0,
        "behavior": "Match a like batch with likes >= min_likes (default 1); totalLikes is a separate stream counter."
      }
    },
    {
      "id": "trigger.tiktok_question",
      "kind": "trigger",
      "runtimeKey": "tiktok_question",
      "label": "TikTok question",
      "category": "When",
      "summary": "Fires when TikTok emits a viewer question.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected supported event provider; enabled automation and matching filters.",
        "inboundProviders": [
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_question"
        },
        {
          "path": "src/features/automation-provider-capabilities.js",
          "symbol": "AUTOMATION_TRIGGER_PLATFORMS.tiktok_question"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "variable.trigger.tiktok_question.user",
        "variable.trigger.tiktok_question.username",
        "variable.trigger.tiktok_question.displayName",
        "variable.trigger.tiktok_question.userId",
        "variable.trigger.tiktok_question.eventId",
        "variable.trigger.tiktok_question.roomId",
        "variable.trigger.tiktok_question.question",
        "variable.trigger.tiktok_question.message",
        "context.automation"
      ],
      "examples": [
        {
          "purpose": "Trigger selection and filter defaults; supply a real target/pattern when required.",
          "format": "configuration",
          "value": {
            "triggerType": "tiktok_question",
            "triggerPlatform": "tiktok",
            "triggerFilters": {}
          }
        }
      ],
      "details": {
        "behavior": "Mapped viewer question; both question and message refer to its question text.",
        "filters": [],
        "variableIds": [
          "variable.trigger.tiktok_question.user",
          "variable.trigger.tiktok_question.username",
          "variable.trigger.tiktok_question.displayName",
          "variable.trigger.tiktok_question.userId",
          "variable.trigger.tiktok_question.eventId",
          "variable.trigger.tiktok_question.roomId",
          "variable.trigger.tiktok_question.question",
          "variable.trigger.tiktok_question.message"
        ],
        "cooldown": "Automation cooldownSec defaults 0; keyed by automation ID and event platform; held in memory until restart.",
        "delay": "No additional trigger delay.",
        "ui": {
          "path": [
            "Bot",
            "Automations",
            "+ New",
            "When"
          ],
          "initialFields": [],
          "steps": [
            "Choose Trigger category: Platform events.",
            "Choose the incoming Platform first.",
            "Choose Trigger event: TikTok question.",
            "Fill the Trigger filters below, set Cooldown (seconds), then open Where and choose a supported Platform.",
            "Open Do, add actions, then Create Automation or Save Changes."
          ]
        }
      }
    },
    {
      "id": "variable.trigger.tiktok_question.user",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_question.user",
      "label": "{user}",
      "category": "Event variables",
      "summary": "Viewer display name/username supplied by this event; outgoing raids use destination identity.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_question.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_question"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{user}"
        }
      ],
      "details": {
        "syntax": "{user}",
        "canonicalKey": "user",
        "aliases": [],
        "producer": "trigger.tiktok_question",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Mapped viewer question; both question and message refer to its question text."
      }
    },
    {
      "id": "variable.trigger.tiktok_question.username",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_question.username",
      "label": "{username}",
      "category": "Event variables",
      "summary": "Normalized or provider-supplied event username, not an arbitrary command argument.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_question.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_question"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{username}"
        }
      ],
      "details": {
        "syntax": "{username}",
        "canonicalKey": "username",
        "aliases": [],
        "producer": "trigger.tiktok_question",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Mapped viewer question; both question and message refer to its question text."
      }
    },
    {
      "id": "variable.trigger.tiktok_question.displayName",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_question.displayName",
      "label": "{displayName}",
      "category": "Event variables",
      "summary": "Event display name with username fallback.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_question.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_question"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{displayName}"
        }
      ],
      "details": {
        "syntax": "{displayName}",
        "canonicalKey": "displayName",
        "aliases": [],
        "producer": "trigger.tiktok_question",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Mapped viewer question; both question and message refer to its question text."
      }
    },
    {
      "id": "variable.trigger.tiktok_question.userId",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_question.userId",
      "label": "{userId}",
      "category": "Event variables",
      "summary": "Provider user ID when supplied; otherwise empty.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_question.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_question"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{userId}"
        }
      ],
      "details": {
        "syntax": "{userId}",
        "canonicalKey": "userId",
        "aliases": [],
        "producer": "trigger.tiktok_question",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Mapped viewer question; both question and message refer to its question text."
      }
    },
    {
      "id": "variable.trigger.tiktok_question.eventId",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_question.eventId",
      "label": "{eventId}",
      "category": "Event variables",
      "summary": "Event/message identity when supplied; otherwise empty.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_question.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_question"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{eventId}"
        }
      ],
      "details": {
        "syntax": "{eventId}",
        "canonicalKey": "eventId",
        "aliases": [],
        "producer": "trigger.tiktok_question",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Mapped viewer question; both question and message refer to its question text."
      }
    },
    {
      "id": "variable.trigger.tiktok_question.roomId",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_question.roomId",
      "label": "{roomId}",
      "category": "Event variables",
      "summary": "Provider room identifier when supplied; otherwise empty.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_question.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_question"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{roomId}"
        }
      ],
      "details": {
        "syntax": "{roomId}",
        "canonicalKey": "roomId",
        "aliases": [],
        "producer": "trigger.tiktok_question",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Mapped viewer question; both question and message refer to its question text."
      }
    },
    {
      "id": "variable.trigger.tiktok_question.question",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_question.question",
      "label": "{question}",
      "category": "Event variables",
      "summary": "TikTok viewer question text.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_question.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_question"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{question}"
        }
      ],
      "details": {
        "syntax": "{question}",
        "canonicalKey": "question",
        "aliases": [],
        "producer": "trigger.tiktok_question",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Mapped viewer question; both question and message refer to its question text."
      }
    },
    {
      "id": "variable.trigger.tiktok_question.message",
      "kind": "variable",
      "runtimeKey": "trigger.tiktok_question.message",
      "label": "{message}",
      "category": "Event variables",
      "summary": "Event text; reward redemptions use viewer input, TikTok questions use the question text.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.tiktok_question.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.tiktok_question"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{message}"
        }
      ],
      "details": {
        "syntax": "{message}",
        "canonicalKey": "message",
        "aliases": [],
        "producer": "trigger.tiktok_question",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Mapped viewer question; both question and message refer to its question text."
      }
    },
    {
      "id": "trigger.gift_sub",
      "kind": "trigger",
      "runtimeKey": "gift_sub",
      "label": "Gift subscription",
      "category": "When",
      "summary": "Fires when subs are gifted to the community.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected supported event provider; enabled automation and matching filters.",
        "inboundProviders": [
          "twitch",
          "youtube",
          "kick"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.gift_sub"
        },
        {
          "path": "src/features/automation-provider-capabilities.js",
          "symbol": "AUTOMATION_TRIGGER_PLATFORMS.gift_sub"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "variable.trigger.gift_sub.gifter",
        "variable.trigger.gift_sub.count",
        "variable.trigger.gift_sub.tier",
        "variable.trigger.gift_sub.user",
        "context.automation"
      ],
      "examples": [
        {
          "purpose": "Trigger selection and filter defaults; supply a real target/pattern when required.",
          "format": "configuration",
          "value": {
            "triggerType": "gift_sub",
            "triggerPlatform": "twitch",
            "triggerFilters": {
              "min_count": 0
            }
          }
        }
      ],
      "details": {
        "behavior": "Gift count must meet minimum; missing count is 1. TikTok gifted subscriptions use Subscription instead.",
        "filters": [
          {
            "key": "min_count",
            "type": "number",
            "label": "Minimum gift count (0 = any)",
            "min": 0,
            "default": 0
          }
        ],
        "variableIds": [
          "variable.trigger.gift_sub.gifter",
          "variable.trigger.gift_sub.count",
          "variable.trigger.gift_sub.tier",
          "variable.trigger.gift_sub.user"
        ],
        "cooldown": "Automation cooldownSec defaults 0; keyed by automation ID and event platform; held in memory until restart.",
        "delay": "No additional trigger delay.",
        "ui": {
          "path": [
            "Bot",
            "Automations",
            "+ New",
            "When"
          ],
          "initialFields": [],
          "steps": [
            "Choose Trigger category: Monetization.",
            "Choose Trigger event: Gift subscription.",
            "Fill the Trigger filters below, set Cooldown (seconds), then open Where and choose a supported Platform.",
            "Open Do, add actions, then Create Automation or Save Changes."
          ]
        }
      }
    },
    {
      "id": "variable.trigger.gift_sub.gifter",
      "kind": "variable",
      "runtimeKey": "trigger.gift_sub.gifter",
      "label": "{gifter}",
      "category": "Event variables",
      "summary": "Gift subscription sender username.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.gift_sub.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.gift_sub"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{gifter}"
        }
      ],
      "details": {
        "syntax": "{gifter}",
        "canonicalKey": "gifter",
        "aliases": [],
        "producer": "trigger.gift_sub",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": null,
        "behavior": "Gift count must meet minimum; missing count is 1. TikTok gifted subscriptions use Subscription instead."
      }
    },
    {
      "id": "variable.trigger.gift_sub.count",
      "kind": "variable",
      "runtimeKey": "trigger.gift_sub.count",
      "label": "{count}",
      "category": "Event variables",
      "summary": "Subscription/gift count from the event; extraction defaults to 1.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.gift_sub.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.gift_sub"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{count}"
        }
      ],
      "details": {
        "syntax": "{count}",
        "canonicalKey": "count",
        "aliases": [],
        "producer": "trigger.gift_sub",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": 1,
        "behavior": "Gift count must meet minimum; missing count is 1. TikTok gifted subscriptions use Subscription instead."
      }
    },
    {
      "id": "variable.trigger.gift_sub.tier",
      "kind": "variable",
      "runtimeKey": "trigger.gift_sub.tier",
      "label": "{tier}",
      "category": "Event variables",
      "summary": "Provider subscription tier; missing value defaults to 1000.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.gift_sub.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.gift_sub"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{tier}"
        }
      ],
      "details": {
        "syntax": "{tier}",
        "canonicalKey": "tier",
        "aliases": [],
        "producer": "trigger.gift_sub",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "1000",
        "behavior": "Gift count must meet minimum; missing count is 1. TikTok gifted subscriptions use Subscription instead."
      }
    },
    {
      "id": "variable.trigger.gift_sub.user",
      "kind": "variable",
      "runtimeKey": "trigger.gift_sub.user",
      "label": "{user}",
      "category": "Event variables",
      "summary": "Viewer display name/username supplied by this event; outgoing raids use destination identity.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.gift_sub.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.gift_sub"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{user}"
        }
      ],
      "details": {
        "syntax": "{user}",
        "canonicalKey": "user",
        "aliases": [],
        "producer": "trigger.gift_sub",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": null,
        "behavior": "Gift count must meet minimum; missing count is 1. TikTok gifted subscriptions use Subscription instead."
      }
    },
    {
      "id": "trigger.cheer",
      "kind": "trigger",
      "runtimeKey": "cheer",
      "label": "Bits / KICKs",
      "category": "When",
      "summary": "Fires when a viewer sends Twitch bits or Kick KICKs.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected supported event provider; enabled automation and matching filters.",
        "inboundProviders": [
          "twitch",
          "kick"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.cheer"
        },
        {
          "path": "src/features/automation-provider-capabilities.js",
          "symbol": "AUTOMATION_TRIGGER_PLATFORMS.cheer"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "variable.trigger.cheer.user",
        "variable.trigger.cheer.bits",
        "variable.trigger.cheer.message",
        "context.automation"
      ],
      "examples": [
        {
          "purpose": "Trigger selection and filter defaults; supply a real target/pattern when required.",
          "format": "configuration",
          "value": {
            "triggerType": "cheer",
            "triggerPlatform": "twitch",
            "triggerFilters": {
              "min_bits": 0
            }
          }
        }
      ],
      "details": {
        "behavior": "Twitch bits or Kick KICKs count must meet min_bits; the shared variable is named bits.",
        "filters": [
          {
            "key": "min_bits",
            "type": "number",
            "label": "Minimum amount (0 = any)",
            "min": 0,
            "default": 0
          }
        ],
        "variableIds": [
          "variable.trigger.cheer.user",
          "variable.trigger.cheer.bits",
          "variable.trigger.cheer.message"
        ],
        "cooldown": "Automation cooldownSec defaults 0; keyed by automation ID and event platform; held in memory until restart.",
        "delay": "No additional trigger delay.",
        "ui": {
          "path": [
            "Bot",
            "Automations",
            "+ New",
            "When"
          ],
          "initialFields": [],
          "steps": [
            "Choose Trigger category: Monetization.",
            "Choose Trigger event: Bits / KICKs.",
            "Fill the Trigger filters below, set Cooldown (seconds), then open Where and choose a supported Platform.",
            "Open Do, add actions, then Create Automation or Save Changes."
          ]
        }
      }
    },
    {
      "id": "variable.trigger.cheer.user",
      "kind": "variable",
      "runtimeKey": "trigger.cheer.user",
      "label": "{user}",
      "category": "Event variables",
      "summary": "Viewer display name/username supplied by this event; outgoing raids use destination identity.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.cheer.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.cheer"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{user}"
        }
      ],
      "details": {
        "syntax": "{user}",
        "canonicalKey": "user",
        "aliases": [],
        "producer": "trigger.cheer",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": null,
        "behavior": "Twitch bits or Kick KICKs count must meet min_bits; the shared variable is named bits."
      }
    },
    {
      "id": "variable.trigger.cheer.bits",
      "kind": "variable",
      "runtimeKey": "trigger.cheer.bits",
      "label": "{bits}",
      "category": "Event variables",
      "summary": "Twitch bits or Kick KICKs amount, or 0.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.cheer.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.cheer"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{bits}"
        }
      ],
      "details": {
        "syntax": "{bits}",
        "canonicalKey": "bits",
        "aliases": [],
        "producer": "trigger.cheer",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": 0,
        "behavior": "Twitch bits or Kick KICKs count must meet min_bits; the shared variable is named bits."
      }
    },
    {
      "id": "variable.trigger.cheer.message",
      "kind": "variable",
      "runtimeKey": "trigger.cheer.message",
      "label": "{message}",
      "category": "Event variables",
      "summary": "Event text; reward redemptions use viewer input, TikTok questions use the question text.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.cheer.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.cheer"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{message}"
        }
      ],
      "details": {
        "syntax": "{message}",
        "canonicalKey": "message",
        "aliases": [],
        "producer": "trigger.cheer",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Twitch bits or Kick KICKs count must meet min_bits; the shared variable is named bits."
      }
    },
    {
      "id": "trigger.raid",
      "kind": "trigger",
      "runtimeKey": "raid",
      "label": "Incoming raid",
      "category": "When",
      "summary": "Fires when another streamer raids the channel.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected supported event provider; enabled automation and matching filters.",
        "inboundProviders": [
          "twitch",
          "kick"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.raid"
        },
        {
          "path": "src/features/automation-provider-capabilities.js",
          "symbol": "AUTOMATION_TRIGGER_PLATFORMS.raid"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "variable.trigger.raid.user",
        "variable.trigger.raid.target",
        "variable.trigger.raid.target.url",
        "variable.trigger.raid.target.game",
        "variable.trigger.raid.target.title",
        "variable.trigger.raid.viewers",
        "variable.trigger.raid.username",
        "variable.trigger.raid.displayName",
        "variable.trigger.raid.userId",
        "variable.trigger.raid.eventId",
        "variable.trigger.raid.roomId",
        "context.automation"
      ],
      "examples": [
        {
          "purpose": "Trigger selection and filter defaults; supply a real target/pattern when required.",
          "format": "configuration",
          "value": {
            "triggerType": "raid",
            "triggerPlatform": "twitch",
            "triggerFilters": {
              "min_viewers": 0,
              "upcoming_ad_within_minutes": 0
            }
          }
        }
      ],
      "details": {
        "behavior": "Incoming raid viewers must meet minimum. Positive upcoming-ad window applies only to Twitch with a known eligible schedule. target is the raider, not the receiving broadcaster.",
        "filters": [
          {
            "key": "min_viewers",
            "type": "number",
            "label": "Minimum viewers (0 = any)",
            "min": 0,
            "default": 0
          },
          {
            "key": "upcoming_ad_within_minutes",
            "type": "number",
            "label": "Only if next Twitch ad is within minutes (0 = off)",
            "min": 0,
            "max": 180,
            "default": 0
          }
        ],
        "variableIds": [
          "variable.trigger.raid.user",
          "variable.trigger.raid.target",
          "variable.trigger.raid.target.url",
          "variable.trigger.raid.target.game",
          "variable.trigger.raid.target.title",
          "variable.trigger.raid.viewers",
          "variable.trigger.raid.username",
          "variable.trigger.raid.displayName",
          "variable.trigger.raid.userId",
          "variable.trigger.raid.eventId",
          "variable.trigger.raid.roomId"
        ],
        "cooldown": "Automation cooldownSec defaults 0; keyed by automation ID and event platform; held in memory until restart.",
        "delay": "No additional trigger delay.",
        "ui": {
          "path": [
            "Bot",
            "Automations",
            "+ New",
            "When"
          ],
          "initialFields": [],
          "steps": [
            "Choose Trigger category: Raids.",
            "Choose Trigger event: Incoming raid.",
            "Fill the Trigger filters below, set Cooldown (seconds), then open Where and choose a supported Platform.",
            "Open Do, add actions, then Create Automation or Save Changes."
          ]
        }
      }
    },
    {
      "id": "variable.trigger.raid.user",
      "kind": "variable",
      "runtimeKey": "trigger.raid.user",
      "label": "{user}",
      "category": "Event variables",
      "summary": "Viewer display name/username supplied by this event; outgoing raids use destination identity.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.raid.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.raid"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{user}"
        }
      ],
      "details": {
        "syntax": "{user}",
        "canonicalKey": "user",
        "aliases": [],
        "producer": "trigger.raid",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Incoming raid viewers must meet minimum. Positive upcoming-ad window applies only to Twitch with a known eligible schedule. target is the raider, not the receiving broadcaster."
      }
    },
    {
      "id": "variable.trigger.raid.target",
      "kind": "variable",
      "runtimeKey": "trigger.raid.target",
      "label": "{target}",
      "category": "Event variables",
      "summary": "Raider username for incoming raids; destination login for outgoing raids.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.raid.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.raid"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{target}"
        }
      ],
      "details": {
        "syntax": "{target}",
        "canonicalKey": "target",
        "aliases": [],
        "producer": "trigger.raid",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Incoming raid viewers must meet minimum. Positive upcoming-ad window applies only to Twitch with a known eligible schedule. target is the raider, not the receiving broadcaster."
      }
    },
    {
      "id": "variable.trigger.raid.target.url",
      "kind": "variable",
      "runtimeKey": "trigger.raid.target.url",
      "label": "{target.url}",
      "category": "Event variables",
      "summary": "Profile URL for the target username on the current platform",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.raid.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.raid"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{target.url}"
        }
      ],
      "details": {
        "syntax": "{target.url}",
        "canonicalKey": "target.url",
        "aliases": [],
        "producer": "trigger.raid",
        "lifetime": "Current action sequence.",
        "resolution": "Advertised for this trigger; resolved by global variable engine after event substitution.",
        "emptyEventFallback": null,
        "behavior": "Incoming raid viewers must meet minimum. Positive upcoming-ad window applies only to Twitch with a known eligible schedule. target is the raider, not the receiving broadcaster."
      }
    },
    {
      "id": "variable.trigger.raid.target.game",
      "kind": "variable",
      "runtimeKey": "trigger.raid.target.game",
      "label": "{target.game}",
      "category": "Event variables",
      "summary": "Target channel category/game on the current platform",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.raid.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.raid"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{target.game}"
        }
      ],
      "details": {
        "syntax": "{target.game}",
        "canonicalKey": "target.game",
        "aliases": [],
        "producer": "trigger.raid",
        "lifetime": "Current action sequence.",
        "resolution": "Advertised for this trigger; resolved by global variable engine after event substitution.",
        "emptyEventFallback": null,
        "behavior": "Incoming raid viewers must meet minimum. Positive upcoming-ad window applies only to Twitch with a known eligible schedule. target is the raider, not the receiving broadcaster."
      }
    },
    {
      "id": "variable.trigger.raid.target.title",
      "kind": "variable",
      "runtimeKey": "trigger.raid.target.title",
      "label": "{target.title}",
      "category": "Event variables",
      "summary": "Target channel title on the current platform",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.raid.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.raid"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{target.title}"
        }
      ],
      "details": {
        "syntax": "{target.title}",
        "canonicalKey": "target.title",
        "aliases": [],
        "producer": "trigger.raid",
        "lifetime": "Current action sequence.",
        "resolution": "Advertised for this trigger; resolved by global variable engine after event substitution.",
        "emptyEventFallback": null,
        "behavior": "Incoming raid viewers must meet minimum. Positive upcoming-ad window applies only to Twitch with a known eligible schedule. target is the raider, not the receiving broadcaster."
      }
    },
    {
      "id": "variable.trigger.raid.viewers",
      "kind": "variable",
      "runtimeKey": "trigger.raid.viewers",
      "label": "{viewers}",
      "category": "Event variables",
      "summary": "Incoming raid size or outgoing raid viewer count, or 0.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.raid.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.raid"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{viewers}"
        }
      ],
      "details": {
        "syntax": "{viewers}",
        "canonicalKey": "viewers",
        "aliases": [],
        "producer": "trigger.raid",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": 0,
        "behavior": "Incoming raid viewers must meet minimum. Positive upcoming-ad window applies only to Twitch with a known eligible schedule. target is the raider, not the receiving broadcaster."
      }
    },
    {
      "id": "variable.trigger.raid.username",
      "kind": "variable",
      "runtimeKey": "trigger.raid.username",
      "label": "{username}",
      "category": "Event variables",
      "summary": "Normalized or provider-supplied event username, not an arbitrary command argument.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.raid.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.raid"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{username}"
        }
      ],
      "details": {
        "syntax": "{username}",
        "canonicalKey": "username",
        "aliases": [],
        "producer": "trigger.raid",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Incoming raid viewers must meet minimum. Positive upcoming-ad window applies only to Twitch with a known eligible schedule. target is the raider, not the receiving broadcaster."
      }
    },
    {
      "id": "variable.trigger.raid.displayName",
      "kind": "variable",
      "runtimeKey": "trigger.raid.displayName",
      "label": "{displayName}",
      "category": "Event variables",
      "summary": "Event display name with username fallback.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.raid.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.raid"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{displayName}"
        }
      ],
      "details": {
        "syntax": "{displayName}",
        "canonicalKey": "displayName",
        "aliases": [],
        "producer": "trigger.raid",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Incoming raid viewers must meet minimum. Positive upcoming-ad window applies only to Twitch with a known eligible schedule. target is the raider, not the receiving broadcaster."
      }
    },
    {
      "id": "variable.trigger.raid.userId",
      "kind": "variable",
      "runtimeKey": "trigger.raid.userId",
      "label": "{userId}",
      "category": "Event variables",
      "summary": "Provider user ID when supplied; otherwise empty.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.raid.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.raid"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{userId}"
        }
      ],
      "details": {
        "syntax": "{userId}",
        "canonicalKey": "userId",
        "aliases": [],
        "producer": "trigger.raid",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Incoming raid viewers must meet minimum. Positive upcoming-ad window applies only to Twitch with a known eligible schedule. target is the raider, not the receiving broadcaster."
      }
    },
    {
      "id": "variable.trigger.raid.eventId",
      "kind": "variable",
      "runtimeKey": "trigger.raid.eventId",
      "label": "{eventId}",
      "category": "Event variables",
      "summary": "Event/message identity when supplied; otherwise empty.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.raid.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.raid"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{eventId}"
        }
      ],
      "details": {
        "syntax": "{eventId}",
        "canonicalKey": "eventId",
        "aliases": [],
        "producer": "trigger.raid",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Incoming raid viewers must meet minimum. Positive upcoming-ad window applies only to Twitch with a known eligible schedule. target is the raider, not the receiving broadcaster."
      }
    },
    {
      "id": "variable.trigger.raid.roomId",
      "kind": "variable",
      "runtimeKey": "trigger.raid.roomId",
      "label": "{roomId}",
      "category": "Event variables",
      "summary": "Provider room identifier when supplied; otherwise empty.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.raid.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.raid"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{roomId}"
        }
      ],
      "details": {
        "syntax": "{roomId}",
        "canonicalKey": "roomId",
        "aliases": [],
        "producer": "trigger.raid",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Incoming raid viewers must meet minimum. Positive upcoming-ad window applies only to Twitch with a known eligible schedule. target is the raider, not the receiving broadcaster."
      }
    },
    {
      "id": "trigger.raid_started",
      "kind": "trigger",
      "runtimeKey": "raid_started",
      "label": "Raid started",
      "category": "When",
      "summary": "Fires once when the broadcaster successfully starts an outgoing raid through SheevChat.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected supported event provider; enabled automation and matching filters.",
        "inboundProviders": [
          "twitch",
          "kick"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.raid_started"
        },
        {
          "path": "src/features/automation-provider-capabilities.js",
          "symbol": "AUTOMATION_TRIGGER_PLATFORMS.raid_started"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "variable.trigger.raid_started.target",
        "variable.trigger.raid_started.targetDisplayName",
        "variable.trigger.raid_started.targetId",
        "variable.trigger.raid_started.viewers",
        "variable.trigger.raid_started.user",
        "variable.trigger.raid_started.username",
        "context.automation"
      ],
      "examples": [
        {
          "purpose": "Trigger selection and filter defaults; supply a real target/pattern when required.",
          "format": "configuration",
          "value": {
            "triggerType": "raid_started",
            "triggerPlatform": "twitch",
            "triggerFilters": {}
          }
        }
      ],
      "details": {
        "behavior": "Emitted after SheevChat successfully starts an outgoing raid; not every raid initiated externally. Target identity describes the destination.",
        "filters": [],
        "variableIds": [
          "variable.trigger.raid_started.target",
          "variable.trigger.raid_started.targetDisplayName",
          "variable.trigger.raid_started.targetId",
          "variable.trigger.raid_started.viewers",
          "variable.trigger.raid_started.user",
          "variable.trigger.raid_started.username"
        ],
        "cooldown": "Automation cooldownSec defaults 0; keyed by automation ID and event platform; held in memory until restart.",
        "delay": "No additional trigger delay.",
        "ui": {
          "path": [
            "Bot",
            "Automations",
            "+ New",
            "When"
          ],
          "initialFields": [],
          "steps": [
            "Choose Trigger category: Raids.",
            "Choose Trigger event: Raid started.",
            "Fill the Trigger filters below, set Cooldown (seconds), then open Where and choose a supported Platform.",
            "Open Do, add actions, then Create Automation or Save Changes."
          ]
        }
      }
    },
    {
      "id": "variable.trigger.raid_started.target",
      "kind": "variable",
      "runtimeKey": "trigger.raid_started.target",
      "label": "{target}",
      "category": "Event variables",
      "summary": "Raider username for incoming raids; destination login for outgoing raids.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.raid_started.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.raid_started"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{target}"
        }
      ],
      "details": {
        "syntax": "{target}",
        "canonicalKey": "target",
        "aliases": [],
        "producer": "trigger.raid_started",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Emitted after SheevChat successfully starts an outgoing raid; not every raid initiated externally. Target identity describes the destination."
      }
    },
    {
      "id": "variable.trigger.raid_started.targetDisplayName",
      "kind": "variable",
      "runtimeKey": "trigger.raid_started.targetDisplayName",
      "label": "{targetDisplayName}",
      "category": "Event variables",
      "summary": "Outgoing raid destination display name with login fallback.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.raid_started.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.raid_started"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{targetDisplayName}"
        }
      ],
      "details": {
        "syntax": "{targetDisplayName}",
        "canonicalKey": "targetDisplayName",
        "aliases": [],
        "producer": "trigger.raid_started",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Emitted after SheevChat successfully starts an outgoing raid; not every raid initiated externally. Target identity describes the destination."
      }
    },
    {
      "id": "variable.trigger.raid_started.targetId",
      "kind": "variable",
      "runtimeKey": "trigger.raid_started.targetId",
      "label": "{targetId}",
      "category": "Event variables",
      "summary": "Outgoing raid destination provider ID.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.raid_started.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.raid_started"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{targetId}"
        }
      ],
      "details": {
        "syntax": "{targetId}",
        "canonicalKey": "targetId",
        "aliases": [],
        "producer": "trigger.raid_started",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Emitted after SheevChat successfully starts an outgoing raid; not every raid initiated externally. Target identity describes the destination."
      }
    },
    {
      "id": "variable.trigger.raid_started.viewers",
      "kind": "variable",
      "runtimeKey": "trigger.raid_started.viewers",
      "label": "{viewers}",
      "category": "Event variables",
      "summary": "Incoming raid size or outgoing raid viewer count, or 0.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.raid_started.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.raid_started"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{viewers}"
        }
      ],
      "details": {
        "syntax": "{viewers}",
        "canonicalKey": "viewers",
        "aliases": [],
        "producer": "trigger.raid_started",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": 0,
        "behavior": "Emitted after SheevChat successfully starts an outgoing raid; not every raid initiated externally. Target identity describes the destination."
      }
    },
    {
      "id": "variable.trigger.raid_started.user",
      "kind": "variable",
      "runtimeKey": "trigger.raid_started.user",
      "label": "{user}",
      "category": "Event variables",
      "summary": "Viewer display name/username supplied by this event; outgoing raids use destination identity.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.raid_started.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.raid_started"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{user}"
        }
      ],
      "details": {
        "syntax": "{user}",
        "canonicalKey": "user",
        "aliases": [],
        "producer": "trigger.raid_started",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Emitted after SheevChat successfully starts an outgoing raid; not every raid initiated externally. Target identity describes the destination."
      }
    },
    {
      "id": "variable.trigger.raid_started.username",
      "kind": "variable",
      "runtimeKey": "trigger.raid_started.username",
      "label": "{username}",
      "category": "Event variables",
      "summary": "Normalized or provider-supplied event username, not an arbitrary command argument.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.raid_started.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.raid_started"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{username}"
        }
      ],
      "details": {
        "syntax": "{username}",
        "canonicalKey": "username",
        "aliases": [],
        "producer": "trigger.raid_started",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Emitted after SheevChat successfully starts an outgoing raid; not every raid initiated externally. Target identity describes the destination."
      }
    },
    {
      "id": "trigger.channel_point_redeem",
      "kind": "trigger",
      "runtimeKey": "channel_point_redeem",
      "label": "Channel reward redemption",
      "category": "When",
      "summary": "Fires when a viewer redeems a Twitch channel point reward or Kick channel reward.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected supported event provider; enabled automation and matching filters.",
        "inboundProviders": [
          "twitch",
          "kick"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.channel_point_redeem"
        },
        {
          "path": "src/features/automation-provider-capabilities.js",
          "symbol": "AUTOMATION_TRIGGER_PLATFORMS.channel_point_redeem"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "variable.trigger.channel_point_redeem.user",
        "variable.trigger.channel_point_redeem.user.points",
        "variable.trigger.channel_point_redeem.user.pointsRank",
        "variable.trigger.channel_point_redeem.reward",
        "variable.trigger.channel_point_redeem.message",
        "variable.trigger.channel_point_redeem.username",
        "variable.trigger.channel_point_redeem.input",
        "context.automation"
      ],
      "examples": [
        {
          "purpose": "Trigger selection and filter defaults; supply a real target/pattern when required.",
          "format": "configuration",
          "value": {
            "triggerType": "channel_point_redeem",
            "triggerPlatform": "twitch",
            "triggerFilters": {
              "reward_id": ""
            }
          }
        }
      ],
      "details": {
        "behavior": "Blank reward accepts any mapped redemption; otherwise reward ID matches exactly. input/message are the viewer reward input.",
        "filters": [
          {
            "key": "reward_id",
            "type": "rewards_dropdown",
            "label": "Reward (blank = any reward)"
          }
        ],
        "variableIds": [
          "variable.trigger.channel_point_redeem.user",
          "variable.trigger.channel_point_redeem.user.points",
          "variable.trigger.channel_point_redeem.user.pointsRank",
          "variable.trigger.channel_point_redeem.reward",
          "variable.trigger.channel_point_redeem.message",
          "variable.trigger.channel_point_redeem.username",
          "variable.trigger.channel_point_redeem.input"
        ],
        "cooldown": "Automation cooldownSec defaults 0; keyed by automation ID and event platform; held in memory until restart.",
        "delay": "No additional trigger delay.",
        "ui": {
          "path": [
            "Bot",
            "Automations",
            "+ New",
            "When"
          ],
          "initialFields": [],
          "steps": [
            "Choose Trigger category: Platform events.",
            "Choose the incoming Platform first.",
            "Choose Trigger event: Channel reward redemption.",
            "Fill the Trigger filters below, set Cooldown (seconds), then open Where and choose a supported Platform.",
            "Open Do, add actions, then Create Automation or Save Changes."
          ]
        }
      }
    },
    {
      "id": "variable.trigger.channel_point_redeem.user",
      "kind": "variable",
      "runtimeKey": "trigger.channel_point_redeem.user",
      "label": "{user}",
      "category": "Event variables",
      "summary": "Viewer display name/username supplied by this event; outgoing raids use destination identity.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.channel_point_redeem.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.channel_point_redeem"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{user}"
        }
      ],
      "details": {
        "syntax": "{user}",
        "canonicalKey": "user",
        "aliases": [],
        "producer": "trigger.channel_point_redeem",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Blank reward accepts any mapped redemption; otherwise reward ID matches exactly. input/message are the viewer reward input."
      }
    },
    {
      "id": "variable.trigger.channel_point_redeem.user.points",
      "kind": "variable",
      "runtimeKey": "trigger.channel_point_redeem.user.points",
      "label": "{user.points}",
      "category": "Event variables",
      "summary": "Command sender current loyalty currency",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.channel_point_redeem.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.channel_point_redeem"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{user.points}"
        }
      ],
      "details": {
        "syntax": "{user.points}",
        "canonicalKey": "user.points",
        "aliases": [],
        "producer": "trigger.channel_point_redeem",
        "lifetime": "Current action sequence.",
        "resolution": "Advertised for this trigger; resolved by global variable engine after event substitution.",
        "emptyEventFallback": null,
        "behavior": "Blank reward accepts any mapped redemption; otherwise reward ID matches exactly. input/message are the viewer reward input."
      }
    },
    {
      "id": "variable.trigger.channel_point_redeem.user.pointsRank",
      "kind": "variable",
      "runtimeKey": "trigger.channel_point_redeem.user.pointsRank",
      "label": "{user.pointsRank}",
      "category": "Event variables",
      "summary": "Command sender loyalty rank",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.channel_point_redeem.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.channel_point_redeem"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{user.pointsRank}"
        }
      ],
      "details": {
        "syntax": "{user.pointsRank}",
        "canonicalKey": "user.pointsRank",
        "aliases": [],
        "producer": "trigger.channel_point_redeem",
        "lifetime": "Current action sequence.",
        "resolution": "Advertised for this trigger; resolved by global variable engine after event substitution.",
        "emptyEventFallback": null,
        "behavior": "Blank reward accepts any mapped redemption; otherwise reward ID matches exactly. input/message are the viewer reward input."
      }
    },
    {
      "id": "variable.trigger.channel_point_redeem.reward",
      "kind": "variable",
      "runtimeKey": "trigger.channel_point_redeem.reward",
      "label": "{reward}",
      "category": "Event variables",
      "summary": "Redeemed reward name.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.channel_point_redeem.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.channel_point_redeem"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{reward}"
        }
      ],
      "details": {
        "syntax": "{reward}",
        "canonicalKey": "reward",
        "aliases": [],
        "producer": "trigger.channel_point_redeem",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Blank reward accepts any mapped redemption; otherwise reward ID matches exactly. input/message are the viewer reward input."
      }
    },
    {
      "id": "variable.trigger.channel_point_redeem.message",
      "kind": "variable",
      "runtimeKey": "trigger.channel_point_redeem.message",
      "label": "{message}",
      "category": "Event variables",
      "summary": "Event text; reward redemptions use viewer input, TikTok questions use the question text.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.channel_point_redeem.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.channel_point_redeem"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{message}"
        }
      ],
      "details": {
        "syntax": "{message}",
        "canonicalKey": "message",
        "aliases": [],
        "producer": "trigger.channel_point_redeem",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Blank reward accepts any mapped redemption; otherwise reward ID matches exactly. input/message are the viewer reward input."
      }
    },
    {
      "id": "variable.trigger.channel_point_redeem.username",
      "kind": "variable",
      "runtimeKey": "trigger.channel_point_redeem.username",
      "label": "{username}",
      "category": "Event variables",
      "summary": "Normalized or provider-supplied event username, not an arbitrary command argument.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.channel_point_redeem.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.channel_point_redeem"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{username}"
        }
      ],
      "details": {
        "syntax": "{username}",
        "canonicalKey": "username",
        "aliases": [],
        "producer": "trigger.channel_point_redeem",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Blank reward accepts any mapped redemption; otherwise reward ID matches exactly. input/message are the viewer reward input."
      }
    },
    {
      "id": "variable.trigger.channel_point_redeem.input",
      "kind": "variable",
      "runtimeKey": "trigger.channel_point_redeem.input",
      "label": "{input}",
      "category": "Event variables",
      "summary": "Reward redemption viewer input; mirrors message in action context.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.channel_point_redeem.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.channel_point_redeem"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{input}"
        }
      ],
      "details": {
        "syntax": "{input}",
        "canonicalKey": "input",
        "aliases": [],
        "producer": "trigger.channel_point_redeem",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Blank reward accepts any mapped redemption; otherwise reward ID matches exactly. input/message are the viewer reward input."
      }
    },
    {
      "id": "trigger.imported_app_event",
      "kind": "trigger",
      "runtimeKey": "imported_app_event",
      "label": "Imported app event",
      "category": "When",
      "summary": "Fires when an installed action library event stream receives a matching mapped event. Choose a specific library and event stream for normal use.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected supported event provider; enabled automation and matching filters.",
        "inboundProviders": [
          "app"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.imported_app_event"
        },
        {
          "path": "src/features/automation-provider-capabilities.js",
          "symbol": "AUTOMATION_TRIGGER_PLATFORMS.imported_app_event"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "variable.trigger.imported_app_event.app",
        "variable.trigger.imported_app_event.library",
        "variable.trigger.imported_app_event.libraryId",
        "variable.trigger.imported_app_event.eventStream",
        "variable.trigger.imported_app_event.eventStreamId",
        "variable.trigger.imported_app_event.eventText",
        "variable.trigger.imported_app_event.eventJson",
        "variable.trigger.imported_app_event.event.key",
        "variable.trigger.imported_app_event.event.value",
        "context.automation"
      ],
      "examples": [
        {
          "purpose": "Trigger selection and filter defaults; supply a real target/pattern when required.",
          "format": "configuration",
          "value": {
            "triggerType": "imported_app_event",
            "triggerPlatform": "app",
            "triggerFilters": {
              "library_id": "",
              "subscription_id": "",
              "event_key": "",
              "event_value": ""
            }
          }
        }
      ],
      "details": {
        "behavior": "Optional library/stream IDs compare case-insensitively. A mapped key with no expected value must be nonempty; otherwise compare its string value case-insensitively. Package mappings can add arbitrary event.<key> variables.",
        "filters": [
          {
            "key": "library_id",
            "type": "action_library_dropdown",
            "label": "Action library"
          },
          {
            "key": "subscription_id",
            "type": "action_library_subscription_dropdown",
            "label": "Event stream"
          },
          {
            "key": "event_key",
            "type": "text",
            "label": "Mapped value key (optional)",
            "placeholder": "state, user, scene"
          },
          {
            "key": "event_value",
            "type": "text",
            "label": "Mapped value equals (optional)",
            "placeholder": "ready"
          }
        ],
        "variableIds": [
          "variable.trigger.imported_app_event.app",
          "variable.trigger.imported_app_event.library",
          "variable.trigger.imported_app_event.libraryId",
          "variable.trigger.imported_app_event.eventStream",
          "variable.trigger.imported_app_event.eventStreamId",
          "variable.trigger.imported_app_event.eventText",
          "variable.trigger.imported_app_event.eventJson",
          "variable.trigger.imported_app_event.event.key",
          "variable.trigger.imported_app_event.event.value"
        ],
        "cooldown": "Automation cooldownSec defaults 0; keyed by automation ID and event platform; held in memory until restart.",
        "delay": "No additional trigger delay.",
        "ui": {
          "path": [
            "Bot",
            "Automations",
            "+ New",
            "When"
          ],
          "initialFields": [],
          "steps": [
            "Choose Trigger category: Broadcast software & installed apps.",
            "Choose Trigger event: Imported app event.",
            "Fill the Trigger filters below, set Cooldown (seconds), then open Where and choose a supported Platform.",
            "Open Do, add actions, then Create Automation or Save Changes."
          ]
        }
      }
    },
    {
      "id": "variable.trigger.imported_app_event.app",
      "kind": "variable",
      "runtimeKey": "trigger.imported_app_event.app",
      "label": "{app}",
      "category": "Event variables",
      "summary": "Installed event library name with ID fallback.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.imported_app_event.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.imported_app_event"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{app}"
        }
      ],
      "details": {
        "syntax": "{app}",
        "canonicalKey": "app",
        "aliases": [],
        "producer": "trigger.imported_app_event",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Optional library/stream IDs compare case-insensitively. A mapped key with no expected value must be nonempty; otherwise compare its string value case-insensitively. Package mappings can add arbitrary event.<key> variables."
      }
    },
    {
      "id": "variable.trigger.imported_app_event.library",
      "kind": "variable",
      "runtimeKey": "trigger.imported_app_event.library",
      "label": "{library}",
      "category": "Event variables",
      "summary": "Installed event library name with ID fallback.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.imported_app_event.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.imported_app_event"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{library}"
        }
      ],
      "details": {
        "syntax": "{library}",
        "canonicalKey": "library",
        "aliases": [],
        "producer": "trigger.imported_app_event",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Optional library/stream IDs compare case-insensitively. A mapped key with no expected value must be nonempty; otherwise compare its string value case-insensitively. Package mappings can add arbitrary event.<key> variables."
      }
    },
    {
      "id": "variable.trigger.imported_app_event.libraryId",
      "kind": "variable",
      "runtimeKey": "trigger.imported_app_event.libraryId",
      "label": "{libraryId}",
      "category": "Event variables",
      "summary": "Installed library ID.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.imported_app_event.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.imported_app_event"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{libraryId}"
        }
      ],
      "details": {
        "syntax": "{libraryId}",
        "canonicalKey": "libraryId",
        "aliases": [],
        "producer": "trigger.imported_app_event",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Optional library/stream IDs compare case-insensitively. A mapped key with no expected value must be nonempty; otherwise compare its string value case-insensitively. Package mappings can add arbitrary event.<key> variables."
      }
    },
    {
      "id": "variable.trigger.imported_app_event.eventStream",
      "kind": "variable",
      "runtimeKey": "trigger.imported_app_event.eventStream",
      "label": "{eventStream}",
      "category": "Event variables",
      "summary": "Subscription label with ID fallback.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.imported_app_event.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.imported_app_event"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{eventStream}"
        }
      ],
      "details": {
        "syntax": "{eventStream}",
        "canonicalKey": "eventStream",
        "aliases": [],
        "producer": "trigger.imported_app_event",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Optional library/stream IDs compare case-insensitively. A mapped key with no expected value must be nonempty; otherwise compare its string value case-insensitively. Package mappings can add arbitrary event.<key> variables."
      }
    },
    {
      "id": "variable.trigger.imported_app_event.eventStreamId",
      "kind": "variable",
      "runtimeKey": "trigger.imported_app_event.eventStreamId",
      "label": "{eventStreamId}",
      "category": "Event variables",
      "summary": "Subscription ID.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.imported_app_event.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.imported_app_event"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{eventStreamId}"
        }
      ],
      "details": {
        "syntax": "{eventStreamId}",
        "canonicalKey": "eventStreamId",
        "aliases": [],
        "producer": "trigger.imported_app_event",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Optional library/stream IDs compare case-insensitively. A mapped key with no expected value must be nonempty; otherwise compare its string value case-insensitively. Package mappings can add arbitrary event.<key> variables."
      }
    },
    {
      "id": "variable.trigger.imported_app_event.eventText",
      "kind": "variable",
      "runtimeKey": "trigger.imported_app_event.eventText",
      "label": "{eventText}",
      "category": "Event variables",
      "summary": "Mapped imported event text.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.imported_app_event.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.imported_app_event"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{eventText}"
        }
      ],
      "details": {
        "syntax": "{eventText}",
        "canonicalKey": "eventText",
        "aliases": [],
        "producer": "trigger.imported_app_event",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Optional library/stream IDs compare case-insensitively. A mapped key with no expected value must be nonempty; otherwise compare its string value case-insensitively. Package mappings can add arbitrary event.<key> variables."
      }
    },
    {
      "id": "variable.trigger.imported_app_event.eventJson",
      "kind": "variable",
      "runtimeKey": "trigger.imported_app_event.eventJson",
      "label": "{eventJson}",
      "category": "Event variables",
      "summary": "Imported event JSON string when supplied.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.imported_app_event.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.imported_app_event"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{eventJson}"
        }
      ],
      "details": {
        "syntax": "{eventJson}",
        "canonicalKey": "eventJson",
        "aliases": [],
        "producer": "trigger.imported_app_event",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Optional library/stream IDs compare case-insensitively. A mapped key with no expected value must be nonempty; otherwise compare its string value case-insensitively. Package mappings can add arbitrary event.<key> variables."
      }
    },
    {
      "id": "variable.trigger.imported_app_event.event.key",
      "kind": "variable",
      "runtimeKey": "trigger.imported_app_event.event.key",
      "label": "{event.key}",
      "category": "Event variables",
      "summary": "Mapped event key when supplied.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.imported_app_event.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.imported_app_event"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{event.key}"
        }
      ],
      "details": {
        "syntax": "{event.key}",
        "canonicalKey": "event.key",
        "aliases": [],
        "producer": "trigger.imported_app_event",
        "lifetime": "Current action sequence.",
        "resolution": "Advertised by this trigger; only populated when the corresponding event mapping supplies the value.",
        "emptyEventFallback": null,
        "behavior": "Optional library/stream IDs compare case-insensitively. A mapped key with no expected value must be nonempty; otherwise compare its string value case-insensitively. Package mappings can add arbitrary event.<key> variables."
      }
    },
    {
      "id": "variable.trigger.imported_app_event.event.value",
      "kind": "variable",
      "runtimeKey": "trigger.imported_app_event.event.value",
      "label": "{event.value}",
      "category": "Event variables",
      "summary": "Mapped event value when supplied.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.imported_app_event.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.imported_app_event"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{event.value}"
        }
      ],
      "details": {
        "syntax": "{event.value}",
        "canonicalKey": "event.value",
        "aliases": [],
        "producer": "trigger.imported_app_event",
        "lifetime": "Current action sequence.",
        "resolution": "Advertised by this trigger; only populated when the corresponding event mapping supplies the value.",
        "emptyEventFallback": null,
        "behavior": "Optional library/stream IDs compare case-insensitively. A mapped key with no expected value must be nonempty; otherwise compare its string value case-insensitively. Package mappings can add arbitrary event.<key> variables."
      }
    },
    {
      "id": "trigger.ad_break",
      "kind": "trigger",
      "runtimeKey": "ad_break",
      "label": "Ad break",
      "category": "When",
      "summary": "Fires when an ad break starts, with an optional time offset.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected supported event provider; enabled automation and matching filters.",
        "inboundProviders": [
          "twitch"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.ad_break"
        },
        {
          "path": "src/features/automation-provider-capabilities.js",
          "symbol": "AUTOMATION_TRIGGER_PLATFORMS.ad_break"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "variable.trigger.ad_break.duration",
        "variable.trigger.ad_break.is_automatic",
        "context.automation"
      ],
      "examples": [
        {
          "purpose": "Trigger selection and filter defaults; supply a real target/pattern when required.",
          "format": "configuration",
          "value": {
            "triggerType": "ad_break",
            "triggerPlatform": "twitch",
            "triggerFilters": {
              "offset_sec": 0,
              "is_automatic": ""
            }
          }
        }
      ],
      "details": {
        "behavior": "Match ad-start with optional automatic/manual filter. Positive offset delays actions; negative offsets clamp to immediate and do not schedule a pre-ad action.",
        "filters": [
          {
            "key": "offset_sec",
            "type": "number",
            "label": "Offset (seconds, negative = before if supported)",
            "min": -300,
            "max": 300,
            "default": 0
          },
          {
            "key": "is_automatic",
            "type": "select",
            "label": "Ad type",
            "options": [
              {
                "value": "",
                "label": "Any"
              },
              {
                "value": "true",
                "label": "Automatic only"
              },
              {
                "value": "false",
                "label": "Manual only"
              }
            ]
          }
        ],
        "variableIds": [
          "variable.trigger.ad_break.duration",
          "variable.trigger.ad_break.is_automatic"
        ],
        "cooldown": "Automation cooldownSec defaults 0; keyed by automation ID and event platform; held in memory until restart.",
        "delay": "offset_sec positive delays; negative clamps to 0.",
        "ui": {
          "path": [
            "Bot",
            "Automations",
            "+ New",
            "When"
          ],
          "initialFields": [],
          "steps": [
            "Choose Trigger category: Platform events.",
            "Choose the incoming Platform first.",
            "Choose Trigger event: Ad break.",
            "Fill the Trigger filters below, set Cooldown (seconds), then open Where and choose a supported Platform.",
            "Open Do, add actions, then Create Automation or Save Changes."
          ]
        }
      }
    },
    {
      "id": "variable.trigger.ad_break.duration",
      "kind": "variable",
      "runtimeKey": "trigger.ad_break.duration",
      "label": "{duration}",
      "category": "Event variables",
      "summary": "Ad duration in seconds, or 0.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.ad_break.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.ad_break"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{duration}"
        }
      ],
      "details": {
        "syntax": "{duration}",
        "canonicalKey": "duration",
        "aliases": [],
        "producer": "trigger.ad_break",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": 0,
        "behavior": "Match ad-start with optional automatic/manual filter. Positive offset delays actions; negative offsets clamp to immediate and do not schedule a pre-ad action."
      }
    },
    {
      "id": "variable.trigger.ad_break.is_automatic",
      "kind": "variable",
      "runtimeKey": "trigger.ad_break.is_automatic",
      "label": "{is_automatic}",
      "category": "Event variables",
      "summary": "Ad type as yes/no.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.ad_break.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.ad_break"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{is_automatic}"
        }
      ],
      "details": {
        "syntax": "{is_automatic}",
        "canonicalKey": "is_automatic",
        "aliases": [],
        "producer": "trigger.ad_break",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "no",
        "behavior": "Match ad-start with optional automatic/manual filter. Positive offset delays actions; negative offsets clamp to immediate and do not schedule a pre-ad action."
      }
    },
    {
      "id": "trigger.hype_train",
      "kind": "trigger",
      "runtimeKey": "hype_train",
      "label": "Hype Train",
      "category": "When",
      "summary": "Fires when a Hype Train begins.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected supported event provider; enabled automation and matching filters.",
        "inboundProviders": [
          "twitch"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.hype_train"
        },
        {
          "path": "src/features/automation-provider-capabilities.js",
          "symbol": "AUTOMATION_TRIGGER_PLATFORMS.hype_train"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "variable.trigger.hype_train.level",
        "variable.trigger.hype_train.goal",
        "context.automation"
      ],
      "examples": [
        {
          "purpose": "Trigger selection and filter defaults; supply a real target/pattern when required.",
          "format": "configuration",
          "value": {
            "triggerType": "hype_train",
            "triggerPlatform": "twitch",
            "triggerFilters": {}
          }
        }
      ],
      "details": {
        "behavior": "Mapped Hype Train begin event; level defaults 1 and goal 0.",
        "filters": [],
        "variableIds": [
          "variable.trigger.hype_train.level",
          "variable.trigger.hype_train.goal"
        ],
        "cooldown": "Automation cooldownSec defaults 0; keyed by automation ID and event platform; held in memory until restart.",
        "delay": "No additional trigger delay.",
        "ui": {
          "path": [
            "Bot",
            "Automations",
            "+ New",
            "When"
          ],
          "initialFields": [],
          "steps": [
            "Choose Trigger category: Platform events.",
            "Choose the incoming Platform first.",
            "Choose Trigger event: Hype Train.",
            "Fill the Trigger filters below, set Cooldown (seconds), then open Where and choose a supported Platform.",
            "Open Do, add actions, then Create Automation or Save Changes."
          ]
        }
      }
    },
    {
      "id": "variable.trigger.hype_train.level",
      "kind": "variable",
      "runtimeKey": "trigger.hype_train.level",
      "label": "{level}",
      "category": "Event variables",
      "summary": "Hype Train level, default 1.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.hype_train.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.hype_train"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{level}"
        }
      ],
      "details": {
        "syntax": "{level}",
        "canonicalKey": "level",
        "aliases": [],
        "producer": "trigger.hype_train",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": 1,
        "behavior": "Mapped Hype Train begin event; level defaults 1 and goal 0."
      }
    },
    {
      "id": "variable.trigger.hype_train.goal",
      "kind": "variable",
      "runtimeKey": "trigger.hype_train.goal",
      "label": "{goal}",
      "category": "Event variables",
      "summary": "Hype Train goal, default 0.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.hype_train.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.hype_train"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{goal}"
        }
      ],
      "details": {
        "syntax": "{goal}",
        "canonicalKey": "goal",
        "aliases": [],
        "producer": "trigger.hype_train",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": 0,
        "behavior": "Mapped Hype Train begin event; level defaults 1 and goal 0."
      }
    },
    {
      "id": "trigger.poll_end",
      "kind": "trigger",
      "runtimeKey": "poll_end",
      "label": "Poll ended",
      "category": "When",
      "summary": "Fires when a Twitch poll ends.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected supported event provider; enabled automation and matching filters.",
        "inboundProviders": [
          "twitch"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.poll_end"
        },
        {
          "path": "src/features/automation-provider-capabilities.js",
          "symbol": "AUTOMATION_TRIGGER_PLATFORMS.poll_end"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "variable.trigger.poll_end.title",
        "variable.trigger.poll_end.winner",
        "variable.trigger.poll_end.winner_votes",
        "context.automation"
      ],
      "examples": [
        {
          "purpose": "Trigger selection and filter defaults; supply a real target/pattern when required.",
          "format": "configuration",
          "value": {
            "triggerType": "poll_end",
            "triggerPlatform": "twitch",
            "triggerFilters": {}
          }
        }
      ],
      "details": {
        "behavior": "Mapped completed Twitch poll; title, winning choice and votes refer to that poll, not stream metadata.",
        "filters": [],
        "variableIds": [
          "variable.trigger.poll_end.title",
          "variable.trigger.poll_end.winner",
          "variable.trigger.poll_end.winner_votes"
        ],
        "cooldown": "Automation cooldownSec defaults 0; keyed by automation ID and event platform; held in memory until restart.",
        "delay": "No additional trigger delay.",
        "ui": {
          "path": [
            "Bot",
            "Automations",
            "+ New",
            "When"
          ],
          "initialFields": [],
          "steps": [
            "Choose Trigger category: Platform events.",
            "Choose the incoming Platform first.",
            "Choose Trigger event: Poll ended.",
            "Fill the Trigger filters below, set Cooldown (seconds), then open Where and choose a supported Platform.",
            "Open Do, add actions, then Create Automation or Save Changes."
          ]
        }
      }
    },
    {
      "id": "variable.trigger.poll_end.title",
      "kind": "variable",
      "runtimeKey": "trigger.poll_end.title",
      "label": "{title}",
      "category": "Event variables",
      "summary": "Poll or prediction title in these event contexts; not the channel title.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.poll_end.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.poll_end"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{title}"
        }
      ],
      "details": {
        "syntax": "{title}",
        "canonicalKey": "title",
        "aliases": [],
        "producer": "trigger.poll_end",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Mapped completed Twitch poll; title, winning choice and votes refer to that poll, not stream metadata."
      }
    },
    {
      "id": "variable.trigger.poll_end.winner",
      "kind": "variable",
      "runtimeKey": "trigger.poll_end.winner",
      "label": "{winner}",
      "category": "Event variables",
      "summary": "Winning poll choice.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.poll_end.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.poll_end"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{winner}"
        }
      ],
      "details": {
        "syntax": "{winner}",
        "canonicalKey": "winner",
        "aliases": [],
        "producer": "trigger.poll_end",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Mapped completed Twitch poll; title, winning choice and votes refer to that poll, not stream metadata."
      }
    },
    {
      "id": "variable.trigger.poll_end.winner_votes",
      "kind": "variable",
      "runtimeKey": "trigger.poll_end.winner_votes",
      "label": "{winner_votes}",
      "category": "Event variables",
      "summary": "Winning poll vote count, or 0.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.poll_end.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.poll_end"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{winner_votes}"
        }
      ],
      "details": {
        "syntax": "{winner_votes}",
        "canonicalKey": "winner_votes",
        "aliases": [],
        "producer": "trigger.poll_end",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": 0,
        "behavior": "Mapped completed Twitch poll; title, winning choice and votes refer to that poll, not stream metadata."
      }
    },
    {
      "id": "trigger.prediction_lock",
      "kind": "trigger",
      "runtimeKey": "prediction_lock",
      "label": "Prediction locked",
      "category": "When",
      "summary": "Fires when a Twitch prediction is locked for voting.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected supported event provider; enabled automation and matching filters.",
        "inboundProviders": [
          "twitch"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.prediction_lock"
        },
        {
          "path": "src/features/automation-provider-capabilities.js",
          "symbol": "AUTOMATION_TRIGGER_PLATFORMS.prediction_lock"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "variable.trigger.prediction_lock.title",
        "context.automation"
      ],
      "examples": [
        {
          "purpose": "Trigger selection and filter defaults; supply a real target/pattern when required.",
          "format": "configuration",
          "value": {
            "triggerType": "prediction_lock",
            "triggerPlatform": "twitch",
            "triggerFilters": {}
          }
        }
      ],
      "details": {
        "behavior": "Mapped Twitch prediction lock; title is the prediction title.",
        "filters": [],
        "variableIds": [
          "variable.trigger.prediction_lock.title"
        ],
        "cooldown": "Automation cooldownSec defaults 0; keyed by automation ID and event platform; held in memory until restart.",
        "delay": "No additional trigger delay.",
        "ui": {
          "path": [
            "Bot",
            "Automations",
            "+ New",
            "When"
          ],
          "initialFields": [],
          "steps": [
            "Choose Trigger category: Platform events.",
            "Choose the incoming Platform first.",
            "Choose Trigger event: Prediction locked.",
            "Fill the Trigger filters below, set Cooldown (seconds), then open Where and choose a supported Platform.",
            "Open Do, add actions, then Create Automation or Save Changes."
          ]
        }
      }
    },
    {
      "id": "variable.trigger.prediction_lock.title",
      "kind": "variable",
      "runtimeKey": "trigger.prediction_lock.title",
      "label": "{title}",
      "category": "Event variables",
      "summary": "Poll or prediction title in these event contexts; not the channel title.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.prediction_lock.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.prediction_lock"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{title}"
        }
      ],
      "details": {
        "syntax": "{title}",
        "canonicalKey": "title",
        "aliases": [],
        "producer": "trigger.prediction_lock",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Mapped Twitch prediction lock; title is the prediction title."
      }
    },
    {
      "id": "trigger.superchat",
      "kind": "trigger",
      "runtimeKey": "superchat",
      "label": "Super Chat / Super Sticker",
      "category": "When",
      "summary": "Fires when a viewer sends a Super Chat or Super Sticker.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected supported event provider; enabled automation and matching filters.",
        "inboundProviders": [
          "youtube"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.superchat"
        },
        {
          "path": "src/features/automation-provider-capabilities.js",
          "symbol": "AUTOMATION_TRIGGER_PLATFORMS.superchat"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "variable.trigger.superchat.user",
        "variable.trigger.superchat.amount",
        "variable.trigger.superchat.message",
        "context.automation"
      ],
      "examples": [
        {
          "purpose": "Trigger selection and filter defaults; supply a real target/pattern when required.",
          "format": "configuration",
          "value": {
            "triggerType": "superchat",
            "triggerPlatform": "youtube",
            "triggerFilters": {
              "min_amount": 0
            }
          }
        }
      ],
      "details": {
        "behavior": "Mapped YouTube Super Chat/Sticker with amount >= min_amount. Uses normalized event amount; do not infer universal currency conversion from the dollar label.",
        "filters": [
          {
            "key": "min_amount",
            "type": "number",
            "label": "Minimum amount ($, 0 = any)",
            "min": 0,
            "default": 0
          }
        ],
        "variableIds": [
          "variable.trigger.superchat.user",
          "variable.trigger.superchat.amount",
          "variable.trigger.superchat.message"
        ],
        "cooldown": "Automation cooldownSec defaults 0; keyed by automation ID and event platform; held in memory until restart.",
        "delay": "No additional trigger delay.",
        "ui": {
          "path": [
            "Bot",
            "Automations",
            "+ New",
            "When"
          ],
          "initialFields": [],
          "steps": [
            "Choose Trigger category: Monetization.",
            "Choose Trigger event: Super Chat / Super Sticker.",
            "Fill the Trigger filters below, set Cooldown (seconds), then open Where and choose a supported Platform.",
            "Open Do, add actions, then Create Automation or Save Changes."
          ]
        }
      }
    },
    {
      "id": "variable.trigger.superchat.user",
      "kind": "variable",
      "runtimeKey": "trigger.superchat.user",
      "label": "{user}",
      "category": "Event variables",
      "summary": "Viewer display name/username supplied by this event; outgoing raids use destination identity.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.superchat.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.superchat"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{user}"
        }
      ],
      "details": {
        "syntax": "{user}",
        "canonicalKey": "user",
        "aliases": [],
        "producer": "trigger.superchat",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": null,
        "behavior": "Mapped YouTube Super Chat/Sticker with amount >= min_amount. Uses normalized event amount; do not infer universal currency conversion from the dollar label."
      }
    },
    {
      "id": "variable.trigger.superchat.amount",
      "kind": "variable",
      "runtimeKey": "trigger.superchat.amount",
      "label": "{amount}",
      "category": "Event variables",
      "summary": "Provider-normalized gift amount or Super Chat amount; do not assume cross-provider currency equivalence.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.superchat.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.superchat"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{amount}"
        }
      ],
      "details": {
        "syntax": "{amount}",
        "canonicalKey": "amount",
        "aliases": [],
        "producer": "trigger.superchat",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": 0,
        "behavior": "Mapped YouTube Super Chat/Sticker with amount >= min_amount. Uses normalized event amount; do not infer universal currency conversion from the dollar label."
      }
    },
    {
      "id": "variable.trigger.superchat.message",
      "kind": "variable",
      "runtimeKey": "trigger.superchat.message",
      "label": "{message}",
      "category": "Event variables",
      "summary": "Event text; reward redemptions use viewer input, TikTok questions use the question text.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.superchat.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.superchat"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{message}"
        }
      ],
      "details": {
        "syntax": "{message}",
        "canonicalKey": "message",
        "aliases": [],
        "producer": "trigger.superchat",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Mapped YouTube Super Chat/Sticker with amount >= min_amount. Uses normalized event amount; do not infer universal currency conversion from the dollar label."
      }
    },
    {
      "id": "trigger.obs_scene_change",
      "kind": "trigger",
      "runtimeKey": "obs_scene_change",
      "label": "OBS scene change",
      "category": "When",
      "summary": "Fires when OBS changes to a selected program scene. Leave the scene blank to react to any scene change.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected supported event provider; enabled automation and matching filters.",
        "inboundProviders": [
          "obs"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.obs_scene_change"
        },
        {
          "path": "src/features/automation-provider-capabilities.js",
          "symbol": "AUTOMATION_TRIGGER_PLATFORMS.obs_scene_change"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "variable.trigger.obs_scene_change.scene",
        "variable.trigger.obs_scene_change.previousScene",
        "variable.trigger.obs_scene_change.platform",
        "context.automation"
      ],
      "examples": [
        {
          "purpose": "Trigger selection and filter defaults; supply a real target/pattern when required.",
          "format": "configuration",
          "value": {
            "triggerType": "obs_scene_change",
            "triggerPlatform": "obs",
            "triggerFilters": {
              "sceneName": ""
            }
          }
        }
      ],
      "details": {
        "behavior": "Program-scene change; blank selects any scene, otherwise trimmed case-insensitive scene-name equality. Requires OBS connection.",
        "filters": [
          {
            "key": "sceneName",
            "type": "obs_scene_dropdown",
            "label": "Scene (blank = any scene)"
          }
        ],
        "variableIds": [
          "variable.trigger.obs_scene_change.scene",
          "variable.trigger.obs_scene_change.previousScene",
          "variable.trigger.obs_scene_change.platform"
        ],
        "cooldown": "Automation cooldownSec defaults 0; keyed by automation ID and event platform; held in memory until restart.",
        "delay": "No additional trigger delay.",
        "ui": {
          "path": [
            "Bot",
            "Automations",
            "+ New",
            "When"
          ],
          "initialFields": [],
          "steps": [
            "Choose Trigger category: Broadcast software & installed apps.",
            "Choose Trigger event: OBS scene change.",
            "Fill the Trigger filters below, set Cooldown (seconds), then open Where and choose a supported Platform.",
            "Open Do, add actions, then Create Automation or Save Changes."
          ]
        }
      }
    },
    {
      "id": "variable.trigger.obs_scene_change.scene",
      "kind": "variable",
      "runtimeKey": "trigger.obs_scene_change.scene",
      "label": "{scene}",
      "category": "Event variables",
      "summary": "New active scene name.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.obs_scene_change.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.obs_scene_change"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{scene}"
        }
      ],
      "details": {
        "syntax": "{scene}",
        "canonicalKey": "scene",
        "aliases": [],
        "producer": "trigger.obs_scene_change",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Program-scene change; blank selects any scene, otherwise trimmed case-insensitive scene-name equality. Requires OBS connection."
      }
    },
    {
      "id": "variable.trigger.obs_scene_change.previousScene",
      "kind": "variable",
      "runtimeKey": "trigger.obs_scene_change.previousScene",
      "label": "{previousScene}",
      "category": "Event variables",
      "summary": "Previous scene name.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.obs_scene_change.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.obs_scene_change"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{previousScene}"
        }
      ],
      "details": {
        "syntax": "{previousScene}",
        "canonicalKey": "previousScene",
        "aliases": [],
        "producer": "trigger.obs_scene_change",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Program-scene change; blank selects any scene, otherwise trimmed case-insensitive scene-name equality. Requires OBS connection."
      }
    },
    {
      "id": "variable.trigger.obs_scene_change.platform",
      "kind": "variable",
      "runtimeKey": "trigger.obs_scene_change.platform",
      "label": "{platform}",
      "category": "Event variables",
      "summary": "Originating provider, including obs/streamlabs for local events; not necessarily a chat destination.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.obs_scene_change.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.obs_scene_change"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{platform}"
        }
      ],
      "details": {
        "syntax": "{platform}",
        "canonicalKey": "platform",
        "aliases": [],
        "producer": "trigger.obs_scene_change",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "obs",
        "behavior": "Program-scene change; blank selects any scene, otherwise trimmed case-insensitive scene-name equality. Requires OBS connection."
      }
    },
    {
      "id": "trigger.streamlabs_scene_change",
      "kind": "trigger",
      "runtimeKey": "streamlabs_scene_change",
      "label": "Streamlabs Desktop scene change",
      "category": "When",
      "summary": "Fires when Streamlabs Desktop switches to a selected scene. Leave the scene blank to react to any scene change.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected supported event provider; enabled automation and matching filters.",
        "inboundProviders": [
          "streamlabs"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.streamlabs_scene_change"
        },
        {
          "path": "src/features/automation-provider-capabilities.js",
          "symbol": "AUTOMATION_TRIGGER_PLATFORMS.streamlabs_scene_change"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "variable.trigger.streamlabs_scene_change.scene",
        "variable.trigger.streamlabs_scene_change.previousScene",
        "variable.trigger.streamlabs_scene_change.platform",
        "context.automation"
      ],
      "examples": [
        {
          "purpose": "Trigger selection and filter defaults; supply a real target/pattern when required.",
          "format": "configuration",
          "value": {
            "triggerType": "streamlabs_scene_change",
            "triggerPlatform": "streamlabs",
            "triggerFilters": {
              "sceneId": ""
            }
          }
        }
      ],
      "details": {
        "behavior": "Blank selects any scene, otherwise exact selected scene ID equality. Requires Streamlabs Desktop connection.",
        "filters": [
          {
            "key": "sceneId",
            "type": "streamlabs_scene_dropdown",
            "label": "Scene (blank = any scene)"
          }
        ],
        "variableIds": [
          "variable.trigger.streamlabs_scene_change.scene",
          "variable.trigger.streamlabs_scene_change.previousScene",
          "variable.trigger.streamlabs_scene_change.platform"
        ],
        "cooldown": "Automation cooldownSec defaults 0; keyed by automation ID and event platform; held in memory until restart.",
        "delay": "No additional trigger delay.",
        "ui": {
          "path": [
            "Bot",
            "Automations",
            "+ New",
            "When"
          ],
          "initialFields": [],
          "steps": [
            "Choose Trigger category: Broadcast software & installed apps.",
            "Choose Trigger event: Streamlabs Desktop scene change.",
            "Fill the Trigger filters below, set Cooldown (seconds), then open Where and choose a supported Platform.",
            "Open Do, add actions, then Create Automation or Save Changes."
          ]
        }
      }
    },
    {
      "id": "variable.trigger.streamlabs_scene_change.scene",
      "kind": "variable",
      "runtimeKey": "trigger.streamlabs_scene_change.scene",
      "label": "{scene}",
      "category": "Event variables",
      "summary": "New active scene name.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.streamlabs_scene_change.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.streamlabs_scene_change"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{scene}"
        }
      ],
      "details": {
        "syntax": "{scene}",
        "canonicalKey": "scene",
        "aliases": [],
        "producer": "trigger.streamlabs_scene_change",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Blank selects any scene, otherwise exact selected scene ID equality. Requires Streamlabs Desktop connection."
      }
    },
    {
      "id": "variable.trigger.streamlabs_scene_change.previousScene",
      "kind": "variable",
      "runtimeKey": "trigger.streamlabs_scene_change.previousScene",
      "label": "{previousScene}",
      "category": "Event variables",
      "summary": "Previous scene name.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.streamlabs_scene_change.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.streamlabs_scene_change"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{previousScene}"
        }
      ],
      "details": {
        "syntax": "{previousScene}",
        "canonicalKey": "previousScene",
        "aliases": [],
        "producer": "trigger.streamlabs_scene_change",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Blank selects any scene, otherwise exact selected scene ID equality. Requires Streamlabs Desktop connection."
      }
    },
    {
      "id": "variable.trigger.streamlabs_scene_change.platform",
      "kind": "variable",
      "runtimeKey": "trigger.streamlabs_scene_change.platform",
      "label": "{platform}",
      "category": "Event variables",
      "summary": "Originating provider, including obs/streamlabs for local events; not necessarily a chat destination.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.streamlabs_scene_change.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.streamlabs_scene_change"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{platform}"
        }
      ],
      "details": {
        "syntax": "{platform}",
        "canonicalKey": "platform",
        "aliases": [],
        "producer": "trigger.streamlabs_scene_change",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "streamlabs",
        "behavior": "Blank selects any scene, otherwise exact selected scene ID equality. Requires Streamlabs Desktop connection."
      }
    },
    {
      "id": "trigger.streamlabs_output_change",
      "kind": "trigger",
      "runtimeKey": "streamlabs_output_change",
      "label": "Streamlabs Desktop output status",
      "category": "When",
      "summary": "Fires after a Streamlabs stream, recording, or replay buffer actually starts or stops. Transient statuses do not fire.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected supported event provider; enabled automation and matching filters.",
        "inboundProviders": [
          "streamlabs"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.streamlabs_output_change"
        },
        {
          "path": "src/features/automation-provider-capabilities.js",
          "symbol": "AUTOMATION_TRIGGER_PLATFORMS.streamlabs_output_change"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "variable.trigger.streamlabs_output_change.output",
        "variable.trigger.streamlabs_output_change.transition",
        "variable.trigger.streamlabs_output_change.status",
        "variable.trigger.streamlabs_output_change.previousStatus",
        "variable.trigger.streamlabs_output_change.platform",
        "context.automation"
      ],
      "examples": [
        {
          "purpose": "Trigger selection and filter defaults; supply a real target/pattern when required.",
          "format": "configuration",
          "value": {
            "triggerType": "streamlabs_output_change",
            "triggerPlatform": "streamlabs",
            "triggerFilters": {
              "output": "stream",
              "transition": "started"
            }
          }
        }
      ],
      "details": {
        "behavior": "Only settled stream/record/replay start/stop transitions. Output defaults stream; transition defaults started. Transient statuses do not fire.",
        "filters": [
          {
            "key": "output",
            "type": "select",
            "label": "Output",
            "default": "stream",
            "options": [
              {
                "value": "stream",
                "label": "Stream"
              },
              {
                "value": "record",
                "label": "Recording"
              },
              {
                "value": "replay",
                "label": "Replay buffer"
              }
            ]
          },
          {
            "key": "transition",
            "type": "select",
            "label": "When",
            "default": "started",
            "options": [
              {
                "value": "started",
                "label": "Started"
              },
              {
                "value": "stopped",
                "label": "Stopped"
              }
            ]
          }
        ],
        "variableIds": [
          "variable.trigger.streamlabs_output_change.output",
          "variable.trigger.streamlabs_output_change.transition",
          "variable.trigger.streamlabs_output_change.status",
          "variable.trigger.streamlabs_output_change.previousStatus",
          "variable.trigger.streamlabs_output_change.platform"
        ],
        "cooldown": "Automation cooldownSec defaults 0; keyed by automation ID and event platform; held in memory until restart.",
        "delay": "No additional trigger delay.",
        "ui": {
          "path": [
            "Bot",
            "Automations",
            "+ New",
            "When"
          ],
          "initialFields": [],
          "steps": [
            "Choose Trigger category: Broadcast software & installed apps.",
            "Choose Trigger event: Streamlabs Desktop output status.",
            "Fill the Trigger filters below, set Cooldown (seconds), then open Where and choose a supported Platform.",
            "Open Do, add actions, then Create Automation or Save Changes."
          ]
        }
      }
    },
    {
      "id": "variable.trigger.streamlabs_output_change.output",
      "kind": "variable",
      "runtimeKey": "trigger.streamlabs_output_change.output",
      "label": "{output}",
      "category": "Event variables",
      "summary": "Streamlabs output family: stream, record or replay.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.streamlabs_output_change.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.streamlabs_output_change"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{output}"
        }
      ],
      "details": {
        "syntax": "{output}",
        "canonicalKey": "output",
        "aliases": [],
        "producer": "trigger.streamlabs_output_change",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Only settled stream/record/replay start/stop transitions. Output defaults stream; transition defaults started. Transient statuses do not fire."
      }
    },
    {
      "id": "variable.trigger.streamlabs_output_change.transition",
      "kind": "variable",
      "runtimeKey": "trigger.streamlabs_output_change.transition",
      "label": "{transition}",
      "category": "Event variables",
      "summary": "Settled output transition: started or stopped.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.streamlabs_output_change.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.streamlabs_output_change"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{transition}"
        }
      ],
      "details": {
        "syntax": "{transition}",
        "canonicalKey": "transition",
        "aliases": [],
        "producer": "trigger.streamlabs_output_change",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Only settled stream/record/replay start/stop transitions. Output defaults stream; transition defaults started. Transient statuses do not fire."
      }
    },
    {
      "id": "variable.trigger.streamlabs_output_change.status",
      "kind": "variable",
      "runtimeKey": "trigger.streamlabs_output_change.status",
      "label": "{status}",
      "category": "Event variables",
      "summary": "New Streamlabs output status.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.streamlabs_output_change.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.streamlabs_output_change"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{status}"
        }
      ],
      "details": {
        "syntax": "{status}",
        "canonicalKey": "status",
        "aliases": [],
        "producer": "trigger.streamlabs_output_change",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Only settled stream/record/replay start/stop transitions. Output defaults stream; transition defaults started. Transient statuses do not fire."
      }
    },
    {
      "id": "variable.trigger.streamlabs_output_change.previousStatus",
      "kind": "variable",
      "runtimeKey": "trigger.streamlabs_output_change.previousStatus",
      "label": "{previousStatus}",
      "category": "Event variables",
      "summary": "Previous output status.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.streamlabs_output_change.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.streamlabs_output_change"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{previousStatus}"
        }
      ],
      "details": {
        "syntax": "{previousStatus}",
        "canonicalKey": "previousStatus",
        "aliases": [],
        "producer": "trigger.streamlabs_output_change",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Only settled stream/record/replay start/stop transitions. Output defaults stream; transition defaults started. Transient statuses do not fire."
      }
    },
    {
      "id": "variable.trigger.streamlabs_output_change.platform",
      "kind": "variable",
      "runtimeKey": "trigger.streamlabs_output_change.platform",
      "label": "{platform}",
      "category": "Event variables",
      "summary": "Originating provider, including obs/streamlabs for local events; not necessarily a chat destination.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.streamlabs_output_change.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.streamlabs_output_change"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{platform}"
        }
      ],
      "details": {
        "syntax": "{platform}",
        "canonicalKey": "platform",
        "aliases": [],
        "producer": "trigger.streamlabs_output_change",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "streamlabs",
        "behavior": "Only settled stream/record/replay start/stop transitions. Output defaults stream; transition defaults started. Transient statuses do not fire."
      }
    },
    {
      "id": "trigger.streamlabs_collection_change",
      "kind": "trigger",
      "runtimeKey": "streamlabs_collection_change",
      "label": "Streamlabs Desktop scene collection change",
      "category": "When",
      "summary": "Fires when Streamlabs Desktop switches to a selected scene collection. Leave blank for any collection.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected supported event provider; enabled automation and matching filters.",
        "inboundProviders": [
          "streamlabs"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.streamlabs_collection_change"
        },
        {
          "path": "src/features/automation-provider-capabilities.js",
          "symbol": "AUTOMATION_TRIGGER_PLATFORMS.streamlabs_collection_change"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "variable.trigger.streamlabs_collection_change.collection",
        "variable.trigger.streamlabs_collection_change.previousCollection",
        "variable.trigger.streamlabs_collection_change.platform",
        "context.automation"
      ],
      "examples": [
        {
          "purpose": "Trigger selection and filter defaults; supply a real target/pattern when required.",
          "format": "configuration",
          "value": {
            "triggerType": "streamlabs_collection_change",
            "triggerPlatform": "streamlabs",
            "triggerFilters": {
              "collectionId": ""
            }
          }
        }
      ],
      "details": {
        "behavior": "Blank selects any collection, otherwise exact selected collection ID equality.",
        "filters": [
          {
            "key": "collectionId",
            "type": "streamlabs_collection_dropdown",
            "label": "Scene collection (blank = any)"
          }
        ],
        "variableIds": [
          "variable.trigger.streamlabs_collection_change.collection",
          "variable.trigger.streamlabs_collection_change.previousCollection",
          "variable.trigger.streamlabs_collection_change.platform"
        ],
        "cooldown": "Automation cooldownSec defaults 0; keyed by automation ID and event platform; held in memory until restart.",
        "delay": "No additional trigger delay.",
        "ui": {
          "path": [
            "Bot",
            "Automations",
            "+ New",
            "When"
          ],
          "initialFields": [],
          "steps": [
            "Choose Trigger category: Broadcast software & installed apps.",
            "Choose Trigger event: Streamlabs Desktop scene collection change.",
            "Fill the Trigger filters below, set Cooldown (seconds), then open Where and choose a supported Platform.",
            "Open Do, add actions, then Create Automation or Save Changes."
          ]
        }
      }
    },
    {
      "id": "variable.trigger.streamlabs_collection_change.collection",
      "kind": "variable",
      "runtimeKey": "trigger.streamlabs_collection_change.collection",
      "label": "{collection}",
      "category": "Event variables",
      "summary": "New Streamlabs scene collection name.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.streamlabs_collection_change.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.streamlabs_collection_change"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{collection}"
        }
      ],
      "details": {
        "syntax": "{collection}",
        "canonicalKey": "collection",
        "aliases": [],
        "producer": "trigger.streamlabs_collection_change",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Blank selects any collection, otherwise exact selected collection ID equality."
      }
    },
    {
      "id": "variable.trigger.streamlabs_collection_change.previousCollection",
      "kind": "variable",
      "runtimeKey": "trigger.streamlabs_collection_change.previousCollection",
      "label": "{previousCollection}",
      "category": "Event variables",
      "summary": "Previous scene collection name.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.streamlabs_collection_change.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.streamlabs_collection_change"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{previousCollection}"
        }
      ],
      "details": {
        "syntax": "{previousCollection}",
        "canonicalKey": "previousCollection",
        "aliases": [],
        "producer": "trigger.streamlabs_collection_change",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Blank selects any collection, otherwise exact selected collection ID equality."
      }
    },
    {
      "id": "variable.trigger.streamlabs_collection_change.platform",
      "kind": "variable",
      "runtimeKey": "trigger.streamlabs_collection_change.platform",
      "label": "{platform}",
      "category": "Event variables",
      "summary": "Originating provider, including obs/streamlabs for local events; not necessarily a chat destination.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.streamlabs_collection_change.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.streamlabs_collection_change"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{platform}"
        }
      ],
      "details": {
        "syntax": "{platform}",
        "canonicalKey": "platform",
        "aliases": [],
        "producer": "trigger.streamlabs_collection_change",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "streamlabs",
        "behavior": "Blank selects any collection, otherwise exact selected collection ID equality."
      }
    },
    {
      "id": "trigger.streamlabs_scene_item_visibility",
      "kind": "trigger",
      "runtimeKey": "streamlabs_scene_item_visibility",
      "label": "Streamlabs Desktop scene item visibility",
      "category": "When",
      "summary": "Fires when one exact Streamlabs scene-item instance is shown or hidden. Leave the item blank for any identified item.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected supported event provider; enabled automation and matching filters.",
        "inboundProviders": [
          "streamlabs"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.streamlabs_scene_item_visibility"
        },
        {
          "path": "src/features/automation-provider-capabilities.js",
          "symbol": "AUTOMATION_TRIGGER_PLATFORMS.streamlabs_scene_item_visibility"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "variable.trigger.streamlabs_scene_item_visibility.scene",
        "variable.trigger.streamlabs_scene_item_visibility.source",
        "variable.trigger.streamlabs_scene_item_visibility.visibility",
        "variable.trigger.streamlabs_scene_item_visibility.previousVisibility",
        "variable.trigger.streamlabs_scene_item_visibility.platform",
        "context.automation"
      ],
      "examples": [
        {
          "purpose": "Trigger selection and filter defaults; supply a real target/pattern when required.",
          "format": "configuration",
          "value": {
            "triggerType": "streamlabs_scene_item_visibility",
            "triggerPlatform": "streamlabs",
            "triggerFilters": {
              "itemResourceId": "",
              "visibility": "shown"
            }
          }
        }
      ],
      "details": {
        "behavior": "Exact item resource ID if selected, otherwise any identified item. Visibility defaults shown. This is an instance event, not linked-source fanout.",
        "filters": [
          {
            "key": "itemResourceId",
            "type": "streamlabs_scene_item_dropdown",
            "label": "Scene item (blank = any)"
          },
          {
            "key": "visibility",
            "type": "select",
            "label": "When",
            "default": "shown",
            "options": [
              {
                "value": "shown",
                "label": "Shown"
              },
              {
                "value": "hidden",
                "label": "Hidden"
              }
            ]
          }
        ],
        "variableIds": [
          "variable.trigger.streamlabs_scene_item_visibility.scene",
          "variable.trigger.streamlabs_scene_item_visibility.source",
          "variable.trigger.streamlabs_scene_item_visibility.visibility",
          "variable.trigger.streamlabs_scene_item_visibility.previousVisibility",
          "variable.trigger.streamlabs_scene_item_visibility.platform"
        ],
        "cooldown": "Automation cooldownSec defaults 0; keyed by automation ID and event platform; held in memory until restart.",
        "delay": "No additional trigger delay.",
        "ui": {
          "path": [
            "Bot",
            "Automations",
            "+ New",
            "When"
          ],
          "initialFields": [],
          "steps": [
            "Choose Trigger category: Broadcast software & installed apps.",
            "Choose Trigger event: Streamlabs Desktop scene item visibility.",
            "Fill the Trigger filters below, set Cooldown (seconds), then open Where and choose a supported Platform.",
            "Open Do, add actions, then Create Automation or Save Changes."
          ]
        }
      }
    },
    {
      "id": "variable.trigger.streamlabs_scene_item_visibility.scene",
      "kind": "variable",
      "runtimeKey": "trigger.streamlabs_scene_item_visibility.scene",
      "label": "{scene}",
      "category": "Event variables",
      "summary": "New active scene name.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.streamlabs_scene_item_visibility.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.streamlabs_scene_item_visibility"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{scene}"
        }
      ],
      "details": {
        "syntax": "{scene}",
        "canonicalKey": "scene",
        "aliases": [],
        "producer": "trigger.streamlabs_scene_item_visibility",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Exact item resource ID if selected, otherwise any identified item. Visibility defaults shown. This is an instance event, not linked-source fanout."
      }
    },
    {
      "id": "variable.trigger.streamlabs_scene_item_visibility.source",
      "kind": "variable",
      "runtimeKey": "trigger.streamlabs_scene_item_visibility.source",
      "label": "{source}",
      "category": "Event variables",
      "summary": "Affected Streamlabs source name.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.streamlabs_scene_item_visibility.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.streamlabs_scene_item_visibility"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{source}"
        }
      ],
      "details": {
        "syntax": "{source}",
        "canonicalKey": "source",
        "aliases": [],
        "producer": "trigger.streamlabs_scene_item_visibility",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Exact item resource ID if selected, otherwise any identified item. Visibility defaults shown. This is an instance event, not linked-source fanout."
      }
    },
    {
      "id": "variable.trigger.streamlabs_scene_item_visibility.visibility",
      "kind": "variable",
      "runtimeKey": "trigger.streamlabs_scene_item_visibility.visibility",
      "label": "{visibility}",
      "category": "Event variables",
      "summary": "New scene-item visibility.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.streamlabs_scene_item_visibility.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.streamlabs_scene_item_visibility"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{visibility}"
        }
      ],
      "details": {
        "syntax": "{visibility}",
        "canonicalKey": "visibility",
        "aliases": [],
        "producer": "trigger.streamlabs_scene_item_visibility",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Exact item resource ID if selected, otherwise any identified item. Visibility defaults shown. This is an instance event, not linked-source fanout."
      }
    },
    {
      "id": "variable.trigger.streamlabs_scene_item_visibility.previousVisibility",
      "kind": "variable",
      "runtimeKey": "trigger.streamlabs_scene_item_visibility.previousVisibility",
      "label": "{previousVisibility}",
      "category": "Event variables",
      "summary": "Previous scene-item visibility.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.streamlabs_scene_item_visibility.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.streamlabs_scene_item_visibility"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{previousVisibility}"
        }
      ],
      "details": {
        "syntax": "{previousVisibility}",
        "canonicalKey": "previousVisibility",
        "aliases": [],
        "producer": "trigger.streamlabs_scene_item_visibility",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Exact item resource ID if selected, otherwise any identified item. Visibility defaults shown. This is an instance event, not linked-source fanout."
      }
    },
    {
      "id": "variable.trigger.streamlabs_scene_item_visibility.platform",
      "kind": "variable",
      "runtimeKey": "trigger.streamlabs_scene_item_visibility.platform",
      "label": "{platform}",
      "category": "Event variables",
      "summary": "Originating provider, including obs/streamlabs for local events; not necessarily a chat destination.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.streamlabs_scene_item_visibility.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.streamlabs_scene_item_visibility"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{platform}"
        }
      ],
      "details": {
        "syntax": "{platform}",
        "canonicalKey": "platform",
        "aliases": [],
        "producer": "trigger.streamlabs_scene_item_visibility",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "streamlabs",
        "behavior": "Exact item resource ID if selected, otherwise any identified item. Visibility defaults shown. This is an instance event, not linked-source fanout."
      }
    },
    {
      "id": "trigger.streamlabs_source_mute",
      "kind": "trigger",
      "runtimeKey": "streamlabs_source_mute",
      "label": "Streamlabs Desktop source mute change",
      "category": "When",
      "summary": "Fires when an identified Streamlabs source is muted or unmuted. Leave the source blank for any identified source.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected supported event provider; enabled automation and matching filters.",
        "inboundProviders": [
          "streamlabs"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.streamlabs_source_mute"
        },
        {
          "path": "src/features/automation-provider-capabilities.js",
          "symbol": "AUTOMATION_TRIGGER_PLATFORMS.streamlabs_source_mute"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "variable.trigger.streamlabs_source_mute.source",
        "variable.trigger.streamlabs_source_mute.muteState",
        "variable.trigger.streamlabs_source_mute.previousMuteState",
        "variable.trigger.streamlabs_source_mute.platform",
        "context.automation"
      ],
      "examples": [
        {
          "purpose": "Trigger selection and filter defaults; supply a real target/pattern when required.",
          "format": "configuration",
          "value": {
            "triggerType": "streamlabs_source_mute",
            "triggerPlatform": "streamlabs",
            "triggerFilters": {
              "sourceId": "",
              "muteState": "muted"
            }
          }
        }
      ],
      "details": {
        "behavior": "Exact source ID if selected, otherwise any identified audio source. State defaults muted.",
        "filters": [
          {
            "key": "sourceId",
            "type": "streamlabs_audio_source_dropdown",
            "label": "Audio source (blank = any)"
          },
          {
            "key": "muteState",
            "type": "select",
            "label": "When",
            "default": "muted",
            "options": [
              {
                "value": "muted",
                "label": "Muted"
              },
              {
                "value": "unmuted",
                "label": "Unmuted"
              }
            ]
          }
        ],
        "variableIds": [
          "variable.trigger.streamlabs_source_mute.source",
          "variable.trigger.streamlabs_source_mute.muteState",
          "variable.trigger.streamlabs_source_mute.previousMuteState",
          "variable.trigger.streamlabs_source_mute.platform"
        ],
        "cooldown": "Automation cooldownSec defaults 0; keyed by automation ID and event platform; held in memory until restart.",
        "delay": "No additional trigger delay.",
        "ui": {
          "path": [
            "Bot",
            "Automations",
            "+ New",
            "When"
          ],
          "initialFields": [],
          "steps": [
            "Choose Trigger category: Broadcast software & installed apps.",
            "Choose Trigger event: Streamlabs Desktop source mute change.",
            "Fill the Trigger filters below, set Cooldown (seconds), then open Where and choose a supported Platform.",
            "Open Do, add actions, then Create Automation or Save Changes."
          ]
        }
      }
    },
    {
      "id": "variable.trigger.streamlabs_source_mute.source",
      "kind": "variable",
      "runtimeKey": "trigger.streamlabs_source_mute.source",
      "label": "{source}",
      "category": "Event variables",
      "summary": "Affected Streamlabs source name.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.streamlabs_source_mute.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.streamlabs_source_mute"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{source}"
        }
      ],
      "details": {
        "syntax": "{source}",
        "canonicalKey": "source",
        "aliases": [],
        "producer": "trigger.streamlabs_source_mute",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Exact source ID if selected, otherwise any identified audio source. State defaults muted."
      }
    },
    {
      "id": "variable.trigger.streamlabs_source_mute.muteState",
      "kind": "variable",
      "runtimeKey": "trigger.streamlabs_source_mute.muteState",
      "label": "{muteState}",
      "category": "Event variables",
      "summary": "New source mute state.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.streamlabs_source_mute.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.streamlabs_source_mute"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{muteState}"
        }
      ],
      "details": {
        "syntax": "{muteState}",
        "canonicalKey": "muteState",
        "aliases": [],
        "producer": "trigger.streamlabs_source_mute",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Exact source ID if selected, otherwise any identified audio source. State defaults muted."
      }
    },
    {
      "id": "variable.trigger.streamlabs_source_mute.previousMuteState",
      "kind": "variable",
      "runtimeKey": "trigger.streamlabs_source_mute.previousMuteState",
      "label": "{previousMuteState}",
      "category": "Event variables",
      "summary": "Previous source mute state.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.streamlabs_source_mute.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.streamlabs_source_mute"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{previousMuteState}"
        }
      ],
      "details": {
        "syntax": "{previousMuteState}",
        "canonicalKey": "previousMuteState",
        "aliases": [],
        "producer": "trigger.streamlabs_source_mute",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Exact source ID if selected, otherwise any identified audio source. State defaults muted."
      }
    },
    {
      "id": "variable.trigger.streamlabs_source_mute.platform",
      "kind": "variable",
      "runtimeKey": "trigger.streamlabs_source_mute.platform",
      "label": "{platform}",
      "category": "Event variables",
      "summary": "Originating provider, including obs/streamlabs for local events; not necessarily a chat destination.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.streamlabs_source_mute.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.streamlabs_source_mute"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{platform}"
        }
      ],
      "details": {
        "syntax": "{platform}",
        "canonicalKey": "platform",
        "aliases": [],
        "producer": "trigger.streamlabs_source_mute",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "streamlabs",
        "behavior": "Exact source ID if selected, otherwise any identified audio source. State defaults muted."
      }
    },
    {
      "id": "trigger.chat_contains",
      "kind": "trigger",
      "runtimeKey": "chat_contains",
      "label": "Chat message contains / equals",
      "category": "When",
      "summary": "Fires when a chat message matches a keyword, pattern, or exact phrase.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Connected supported event provider; enabled automation and matching filters.",
        "inboundProviders": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.chat_contains"
        },
        {
          "path": "src/features/automation-provider-capabilities.js",
          "symbol": "AUTOMATION_TRIGGER_PLATFORMS.chat_contains"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Minimum authority is exposed in the editor but is not enforced by this matcher."
      ],
      "relatedIds": [
        "variable.trigger.chat_contains.user",
        "variable.trigger.chat_contains.username",
        "variable.trigger.chat_contains.message",
        "variable.trigger.chat_contains.match",
        "context.automation"
      ],
      "examples": [
        {
          "purpose": "Trigger selection and filter defaults; supply a real target/pattern when required.",
          "format": "configuration",
          "value": {
            "triggerType": "chat_contains",
            "triggerPlatform": "all",
            "triggerFilters": {
              "pattern": "",
              "matchMode": "contains",
              "authority": "anyone"
            }
          }
        }
      ],
      "details": {
        "behavior": "Nonempty pattern required. Equals compares trimmed text case-insensitively. Contains treats ordinary text literally; /pattern/flags uses JavaScript regex, invalid regex never matches. The authority field is displayed but match() does not enforce it; do not rely on this filter as an access-control gate.",
        "filters": [
          {
            "key": "pattern",
            "type": "text",
            "label": "Keyword or regex (wrap in /.../ for regex)",
            "placeholder": "hello|hi there"
          },
          {
            "key": "matchMode",
            "type": "select",
            "label": "Match mode",
            "options": [
              {
                "value": "contains",
                "label": "Contains (default)"
              },
              {
                "value": "equals",
                "label": "Equals (exact match)"
              }
            ]
          },
          {
            "key": "authority",
            "type": "select",
            "label": "Minimum authority",
            "options": [
              {
                "value": "anyone",
                "label": "Anyone"
              },
              {
                "value": "subscriber",
                "label": "Subscriber+"
              },
              {
                "value": "moderator",
                "label": "Moderator+"
              },
              {
                "value": "broadcaster",
                "label": "Broadcaster only"
              }
            ]
          }
        ],
        "variableIds": [
          "variable.trigger.chat_contains.user",
          "variable.trigger.chat_contains.username",
          "variable.trigger.chat_contains.message",
          "variable.trigger.chat_contains.match"
        ],
        "cooldown": "Automation cooldownSec defaults 0; keyed by automation ID and event platform; held in memory until restart.",
        "delay": "No additional trigger delay.",
        "ui": {
          "path": [
            "Bot",
            "Automations",
            "+ New",
            "When"
          ],
          "initialFields": [],
          "steps": [
            "Choose Trigger category: Chat & viewers.",
            "Choose Trigger event: Chat message contains / equals.",
            "Fill the Trigger filters below, set Cooldown (seconds), then open Where and choose a supported Platform.",
            "Open Do, add actions, then Create Automation or Save Changes."
          ]
        }
      }
    },
    {
      "id": "variable.trigger.chat_contains.user",
      "kind": "variable",
      "runtimeKey": "trigger.chat_contains.user",
      "label": "{user}",
      "category": "Event variables",
      "summary": "Viewer display name/username supplied by this event; outgoing raids use destination identity.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.chat_contains.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.chat_contains"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{user}"
        }
      ],
      "details": {
        "syntax": "{user}",
        "canonicalKey": "user",
        "aliases": [],
        "producer": "trigger.chat_contains",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": null,
        "behavior": "Nonempty pattern required. Equals compares trimmed text case-insensitively. Contains treats ordinary text literally; /pattern/flags uses JavaScript regex, invalid regex never matches. The authority field is displayed but match() does not enforce it; do not rely on this filter as an access-control gate."
      }
    },
    {
      "id": "variable.trigger.chat_contains.username",
      "kind": "variable",
      "runtimeKey": "trigger.chat_contains.username",
      "label": "{username}",
      "category": "Event variables",
      "summary": "Normalized or provider-supplied event username, not an arbitrary command argument.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.chat_contains.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.chat_contains"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{username}"
        }
      ],
      "details": {
        "syntax": "{username}",
        "canonicalKey": "username",
        "aliases": [],
        "producer": "trigger.chat_contains",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": null,
        "behavior": "Nonempty pattern required. Equals compares trimmed text case-insensitively. Contains treats ordinary text literally; /pattern/flags uses JavaScript regex, invalid regex never matches. The authority field is displayed but match() does not enforce it; do not rely on this filter as an access-control gate."
      }
    },
    {
      "id": "variable.trigger.chat_contains.message",
      "kind": "variable",
      "runtimeKey": "trigger.chat_contains.message",
      "label": "{message}",
      "category": "Event variables",
      "summary": "Event text; reward redemptions use viewer input, TikTok questions use the question text.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.chat_contains.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.chat_contains"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{message}"
        }
      ],
      "details": {
        "syntax": "{message}",
        "canonicalKey": "message",
        "aliases": [],
        "producer": "trigger.chat_contains",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Nonempty pattern required. Equals compares trimmed text case-insensitively. Contains treats ordinary text literally; /pattern/flags uses JavaScript regex, invalid regex never matches. The authority field is displayed but match() does not enforce it; do not rely on this filter as an access-control gate."
      }
    },
    {
      "id": "variable.trigger.chat_contains.match",
      "kind": "variable",
      "runtimeKey": "trigger.chat_contains.match",
      "label": "{match}",
      "category": "Event variables",
      "summary": "Matched literal/regex substring; equals mode uses the complete trimmed matching text.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "TRIGGER_REGISTRY.chat_contains.extract"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "trigger.chat_contains"
      ],
      "examples": [
        {
          "purpose": "Only use with this trigger and a field that supports variables.",
          "format": "template",
          "value": "{match}"
        }
      ],
      "details": {
        "syntax": "{match}",
        "canonicalKey": "match",
        "aliases": [],
        "producer": "trigger.chat_contains",
        "lifetime": "Current action sequence.",
        "resolution": "Produced by event extraction. Missing provider values use the extractor fallback.",
        "emptyEventFallback": "",
        "behavior": "Nonempty pattern required. Equals compares trimmed text case-insensitively. Contains treats ordinary text literally; /pattern/flags uses JavaScript regex, invalid regex never matches. The authority field is displayed but match() does not enforce it; do not rely on this filter as an access-control gate."
      }
    },
    {
      "id": "variable.global.user",
      "kind": "variable",
      "runtimeKey": "global.user",
      "label": "{user}",
      "category": "User",
      "summary": "Command sender display name",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.user"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{user}"
        }
      ],
      "details": {
        "key": "user",
        "aliases": [
          "sender"
        ],
        "category": "User",
        "description": "Command sender display name",
        "canonicalKey": "user",
        "syntax": "{user}",
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Command sender display name",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.sender.name",
      "kind": "variable",
      "runtimeKey": "global.sender.name",
      "label": "{sender.name}",
      "category": "User",
      "summary": "Command sender normalized username",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.sender.name"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{sender.name}"
        }
      ],
      "details": {
        "key": "sender.name",
        "category": "User",
        "description": "Command sender normalized username",
        "canonicalKey": "sender.name",
        "syntax": "{sender.name}",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Command sender normalized username",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.sender.id",
      "kind": "variable",
      "runtimeKey": "global.sender.id",
      "label": "{sender.id}",
      "category": "User",
      "summary": "Platform user ID when supplied by chat",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Depends on the incoming platform event",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.sender.id"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{sender.id}"
        }
      ],
      "details": {
        "key": "sender.id",
        "category": "User",
        "description": "Platform user ID when supplied by chat",
        "availability": "runtime",
        "availabilityNote": "Depends on the incoming platform event",
        "canonicalKey": "sender.id",
        "syntax": "{sender.id}",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Platform user ID when supplied by chat",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.platform.userUrl",
      "kind": "variable",
      "runtimeKey": "global.platform.userUrl",
      "label": "{platform.userUrl}",
      "category": "User",
      "summary": "Profile URL for the command sender on the current platform",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "YouTube prefers channel ID when supplied; otherwise uses the visible username as a handle.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.platform.userUrl"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{platform.userUrl}"
        }
      ],
      "details": {
        "key": "platform.userUrl",
        "aliases": [
          "sender.url",
          "user.url",
          "profile.url"
        ],
        "category": "User",
        "description": "Profile URL for the command sender on the current platform",
        "availability": "runtime",
        "availabilityNote": "YouTube prefers channel ID when supplied; otherwise uses the visible username as a handle.",
        "platforms": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ],
        "canonicalKey": "platform.userUrl",
        "syntax": "{platform.userUrl}",
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Profile URL for the command sender on the current platform",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.sender.points",
      "kind": "variable",
      "runtimeKey": "global.sender.points",
      "label": "{sender.points}",
      "category": "Loyalty",
      "summary": "Command sender current loyalty currency",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.sender.points"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{sender.points}"
        }
      ],
      "details": {
        "key": "sender.points",
        "aliases": [
          "user.points"
        ],
        "category": "Loyalty",
        "description": "Command sender current loyalty currency",
        "canonicalKey": "sender.points",
        "syntax": "{sender.points}",
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Command sender current loyalty currency",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.sender.pointsRank",
      "kind": "variable",
      "runtimeKey": "global.sender.pointsRank",
      "label": "{sender.pointsRank}",
      "category": "Loyalty",
      "summary": "Command sender loyalty rank",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.sender.pointsRank"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{sender.pointsRank}"
        }
      ],
      "details": {
        "key": "sender.pointsRank",
        "aliases": [
          "user.pointsRank"
        ],
        "category": "Loyalty",
        "description": "Command sender loyalty rank",
        "canonicalKey": "sender.pointsRank",
        "syntax": "{sender.pointsRank}",
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Command sender loyalty rank",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.target",
      "kind": "variable",
      "runtimeKey": "global.target",
      "label": "{target}",
      "category": "User",
      "summary": "First argument as a username, falling back to sender",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.target"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{target}"
        }
      ],
      "details": {
        "key": "target",
        "category": "User",
        "description": "First argument as a username, falling back to sender",
        "canonicalKey": "target",
        "syntax": "{target}",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "First argument as a username, falling back to sender",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.target.name",
      "kind": "variable",
      "runtimeKey": "global.target.name",
      "label": "{target.name}",
      "category": "User",
      "summary": "Target normalized username",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.target.name"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{target.name}"
        }
      ],
      "details": {
        "key": "target.name",
        "category": "User",
        "description": "Target normalized username",
        "canonicalKey": "target.name",
        "syntax": "{target.name}",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Target normalized username",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.target.url",
      "kind": "variable",
      "runtimeKey": "global.target.url",
      "label": "{target.url}",
      "category": "User",
      "summary": "Profile URL for the target username on the current platform",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.target.url"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{target.url}"
        }
      ],
      "details": {
        "key": "target.url",
        "category": "User",
        "description": "Profile URL for the target username on the current platform",
        "platforms": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ],
        "canonicalKey": "target.url",
        "syntax": "{target.url}",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Profile URL for the target username on the current platform",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.target.game",
      "kind": "variable",
      "runtimeKey": "global.target.game",
      "label": "{target.game}",
      "category": "User",
      "summary": "Target channel category/game on the current platform",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Twitch and Kick only. Returns Unavailable when unsupported or when channel metadata is unavailable.",
        "providers": [
          "twitch",
          "kick"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.target.game"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{target.game}"
        }
      ],
      "details": {
        "key": "target.game",
        "aliases": [
          "target.category"
        ],
        "category": "User",
        "description": "Target channel category/game on the current platform",
        "availability": "runtime",
        "availabilityNote": "Twitch and Kick only. Returns Unavailable when unsupported or when channel metadata is unavailable.",
        "platforms": [
          "twitch",
          "kick"
        ],
        "canonicalKey": "target.game",
        "syntax": "{target.game}",
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Target channel category/game on the current platform",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.target.title",
      "kind": "variable",
      "runtimeKey": "global.target.title",
      "label": "{target.title}",
      "category": "User",
      "summary": "Target channel title on the current platform",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Twitch and Kick only. Returns Unavailable when unsupported or when channel metadata is unavailable.",
        "providers": [
          "twitch",
          "kick"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.target.title"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{target.title}"
        }
      ],
      "details": {
        "key": "target.title",
        "aliases": [
          "target.stream_title"
        ],
        "category": "User",
        "description": "Target channel title on the current platform",
        "availability": "runtime",
        "availabilityNote": "Twitch and Kick only. Returns Unavailable when unsupported or when channel metadata is unavailable.",
        "platforms": [
          "twitch",
          "kick"
        ],
        "canonicalKey": "target.title",
        "syntax": "{target.title}",
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Target channel title on the current platform",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.target.points",
      "kind": "variable",
      "runtimeKey": "global.target.points",
      "label": "{target.points}",
      "category": "Loyalty",
      "summary": "Target current loyalty currency on this platform",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.target.points"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{target.points}"
        }
      ],
      "details": {
        "key": "target.points",
        "category": "Loyalty",
        "description": "Target current loyalty currency on this platform",
        "canonicalKey": "target.points",
        "syntax": "{target.points}",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Target current loyalty currency on this platform",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.target.pointsRank",
      "kind": "variable",
      "runtimeKey": "global.target.pointsRank",
      "label": "{target.pointsRank}",
      "category": "Loyalty",
      "summary": "Target loyalty rank",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.target.pointsRank"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{target.pointsRank}"
        }
      ],
      "details": {
        "key": "target.pointsRank",
        "category": "Loyalty",
        "description": "Target loyalty rank",
        "canonicalKey": "target.pointsRank",
        "syntax": "{target.pointsRank}",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Target loyalty rank",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.message",
      "kind": "variable",
      "runtimeKey": "global.message",
      "label": "{message}",
      "category": "Command",
      "summary": "All text entered after the command",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.message"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{message}"
        }
      ],
      "details": {
        "key": "message",
        "aliases": [
          "args"
        ],
        "category": "Command",
        "description": "All text entered after the command",
        "canonicalKey": "message",
        "syntax": "{message}",
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "All text entered after the command",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.messageSuffix",
      "kind": "variable",
      "runtimeKey": "global.messageSuffix",
      "label": "{messageSuffix}",
      "category": "Command",
      "summary": "Optional command text wrapped for a natural reply",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.messageSuffix"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{messageSuffix}"
        }
      ],
      "details": {
        "key": "messageSuffix",
        "category": "Command",
        "description": "Optional command text wrapped for a natural reply",
        "canonicalKey": "messageSuffix",
        "syntax": "{messageSuffix}",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Optional command text wrapped for a natural reply",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.arg",
      "kind": "variable",
      "runtimeKey": "global.arg",
      "label": "{arg:1}",
      "category": "Command",
      "summary": "One command argument, numbered from 1",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.arg"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{arg:1}"
        }
      ],
      "details": {
        "key": "arg",
        "syntax": "{arg:1}",
        "category": "Command",
        "description": "One command argument, numbered from 1",
        "fallback": "",
        "canonicalKey": "arg",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "One-based argument index; missing/invalid index uses 1; missing argument is empty.",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.command",
      "kind": "variable",
      "runtimeKey": "global.command",
      "label": "{command}",
      "category": "Command",
      "summary": "Command name without its prefix",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.command"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{command}"
        }
      ],
      "details": {
        "key": "command",
        "category": "Command",
        "description": "Command name without its prefix",
        "canonicalKey": "command",
        "syntax": "{command}",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Command name without its prefix",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.messageId",
      "kind": "variable",
      "runtimeKey": "global.messageId",
      "label": "{messageId}",
      "category": "Command",
      "summary": "Triggering platform message ID when available",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Depends on the incoming platform event",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.messageId"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{messageId}"
        }
      ],
      "details": {
        "key": "messageId",
        "category": "Command",
        "description": "Triggering platform message ID when available",
        "availability": "runtime",
        "availabilityNote": "Depends on the incoming platform event",
        "canonicalKey": "messageId",
        "syntax": "{messageId}",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Triggering platform message ID when available",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.platform",
      "kind": "variable",
      "runtimeKey": "global.platform",
      "label": "{platform}",
      "category": "Channel",
      "summary": "Platform where the command was used",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.platform"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{platform}"
        }
      ],
      "details": {
        "key": "platform",
        "category": "Channel",
        "description": "Platform where the command was used",
        "canonicalKey": "platform",
        "syntax": "{platform}",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Platform where the command was used",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.role",
      "kind": "variable",
      "runtimeKey": "global.role",
      "label": "{role}",
      "category": "Authority",
      "summary": "Viewer highest normalized authority role",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.role"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{role}"
        }
      ],
      "details": {
        "key": "role",
        "category": "Authority",
        "description": "Viewer highest normalized authority role",
        "canonicalKey": "role",
        "syntax": "{role}",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Viewer highest normalized authority role",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.roles",
      "kind": "variable",
      "runtimeKey": "global.roles",
      "label": "{roles}",
      "category": "Authority",
      "summary": "All normalized viewer roles, comma-separated",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.roles"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{roles}"
        }
      ],
      "details": {
        "key": "roles",
        "category": "Authority",
        "description": "All normalized viewer roles, comma-separated",
        "canonicalKey": "roles",
        "syntax": "{roles}",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "All normalized viewer roles, comma-separated",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.authorityLevel",
      "kind": "variable",
      "runtimeKey": "global.authorityLevel",
      "label": "{authorityLevel}",
      "category": "Authority",
      "summary": "Normalized numeric authority level",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.authorityLevel"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{authorityLevel}"
        }
      ],
      "details": {
        "key": "authorityLevel",
        "category": "Authority",
        "description": "Normalized numeric authority level",
        "canonicalKey": "authorityLevel",
        "syntax": "{authorityLevel}",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Normalized numeric authority level",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.pointsName",
      "kind": "variable",
      "runtimeKey": "global.pointsName",
      "label": "{pointsName}",
      "category": "Loyalty",
      "summary": "Configured loyalty currency name",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.pointsName"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{pointsName}"
        }
      ],
      "details": {
        "key": "pointsName",
        "category": "Loyalty",
        "description": "Configured loyalty currency name",
        "canonicalKey": "pointsName",
        "syntax": "{pointsName}",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Configured loyalty currency name",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.counter",
      "kind": "variable",
      "runtimeKey": "global.counter",
      "label": "{counter:deaths}",
      "category": "Counters",
      "summary": "Read a platform-specific counter, then fall back to global",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.counter"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{counter:deaths}"
        }
      ],
      "details": {
        "key": "counter",
        "syntax": "{counter:deaths}",
        "category": "Counters",
        "description": "Read a platform-specific counter, then fall back to global",
        "fallback": "0",
        "canonicalKey": "counter",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Arguments: optional global/platform scope, then counter name. Auto scope checks platform then global. Missing value is 0.",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.usercounter",
      "kind": "variable",
      "runtimeKey": "global.usercounter",
      "label": "{usercounter:Check In}",
      "category": "Counters",
      "summary": "Read the command sender value inside a user counter category",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.usercounter"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{usercounter:Check In}"
        }
      ],
      "details": {
        "key": "usercounter",
        "syntax": "{usercounter:Check In}",
        "category": "Counters",
        "description": "Read the command sender value inside a user counter category",
        "fallback": "0",
        "canonicalKey": "usercounter",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Category name may contain spaces/colons. Reads sender value, missing/invalid category returns 0.",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.target.usercounter",
      "kind": "variable",
      "runtimeKey": "global.target.usercounter",
      "label": "{target.usercounter:Check In}",
      "category": "Counters",
      "summary": "Read the target viewer value inside a user counter category",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.target.usercounter"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{target.usercounter:Check In}"
        }
      ],
      "details": {
        "key": "target.usercounter",
        "syntax": "{target.usercounter:Check In}",
        "category": "Counters",
        "description": "Read the target viewer value inside a user counter category",
        "fallback": "0",
        "canonicalKey": "target.usercounter",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Category name may contain spaces/colons. Reads target value; missing/invalid category returns 0.",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.channel",
      "kind": "variable",
      "runtimeKey": "global.channel",
      "label": "{channel}",
      "category": "Channel",
      "summary": "Connected channel username",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.channel"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{channel}"
        }
      ],
      "details": {
        "key": "channel",
        "category": "Channel",
        "description": "Connected channel username",
        "canonicalKey": "channel",
        "syntax": "{channel}",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Connected channel username",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.channel.displayName",
      "kind": "variable",
      "runtimeKey": "global.channel.displayName",
      "label": "{channel.displayName}",
      "category": "Channel",
      "summary": "Connected channel display name",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.channel.displayName"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{channel.displayName}"
        }
      ],
      "details": {
        "key": "channel.displayName",
        "category": "Channel",
        "description": "Connected channel display name",
        "canonicalKey": "channel.displayName",
        "syntax": "{channel.displayName}",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Connected channel display name",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.channel.id",
      "kind": "variable",
      "runtimeKey": "global.channel.id",
      "label": "{channel.id}",
      "category": "Channel",
      "summary": "Platform channel ID",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.channel.id"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{channel.id}"
        }
      ],
      "details": {
        "key": "channel.id",
        "category": "Channel",
        "description": "Platform channel ID",
        "canonicalKey": "channel.id",
        "syntax": "{channel.id}",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Platform channel ID",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.channel.platform",
      "kind": "variable",
      "runtimeKey": "global.channel.platform",
      "label": "{channel.platform}",
      "category": "Channel",
      "summary": "Connected platform name",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.channel.platform"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{channel.platform}"
        }
      ],
      "details": {
        "key": "channel.platform",
        "category": "Channel",
        "description": "Connected platform name",
        "canonicalKey": "channel.platform",
        "syntax": "{channel.platform}",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Connected platform name",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.channel.isLive",
      "kind": "variable",
      "runtimeKey": "global.channel.isLive",
      "label": "{channel.isLive}",
      "category": "Stream",
      "summary": "Whether the current platform is live",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.channel.isLive"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{channel.isLive}"
        }
      ],
      "details": {
        "key": "channel.isLive",
        "category": "Stream",
        "description": "Whether the current platform is live",
        "canonicalKey": "channel.isLive",
        "syntax": "{channel.isLive}",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Whether the current platform is live",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.channel.chatters",
      "kind": "variable",
      "runtimeKey": "global.channel.chatters",
      "label": "{channel.chatters}",
      "category": "Stream",
      "summary": "Chatters observed in the current session",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.channel.chatters"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{channel.chatters}"
        }
      ],
      "details": {
        "key": "channel.chatters",
        "category": "Stream",
        "description": "Chatters observed in the current session",
        "canonicalKey": "channel.chatters",
        "syntax": "{channel.chatters}",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Chatters observed in the current session",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.channel.viewers",
      "kind": "variable",
      "runtimeKey": "global.channel.viewers",
      "label": "{channel.viewers}",
      "category": "Stream",
      "summary": "Current viewer count when exposed by the platform",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Available while the platform API exposes live viewer data",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.channel.viewers"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{channel.viewers}"
        }
      ],
      "details": {
        "key": "channel.viewers",
        "category": "Stream",
        "description": "Current viewer count when exposed by the platform",
        "availability": "runtime",
        "availabilityNote": "Available while the platform API exposes live viewer data",
        "canonicalKey": "channel.viewers",
        "syntax": "{channel.viewers}",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Current viewer count when exposed by the platform",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.tiktok.viewerCount",
      "kind": "variable",
      "runtimeKey": "global.tiktok.viewerCount",
      "label": "{tiktok.viewerCount}",
      "category": "Stream",
      "summary": "Current TikTok LIVE viewer count",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.tiktok.viewerCount"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{tiktok.viewerCount}"
        }
      ],
      "details": {
        "key": "tiktok.viewerCount",
        "category": "Stream",
        "description": "Current TikTok LIVE viewer count",
        "platforms": [
          "tiktok"
        ],
        "availability": "runtime",
        "canonicalKey": "tiktok.viewerCount",
        "syntax": "{tiktok.viewerCount}",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Current TikTok LIVE viewer count",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.tiktok.totalLikes",
      "kind": "variable",
      "runtimeKey": "global.tiktok.totalLikes",
      "label": "{tiktok.totalLikes}",
      "category": "Stream",
      "summary": "Current TikTok LIVE total likes",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.tiktok.totalLikes"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{tiktok.totalLikes}"
        }
      ],
      "details": {
        "key": "tiktok.totalLikes",
        "category": "Stream",
        "description": "Current TikTok LIVE total likes",
        "platforms": [
          "tiktok"
        ],
        "availability": "runtime",
        "canonicalKey": "tiktok.totalLikes",
        "syntax": "{tiktok.totalLikes}",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Current TikTok LIVE total likes",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.tiktok.roomId",
      "kind": "variable",
      "runtimeKey": "global.tiktok.roomId",
      "label": "{tiktok.roomId}",
      "category": "Stream",
      "summary": "Current TikTok LIVE room identifier",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.tiktok.roomId"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{tiktok.roomId}"
        }
      ],
      "details": {
        "key": "tiktok.roomId",
        "category": "Stream",
        "description": "Current TikTok LIVE room identifier",
        "platforms": [
          "tiktok"
        ],
        "availability": "runtime",
        "canonicalKey": "tiktok.roomId",
        "syntax": "{tiktok.roomId}",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Current TikTok LIVE room identifier",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.tiktok.goalProgress",
      "kind": "variable",
      "runtimeKey": "global.tiktok.goalProgress",
      "label": "{tiktok.goalProgress}",
      "category": "Stream",
      "summary": "Current TikTok LIVE goal progress",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.tiktok.goalProgress"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{tiktok.goalProgress}"
        }
      ],
      "details": {
        "key": "tiktok.goalProgress",
        "category": "Stream",
        "description": "Current TikTok LIVE goal progress",
        "platforms": [
          "tiktok"
        ],
        "availability": "runtime",
        "canonicalKey": "tiktok.goalProgress",
        "syntax": "{tiktok.goalProgress}",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Current TikTok LIVE goal progress",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.tiktok.goalTarget",
      "kind": "variable",
      "runtimeKey": "global.tiktok.goalTarget",
      "label": "{tiktok.goalTarget}",
      "category": "Stream",
      "summary": "Current TikTok LIVE goal target",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.tiktok.goalTarget"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{tiktok.goalTarget}"
        }
      ],
      "details": {
        "key": "tiktok.goalTarget",
        "category": "Stream",
        "description": "Current TikTok LIVE goal target",
        "platforms": [
          "tiktok"
        ],
        "availability": "runtime",
        "canonicalKey": "tiktok.goalTarget",
        "syntax": "{tiktok.goalTarget}",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Current TikTok LIVE goal target",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.channel.title",
      "kind": "variable",
      "runtimeKey": "global.channel.title",
      "label": "{channel.title}",
      "category": "Stream",
      "summary": "Current stream title",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Requires accessible channel or live-stream data",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.channel.title"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{channel.title}"
        }
      ],
      "details": {
        "key": "channel.title",
        "aliases": [
          "title"
        ],
        "category": "Stream",
        "description": "Current stream title",
        "availability": "runtime",
        "availabilityNote": "Requires accessible channel or live-stream data",
        "canonicalKey": "channel.title",
        "syntax": "{channel.title}",
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Current stream title",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.channel.category",
      "kind": "variable",
      "runtimeKey": "global.channel.category",
      "label": "{channel.category}",
      "category": "Stream",
      "summary": "Current stream category or game",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Requires accessible channel or live-stream data",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.channel.category"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{channel.category}"
        }
      ],
      "details": {
        "key": "channel.category",
        "aliases": [
          "game"
        ],
        "category": "Stream",
        "description": "Current stream category or game",
        "availability": "runtime",
        "availabilityNote": "Requires accessible channel or live-stream data",
        "canonicalKey": "channel.category",
        "syntax": "{channel.category}",
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Current stream category or game",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.channel.uptime",
      "kind": "variable",
      "runtimeKey": "global.channel.uptime",
      "label": "{channel.uptime}",
      "category": "Stream",
      "summary": "Current live duration",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Available when a live start time is known",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.channel.uptime"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{channel.uptime}"
        }
      ],
      "details": {
        "key": "channel.uptime",
        "aliases": [
          "uptime"
        ],
        "category": "Stream",
        "description": "Current live duration",
        "availability": "runtime",
        "availabilityNote": "Available when a live start time is known",
        "canonicalKey": "channel.uptime",
        "syntax": "{channel.uptime}",
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Current live duration",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.sender.game",
      "kind": "variable",
      "runtimeKey": "global.sender.game",
      "label": "{sender.game}",
      "category": "User",
      "summary": "The sender's channel category/game on the current platform",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Twitch and Kick only. Returns Unavailable when unsupported or when channel metadata is unavailable.",
        "providers": [
          "twitch",
          "kick"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.sender.game"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{sender.game}"
        }
      ],
      "details": {
        "key": "sender.game",
        "aliases": [
          "sender.category"
        ],
        "category": "User",
        "description": "The sender's channel category/game on the current platform",
        "availability": "runtime",
        "availabilityNote": "Twitch and Kick only. Returns Unavailable when unsupported or when channel metadata is unavailable.",
        "platforms": [
          "twitch",
          "kick"
        ],
        "canonicalKey": "sender.game",
        "syntax": "{sender.game}",
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "The sender's channel category/game on the current platform",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.sender.stream_title",
      "kind": "variable",
      "runtimeKey": "global.sender.stream_title",
      "label": "{sender.stream_title}",
      "category": "User",
      "summary": "The sender's channel title on the current platform",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Twitch and Kick only. Returns Unavailable when unsupported or when channel metadata is unavailable.",
        "providers": [
          "twitch",
          "kick"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.sender.stream_title"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{sender.stream_title}"
        }
      ],
      "details": {
        "key": "sender.stream_title",
        "aliases": [
          "sender.title"
        ],
        "category": "User",
        "description": "The sender's channel title on the current platform",
        "availability": "runtime",
        "availabilityNote": "Twitch and Kick only. Returns Unavailable when unsupported or when channel metadata is unavailable.",
        "platforms": [
          "twitch",
          "kick"
        ],
        "canonicalKey": "sender.stream_title",
        "syntax": "{sender.stream_title}",
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "The sender's channel title on the current platform",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.time",
      "kind": "variable",
      "runtimeKey": "global.time",
      "label": "{time:America/Los_Angeles}",
      "category": "Time",
      "summary": "Current time, optionally in an IANA timezone",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.time"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{time:America/Los_Angeles}"
        }
      ],
      "details": {
        "key": "time",
        "syntax": "{time:America/Los_Angeles}",
        "category": "Time",
        "description": "Current time, optionally in an IANA timezone",
        "canonicalKey": "time",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Optional IANA timezone. Invalid timezone falls back to Unavailable; display follows host locale.",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.date",
      "kind": "variable",
      "runtimeKey": "global.date",
      "label": "{date:America/Los_Angeles}",
      "category": "Time",
      "summary": "Current date, optionally in an IANA timezone",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.date"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{date:America/Los_Angeles}"
        }
      ],
      "details": {
        "key": "date",
        "syntax": "{date:America/Los_Angeles}",
        "category": "Time",
        "description": "Current date, optionally in an IANA timezone",
        "canonicalKey": "date",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Optional IANA timezone. Invalid timezone falls back to Unavailable; display follows host locale.",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.countdown",
      "kind": "variable",
      "runtimeKey": "global.countdown",
      "label": "{countdown:2026-12-31 23:59}",
      "category": "Time",
      "summary": "Time remaining until a target date/time (YYYY-MM-DD or YYYY-MM-DD HH:MM)",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.countdown"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{countdown:2026-12-31 23:59}"
        }
      ],
      "details": {
        "key": "countdown",
        "syntax": "{countdown:2026-12-31 23:59}",
        "category": "Time",
        "description": "Time remaining until a target date/time (YYYY-MM-DD or YYYY-MM-DD HH:MM)",
        "canonicalKey": "countdown",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Rejoin colon arguments as a date/time. Invalid date returns [invalid date]; elapsed returns Event has passed!; timezone-less input follows host Date parsing.",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.random",
      "kind": "variable",
      "runtimeKey": "global.random",
      "label": "{random:1:100}",
      "category": "Utility",
      "summary": "Random whole number in an inclusive range",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.random"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{random:1:100}"
        }
      ],
      "details": {
        "key": "random",
        "syntax": "{random:1:100}",
        "category": "Utility",
        "description": "Random whole number in an inclusive range",
        "canonicalKey": "random",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Inclusive integer min/max, defaults 1/100. Reversed bounds swap; invalid or range over 1e9 falls back to Unavailable.",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.pick",
      "kind": "variable",
      "runtimeKey": "global.pick",
      "label": "{pick:red|green|blue}",
      "category": "Utility",
      "summary": "Randomly select one pipe-separated choice",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.pick"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{pick:red|green|blue}"
        }
      ],
      "details": {
        "key": "pick",
        "syntax": "{pick:red|green|blue}",
        "category": "Utility",
        "description": "Randomly select one pipe-separated choice",
        "canonicalKey": "pick",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Pipe-separated nonempty trimmed choices, first 50 only. Colon characters are rejoined; no choices falls back to Unavailable.",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.list",
      "kind": "variable",
      "runtimeKey": "global.list",
      "label": "{list:prizes}",
      "category": "Utility",
      "summary": "Randomly select an entry from a named Data Manager list",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "The named list must exist and contain at least one item",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.list"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{list:prizes}"
        }
      ],
      "details": {
        "key": "list",
        "syntax": "{list:prizes}",
        "category": "Utility",
        "description": "Randomly select an entry from a named Data Manager list",
        "availabilityNote": "The named list must exist and contain at least one item",
        "canonicalKey": "list",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Named Data Manager list must exist and contain items; selection is random.",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.viewer.random",
      "kind": "variable",
      "runtimeKey": "global.viewer.random",
      "label": "{viewer.random:current}",
      "category": "User",
      "summary": "Random eligible current-session viewer; use current, all, or a platform name",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Uses Twitch live chatters and viewers observed this session on YouTube, Kick, and TikTok. Excludes SheevChat, broadcasters, Bot-tagged accounts, and opted-out viewers.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.viewer.random"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{viewer.random:current}"
        }
      ],
      "details": {
        "key": "viewer.random",
        "syntax": "{viewer.random:current}",
        "category": "User",
        "description": "Random eligible current-session viewer; use current, all, or a platform name",
        "fallback": "",
        "availability": "runtime",
        "availabilityNote": "Uses Twitch live chatters and viewers observed this session on YouTube, Kick, and TikTok. Excludes SheevChat, broadcasters, Bot-tagged accounts, and opted-out viewers.",
        "canonicalKey": "viewer.random",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Argument current (default), all or platform. Excludes broadcasters, bots, SheevChat and opted-out viewers; absence returns empty.",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.repeat",
      "kind": "variable",
      "runtimeKey": "global.repeat",
      "label": "{repeat:3:Hello!}",
      "category": "Utility",
      "summary": "Repeat text up to ten times",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.repeat"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{repeat:3:Hello!}"
        }
      ],
      "details": {
        "key": "repeat",
        "syntax": "{repeat:3:Hello!}",
        "category": "Utility",
        "description": "Repeat text up to ten times",
        "canonicalKey": "repeat",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Count clamps 0–10; remaining colon arguments form repeated text separated by spaces.",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.math",
      "kind": "variable",
      "runtimeKey": "global.math",
      "label": "{math:(10 + 5) * 2}",
      "category": "Utility",
      "summary": "Safely evaluate basic arithmetic",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.math"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{math:(10 + 5) * 2}"
        }
      ],
      "details": {
        "key": "math",
        "syntax": "{math:(10 + 5) * 2}",
        "category": "Utility",
        "description": "Safely evaluate basic arithmetic",
        "canonicalKey": "math",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Basic + - * / % and parentheses, maximum 100 expression characters; division by zero/nonfinite/absolute result over 1e15 fails to Unavailable. No script execution.",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.sender.watchtime",
      "kind": "variable",
      "runtimeKey": "global.sender.watchtime",
      "label": "{sender.watchtime}",
      "category": "Loyalty",
      "summary": "Command sender's total watchtime",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.sender.watchtime"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{sender.watchtime}"
        }
      ],
      "details": {
        "key": "sender.watchtime",
        "aliases": [
          "watchtime",
          "user.watchtime"
        ],
        "category": "Loyalty",
        "description": "Command sender's total watchtime",
        "canonicalKey": "sender.watchtime",
        "syntax": "{sender.watchtime}",
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Command sender's total watchtime",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.target.watchtime",
      "kind": "variable",
      "runtimeKey": "global.target.watchtime",
      "label": "{target.watchtime}",
      "category": "Loyalty",
      "summary": "Target viewer's total watchtime",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.target.watchtime"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{target.watchtime}"
        }
      ],
      "details": {
        "key": "target.watchtime",
        "category": "Loyalty",
        "description": "Target viewer's total watchtime",
        "canonicalKey": "target.watchtime",
        "syntax": "{target.watchtime}",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Target viewer's total watchtime",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.song",
      "kind": "variable",
      "runtimeKey": "global.song",
      "label": "{song}",
      "category": "Music",
      "summary": "Currently playing song title",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Requires an active song or Spotify session",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.song"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{song}"
        }
      ],
      "details": {
        "key": "song",
        "aliases": [
          "song.title"
        ],
        "category": "Music",
        "description": "Currently playing song title",
        "availability": "runtime",
        "availabilityNote": "Requires an active song or Spotify session",
        "canonicalKey": "song",
        "syntax": "{song}",
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Currently playing song title",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.song.artist",
      "kind": "variable",
      "runtimeKey": "global.song.artist",
      "label": "{song.artist}",
      "category": "Music",
      "summary": "Currently playing song artist",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Requires an active song or Spotify session",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.song.artist"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{song.artist}"
        }
      ],
      "details": {
        "key": "song.artist",
        "aliases": [
          "artist"
        ],
        "category": "Music",
        "description": "Currently playing song artist",
        "availability": "runtime",
        "availabilityNote": "Requires an active song or Spotify session",
        "canonicalKey": "song.artist",
        "syntax": "{song.artist}",
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Currently playing song artist",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.song.requester",
      "kind": "variable",
      "runtimeKey": "global.song.requester",
      "label": "{song.requester}",
      "category": "Music",
      "summary": "Who requested the current song",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Only available for song requests (not Spotify direct)",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.song.requester"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{song.requester}"
        }
      ],
      "details": {
        "key": "song.requester",
        "aliases": [
          "requested_by"
        ],
        "category": "Music",
        "description": "Who requested the current song",
        "availability": "runtime",
        "availabilityNote": "Only available for song requests (not Spotify direct)",
        "canonicalKey": "song.requester",
        "syntax": "{song.requester}",
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "Who requested the current song",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.quote",
      "kind": "variable",
      "runtimeKey": "global.quote",
      "label": "{quote}",
      "category": "Utility",
      "summary": "A random saved quote from Data Manager",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Requires at least one saved quote",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.quote"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{quote}"
        }
      ],
      "details": {
        "key": "quote",
        "category": "Utility",
        "description": "A random saved quote from Data Manager",
        "availabilityNote": "Requires at least one saved quote",
        "canonicalKey": "quote",
        "syntax": "{quote}",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "A random saved quote from Data Manager",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "variable.global.quote.text",
      "kind": "variable",
      "runtimeKey": "global.quote.text",
      "label": "{quote.text}",
      "category": "Utility",
      "summary": "Random quote text only (no attribution)",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Values depend on the invocation context; timers and buttons do not have an incoming viewer.",
        "providers": [
          "twitch",
          "youtube",
          "kick",
          "tiktok"
        ]
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "COMMAND_VARIABLE_DEFINITIONS.quote.text"
        },
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.variables"
      ],
      "examples": [
        {
          "purpose": "A single variable expression; context and data prerequisites still apply.",
          "format": "template",
          "value": "{quote.text}"
        }
      ],
      "details": {
        "key": "quote.text",
        "category": "Utility",
        "description": "Random quote text only (no attribution)",
        "canonicalKey": "quote.text",
        "syntax": "{quote.text}",
        "aliases": [],
        "producer": "Global command variable engine, resolved on demand.",
        "fallback": "Unavailable",
        "fallbackNote": "This fallback applies on null/error/timeout; a resolver may return its own 0, empty string or descriptive value instead.",
        "behavior": "A fresh independent random quote is selected on each resolution; do not assume it matches a separate {quote} token.",
        "lifetime": "Resolved for this template; data may be live, cached or persisted according to its provider."
      }
    },
    {
      "id": "command.counter",
      "kind": "command",
      "runtimeKey": "counter",
      "label": "!counter",
      "category": "Default commands",
      "summary": "Read a named counter; automatic scope checks platform then global.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.counter"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!counter <name> [global|platform]"
        }
      ],
      "details": {
        "usage": "!counter <name> [global|platform]",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "requiredAuthority": "anyone",
          "cooldownSec": 5,
          "globalCooldownSec": 5,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          }
        },
        "behavior": "Read a named counter; automatic scope checks platform then global.",
        "aliases": [],
        "responseVariables": []
      }
    },
    {
      "id": "command.count",
      "kind": "command",
      "runtimeKey": "count",
      "label": "!count",
      "category": "Default commands",
      "summary": "Adjust/create a counter; moderator handling applies; missing scope is global.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.count"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!count <name> [amount] [global|platform]"
        }
      ],
      "details": {
        "usage": "!count <name> [amount] [global|platform]",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "requiredAuthority": "anyone",
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          }
        },
        "behavior": "Adjust/create a counter; moderator handling applies; missing scope is global.",
        "aliases": [],
        "responseVariables": []
      }
    },
    {
      "id": "command.setcounter",
      "kind": "command",
      "runtimeKey": "setcounter",
      "label": "!setcounter",
      "category": "Default commands",
      "summary": "Set an exact counter value; moderator handling applies.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.setcounter"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!setcounter <name> <value> [global|platform]"
        }
      ],
      "details": {
        "usage": "!setcounter <name> <value> [global|platform]",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "requiredAuthority": "anyone",
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          }
        },
        "behavior": "Set an exact counter value; moderator handling applies.",
        "aliases": [],
        "responseVariables": []
      }
    },
    {
      "id": "command.resetcounter",
      "kind": "command",
      "runtimeKey": "resetcounter",
      "label": "!resetcounter",
      "category": "Default commands",
      "summary": "Reset a counter; moderator handling applies.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.resetcounter"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!resetcounter <name> [global|platform]"
        }
      ],
      "details": {
        "usage": "!resetcounter <name> [global|platform]",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "requiredAuthority": "anyone",
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          }
        },
        "behavior": "Reset a counter; moderator handling applies.",
        "aliases": [],
        "responseVariables": []
      }
    },
    {
      "id": "command.points",
      "kind": "command",
      "runtimeKey": "points",
      "label": "!points",
      "category": "Default commands",
      "summary": "Read own or target balance.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.points"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!points [username]"
        }
      ],
      "details": {
        "usage": "!points [username]",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "requiredAuthority": "anyone",
          "cooldownSec": 5,
          "globalCooldownSec": 5,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          }
        },
        "behavior": "Read own or target balance.",
        "aliases": [],
        "responseVariables": []
      }
    },
    {
      "id": "command.rank",
      "kind": "command",
      "runtimeKey": "rank",
      "label": "!rank",
      "category": "Default commands",
      "summary": "Read own or target loyalty rank.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.rank"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!rank [username]"
        }
      ],
      "details": {
        "usage": "!rank [username]",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "requiredAuthority": "anyone",
          "cooldownSec": 5,
          "globalCooldownSec": 5,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          }
        },
        "behavior": "Read own or target loyalty rank.",
        "aliases": [],
        "responseVariables": []
      }
    },
    {
      "id": "command.top",
      "kind": "command",
      "runtimeKey": "top",
      "label": "!top",
      "category": "Default commands",
      "summary": "Show the loyalty leaderboard.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.top"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!top"
        }
      ],
      "details": {
        "usage": "!top",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "requiredAuthority": "anyone",
          "cooldownSec": 5,
          "globalCooldownSec": 5,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          }
        },
        "behavior": "Show the loyalty leaderboard.",
        "aliases": [],
        "responseVariables": []
      }
    },
    {
      "id": "command.give",
      "kind": "command",
      "runtimeKey": "give",
      "label": "!give",
      "category": "Default commands",
      "summary": "Transfer loyalty currency.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.give"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!give <username> <amount>"
        }
      ],
      "details": {
        "usage": "!give <username> <amount>",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "requiredAuthority": "anyone",
          "cooldownSec": 5,
          "globalCooldownSec": 5,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          }
        },
        "behavior": "Transfer loyalty currency.",
        "aliases": [],
        "responseVariables": []
      }
    },
    {
      "id": "command.bonus",
      "kind": "command",
      "runtimeKey": "bonus",
      "label": "!bonus",
      "category": "Default commands",
      "summary": "Award currency; broadcaster, or moderator when allowModerators is enabled.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.bonus"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!bonus <username> <amount>"
        }
      ],
      "details": {
        "usage": "!bonus <username> <amount>",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "allowModerators": false,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          }
        },
        "behavior": "Award currency; broadcaster, or moderator when allowModerators is enabled.",
        "aliases": [],
        "responseVariables": []
      }
    },
    {
      "id": "command.gamble",
      "kind": "command",
      "runtimeKey": "gamble",
      "label": "!gamble",
      "category": "Default commands",
      "summary": "Bet currency using configured win chance.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.gamble"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!gamble <amount>"
        }
      ],
      "details": {
        "usage": "!gamble <amount>",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "requiredAuthority": "anyone",
          "cooldownSec": 5,
          "globalCooldownSec": 5,
          "winChance": 50,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          }
        },
        "behavior": "Bet currency using configured win chance.",
        "aliases": [],
        "responseVariables": []
      }
    },
    {
      "id": "command.duel",
      "kind": "command",
      "runtimeKey": "duel",
      "label": "!duel",
      "category": "Default commands",
      "summary": "Challenge a viewer; acceptance expires after configured acceptSec.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.duel"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!duel <username> <amount>"
        }
      ],
      "details": {
        "usage": "!duel <username> <amount>",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "requiredAuthority": "anyone",
          "cooldownSec": 5,
          "globalCooldownSec": 5,
          "acceptSec": 30
        },
        "behavior": "Challenge a viewer; acceptance expires after configured acceptSec.",
        "aliases": [],
        "responseVariables": []
      }
    },
    {
      "id": "command.accept",
      "kind": "command",
      "runtimeKey": "accept",
      "label": "!accept",
      "category": "Default commands",
      "summary": "Accept a pending duel.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.accept"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!accept"
        }
      ],
      "details": {
        "usage": "!accept",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "requiredAuthority": "anyone"
        },
        "behavior": "Accept a pending duel.",
        "aliases": [],
        "responseVariables": []
      }
    },
    {
      "id": "command.deny",
      "kind": "command",
      "runtimeKey": "deny",
      "label": "!deny",
      "category": "Default commands",
      "summary": "Decline a pending duel.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.deny"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!deny"
        }
      ],
      "details": {
        "usage": "!deny",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "requiredAuthority": "anyone"
        },
        "behavior": "Decline a pending duel.",
        "aliases": [],
        "responseVariables": []
      }
    },
    {
      "id": "command.lurk",
      "kind": "command",
      "runtimeKey": "lurk",
      "label": "!lurk",
      "category": "Default commands",
      "summary": "Mark away and send the configured social reply.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.lurk"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [
        "variable.command.lurk.user",
        "variable.command.lurk.messageSuffix"
      ],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!lurk [message]"
        }
      ],
      "details": {
        "usage": "!lurk [message]",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "requiredAuthority": "anyone",
          "cooldownSec": 5,
          "globalCooldownSec": 5,
          "responseTemplate": "@{user} - thanks for the lurk! 🫡{messageSuffix}",
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true,
            "tiktok": true
          }
        },
        "behavior": "Mark away and send the configured social reply.",
        "aliases": [],
        "responseVariables": [
          "user",
          "messageSuffix"
        ]
      }
    },
    {
      "id": "variable.command.lurk.user",
      "kind": "variable",
      "runtimeKey": "command.lurk.user",
      "label": "{user} in !lurk",
      "category": "Command response variables",
      "summary": "Response value in the lurk command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.lurk"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.lurk"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{user}"
        }
      ],
      "details": {
        "syntax": "{user}",
        "canonicalKey": "user",
        "aliases": [],
        "producer": "command.lurk",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "variable.command.lurk.messageSuffix",
      "kind": "variable",
      "runtimeKey": "command.lurk.messageSuffix",
      "label": "{messageSuffix} in !lurk",
      "category": "Command response variables",
      "summary": "Response value in the lurk command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.lurk"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.lurk"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{messageSuffix}"
        }
      ],
      "details": {
        "syntax": "{messageSuffix}",
        "canonicalKey": "messageSuffix",
        "aliases": [],
        "producer": "command.lurk",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "command.unlurk",
      "kind": "command",
      "runtimeKey": "unlurk",
      "label": "!unlurk",
      "category": "Default commands",
      "summary": "Return from lurking.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.unlurk"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [
        "variable.command.unlurk.user"
      ],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!unlurk"
        }
      ],
      "details": {
        "usage": "!unlurk",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "requiredAuthority": "anyone",
          "cooldownSec": 5,
          "globalCooldownSec": 5,
          "responseTemplate": "@{user} - welcome back! 👋",
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true,
            "tiktok": true
          }
        },
        "behavior": "Return from lurking.",
        "aliases": [],
        "responseVariables": [
          "user"
        ]
      }
    },
    {
      "id": "variable.command.unlurk.user",
      "kind": "variable",
      "runtimeKey": "command.unlurk.user",
      "label": "{user} in !unlurk",
      "category": "Command response variables",
      "summary": "Response value in the unlurk command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.unlurk"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.unlurk"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{user}"
        }
      ],
      "details": {
        "syntax": "{user}",
        "canonicalKey": "user",
        "aliases": [],
        "producer": "command.unlurk",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "command.vieweroptout",
      "kind": "command",
      "runtimeKey": "vieweroptout",
      "label": "!vieweroptout",
      "category": "Default commands",
      "summary": "Exclude from random viewer selection; default scope is current platform; naming another viewer requires moderator authority.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.vieweroptout"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!vieweroptout [all] [username]"
        }
      ],
      "details": {
        "usage": "!vieweroptout [all] [username]",
        "defaults": {
          "enabled": true,
          "aliases": [
            "randomvieweroptout"
          ],
          "requiredAuthority": "anyone",
          "cooldownSec": 5,
          "globalCooldownSec": 2,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true,
            "tiktok": true
          }
        },
        "behavior": "Exclude from random viewer selection; default scope is current platform; naming another viewer requires moderator authority.",
        "aliases": [
          "randomvieweroptout"
        ],
        "responseVariables": []
      }
    },
    {
      "id": "command.vieweroptin",
      "kind": "command",
      "runtimeKey": "vieweroptin",
      "label": "!vieweroptin",
      "category": "Default commands",
      "summary": "Rejoin random viewer selection; default scope is current platform; naming another viewer requires moderator authority.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.vieweroptin"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!vieweroptin [all] [username]"
        }
      ],
      "details": {
        "usage": "!vieweroptin [all] [username]",
        "defaults": {
          "enabled": true,
          "aliases": [
            "randomvieweroptin"
          ],
          "requiredAuthority": "anyone",
          "cooldownSec": 5,
          "globalCooldownSec": 2,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true,
            "tiktok": true
          }
        },
        "behavior": "Rejoin random viewer selection; default scope is current platform; naming another viewer requires moderator authority.",
        "aliases": [
          "randomvieweroptin"
        ],
        "responseVariables": []
      }
    },
    {
      "id": "command.watchtime",
      "kind": "command",
      "runtimeKey": "watchtime",
      "label": "!watchtime",
      "category": "Default commands",
      "summary": "Show tracked total watchtime.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.watchtime"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!watchtime [username]"
        }
      ],
      "details": {
        "usage": "!watchtime [username]",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "requiredAuthority": "anyone",
          "cooldownSec": 5,
          "globalCooldownSec": 5,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true,
            "tiktok": true
          }
        },
        "behavior": "Show tracked total watchtime.",
        "aliases": [],
        "responseVariables": []
      }
    },
    {
      "id": "command.cmdsearch",
      "kind": "command",
      "runtimeKey": "cmdsearch",
      "label": "!cmdsearch",
      "category": "Default commands",
      "summary": "Search commands eligible for the current viewer/platform.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.cmdsearch"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!cmdsearch [search text]"
        }
      ],
      "details": {
        "usage": "!cmdsearch [search text]",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "requiredAuthority": "anyone",
          "cooldownSec": 10,
          "globalCooldownSec": 5,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          }
        },
        "behavior": "Search commands eligible for the current viewer/platform.",
        "aliases": [],
        "responseVariables": []
      }
    },
    {
      "id": "command.sheevchat",
      "kind": "command",
      "runtimeKey": "sheevchat",
      "label": "!sheevchat",
      "category": "Default commands",
      "summary": "Hidden built-in application information command.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.sheevchat"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!sheevchat"
        }
      ],
      "details": {
        "usage": "!sheevchat",
        "defaults": {
          "enabled": true,
          "hidden": true,
          "aliases": [
            "sheevbot",
            "sheeveschat",
            "sheevesbot"
          ],
          "requiredAuthority": "anyone",
          "cooldownSec": 300,
          "globalCooldownSec": 30,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          }
        },
        "behavior": "Hidden built-in application information command.",
        "aliases": [
          "sheevbot",
          "sheeveschat",
          "sheevesbot"
        ],
        "responseVariables": []
      }
    },
    {
      "id": "command.settitle",
      "kind": "command",
      "runtimeKey": "settitle",
      "label": "!settitle",
      "category": "Default commands",
      "summary": "Update the current platform stream title; no supported TikTok API.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.settitle"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [
        "variable.command.settitle.title"
      ],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!settitle <title>"
        }
      ],
      "details": {
        "usage": "!settitle <title>",
        "defaults": {
          "enabled": false,
          "aliases": [
            "st"
          ],
          "requiredAuthority": "moderator",
          "cooldownSec": 0,
          "globalCooldownSec": 0,
          "responseTemplate": "Title set to: {title}",
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          }
        },
        "behavior": "Update the current platform stream title; no supported TikTok API.",
        "aliases": [
          "st"
        ],
        "responseVariables": [
          "title"
        ]
      }
    },
    {
      "id": "variable.command.settitle.title",
      "kind": "variable",
      "runtimeKey": "command.settitle.title",
      "label": "{title} in !settitle",
      "category": "Command response variables",
      "summary": "Response value in the settitle command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.settitle"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.settitle"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{title}"
        }
      ],
      "details": {
        "syntax": "{title}",
        "canonicalKey": "title",
        "aliases": [],
        "producer": "command.settitle",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "command.setcategory",
      "kind": "command",
      "runtimeKey": "setcategory",
      "label": "!setcategory",
      "category": "Default commands",
      "summary": "Update current platform category/game; no supported TikTok API.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.setcategory"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [
        "variable.command.setcategory.game"
      ],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!setcategory <category>"
        }
      ],
      "details": {
        "usage": "!setcategory <category>",
        "defaults": {
          "enabled": false,
          "aliases": [
            "setgame",
            "sc",
            "sg"
          ],
          "requiredAuthority": "moderator",
          "cooldownSec": 0,
          "globalCooldownSec": 0,
          "responseTemplate": "Game set to: {game}",
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          }
        },
        "behavior": "Update current platform category/game; no supported TikTok API.",
        "aliases": [
          "setgame",
          "sc",
          "sg"
        ],
        "responseVariables": [
          "game"
        ]
      }
    },
    {
      "id": "variable.command.setcategory.game",
      "kind": "variable",
      "runtimeKey": "command.setcategory.game",
      "label": "{game} in !setcategory",
      "category": "Command response variables",
      "summary": "Response value in the setcategory command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.setcategory"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.setcategory"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{game}"
        }
      ],
      "details": {
        "syntax": "{game}",
        "canonicalKey": "game",
        "aliases": [],
        "producer": "command.setcategory",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "command.setcolor",
      "kind": "command",
      "runtimeKey": "setcolor",
      "label": "!setcolor",
      "category": "Default commands",
      "summary": "Set private SheevChat username display color.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.setcolor"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!setcolor <name|hex|reset>"
        }
      ],
      "details": {
        "usage": "!setcolor <name|hex|reset>",
        "defaults": {
          "enabled": true,
          "aliases": [
            "color",
            "namecolor"
          ],
          "requiredAuthority": "anyone",
          "cooldownSec": 10,
          "globalCooldownSec": 0,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true,
            "tiktok": true
          }
        },
        "behavior": "Set private SheevChat username display color.",
        "aliases": [
          "color",
          "namecolor"
        ],
        "responseVariables": []
      }
    },
    {
      "id": "command.followage",
      "kind": "command",
      "runtimeKey": "followage",
      "label": "!followage",
      "category": "Default commands",
      "summary": "Following duration; Twitch only.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.followage"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [
        "variable.command.followage.user",
        "variable.command.followage.followage"
      ],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!followage [username]"
        }
      ],
      "details": {
        "usage": "!followage [username]",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "requiredAuthority": "anyone",
          "cooldownSec": 5,
          "globalCooldownSec": 5,
          "responseTemplate": "@{user} has been following for {followage}.",
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          }
        },
        "behavior": "Following duration; Twitch only.",
        "aliases": [],
        "responseVariables": [
          "user",
          "followage"
        ]
      }
    },
    {
      "id": "variable.command.followage.user",
      "kind": "variable",
      "runtimeKey": "command.followage.user",
      "label": "{user} in !followage",
      "category": "Command response variables",
      "summary": "Response value in the followage command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.followage"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.followage"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{user}"
        }
      ],
      "details": {
        "syntax": "{user}",
        "canonicalKey": "user",
        "aliases": [],
        "producer": "command.followage",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "variable.command.followage.followage",
      "kind": "variable",
      "runtimeKey": "command.followage.followage",
      "label": "{followage} in !followage",
      "category": "Command response variables",
      "summary": "Response value in the followage command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.followage"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.followage"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{followage}"
        }
      ],
      "details": {
        "syntax": "{followage}",
        "canonicalKey": "followage",
        "aliases": [],
        "producer": "command.followage",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "command.accountage",
      "kind": "command",
      "runtimeKey": "accountage",
      "label": "!accountage",
      "category": "Default commands",
      "summary": "Account age; Twitch and Kick only.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.accountage"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [
        "variable.command.accountage.user",
        "variable.command.accountage.accountage"
      ],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!accountage [username]"
        }
      ],
      "details": {
        "usage": "!accountage [username]",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "requiredAuthority": "anyone",
          "cooldownSec": 5,
          "globalCooldownSec": 5,
          "responseTemplate": "@{user}'s account was created {accountage} ago.",
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          }
        },
        "behavior": "Account age; Twitch and Kick only.",
        "aliases": [],
        "responseVariables": [
          "user",
          "accountage"
        ]
      }
    },
    {
      "id": "variable.command.accountage.user",
      "kind": "variable",
      "runtimeKey": "command.accountage.user",
      "label": "{user} in !accountage",
      "category": "Command response variables",
      "summary": "Response value in the accountage command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.accountage"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.accountage"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{user}"
        }
      ],
      "details": {
        "syntax": "{user}",
        "canonicalKey": "user",
        "aliases": [],
        "producer": "command.accountage",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "variable.command.accountage.accountage",
      "kind": "variable",
      "runtimeKey": "command.accountage.accountage",
      "label": "{accountage} in !accountage",
      "category": "Command response variables",
      "summary": "Response value in the accountage command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.accountage"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.accountage"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{accountage}"
        }
      ],
      "details": {
        "syntax": "{accountage}",
        "canonicalKey": "accountage",
        "aliases": [],
        "producer": "command.accountage",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "command.birthday",
      "kind": "command",
      "runtimeKey": "birthday",
      "label": "!birthday",
      "category": "Default commands",
      "summary": "Look up saved birthday/countdown.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.birthday"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [
        "variable.command.birthday.user",
        "variable.command.birthday.birthday",
        "variable.command.birthday.birthdaycountdown"
      ],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!birthday [username]"
        }
      ],
      "details": {
        "usage": "!birthday [username]",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "requiredAuthority": "anyone",
          "cooldownSec": 5,
          "globalCooldownSec": 5,
          "responseTemplate": "@{user}'s birthday is {birthday} - {birthdaycountdown}!",
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          }
        },
        "behavior": "Look up saved birthday/countdown.",
        "aliases": [],
        "responseVariables": [
          "user",
          "birthday",
          "birthdaycountdown"
        ]
      }
    },
    {
      "id": "variable.command.birthday.user",
      "kind": "variable",
      "runtimeKey": "command.birthday.user",
      "label": "{user} in !birthday",
      "category": "Command response variables",
      "summary": "Response value in the birthday command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.birthday"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.birthday"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{user}"
        }
      ],
      "details": {
        "syntax": "{user}",
        "canonicalKey": "user",
        "aliases": [],
        "producer": "command.birthday",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "variable.command.birthday.birthday",
      "kind": "variable",
      "runtimeKey": "command.birthday.birthday",
      "label": "{birthday} in !birthday",
      "category": "Command response variables",
      "summary": "Response value in the birthday command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.birthday"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.birthday"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{birthday}"
        }
      ],
      "details": {
        "syntax": "{birthday}",
        "canonicalKey": "birthday",
        "aliases": [],
        "producer": "command.birthday",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "variable.command.birthday.birthdaycountdown",
      "kind": "variable",
      "runtimeKey": "command.birthday.birthdaycountdown",
      "label": "{birthdaycountdown} in !birthday",
      "category": "Command response variables",
      "summary": "Response value in the birthday command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.birthday"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.birthday"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{birthdaycountdown}"
        }
      ],
      "details": {
        "syntax": "{birthdaycountdown}",
        "canonicalKey": "birthdaycountdown",
        "aliases": [],
        "producer": "command.birthday",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "command.setbirthday",
      "kind": "command",
      "runtimeKey": "setbirthday",
      "label": "!setbirthday",
      "category": "Default commands",
      "summary": "Save birthday using configured MM-DD or DD-MM format, with optional year.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.setbirthday"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [
        "variable.command.setbirthday.user",
        "variable.command.setbirthday.birthday"
      ],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!setbirthday <date>"
        }
      ],
      "details": {
        "usage": "!setbirthday <date>",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "requiredAuthority": "anyone",
          "cooldownSec": 30,
          "globalCooldownSec": 5,
          "responseTemplate": "@{user} - birthday set to {birthday}!",
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          }
        },
        "behavior": "Save birthday using configured MM-DD or DD-MM format, with optional year.",
        "aliases": [],
        "responseVariables": [
          "user",
          "birthday"
        ]
      }
    },
    {
      "id": "variable.command.setbirthday.user",
      "kind": "variable",
      "runtimeKey": "command.setbirthday.user",
      "label": "{user} in !setbirthday",
      "category": "Command response variables",
      "summary": "Response value in the setbirthday command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.setbirthday"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.setbirthday"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{user}"
        }
      ],
      "details": {
        "syntax": "{user}",
        "canonicalKey": "user",
        "aliases": [],
        "producer": "command.setbirthday",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "variable.command.setbirthday.birthday",
      "kind": "variable",
      "runtimeKey": "command.setbirthday.birthday",
      "label": "{birthday} in !setbirthday",
      "category": "Command response variables",
      "summary": "Response value in the setbirthday command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.setbirthday"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.setbirthday"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{birthday}"
        }
      ],
      "details": {
        "syntax": "{birthday}",
        "canonicalKey": "birthday",
        "aliases": [],
        "producer": "command.setbirthday",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "command.deletebirthday",
      "kind": "command",
      "runtimeKey": "deletebirthday",
      "label": "!deletebirthday",
      "category": "Default commands",
      "summary": "Delete own birthday; another viewer requires moderator handling.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.deletebirthday"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [
        "variable.command.deletebirthday.user"
      ],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!deletebirthday [username]"
        }
      ],
      "details": {
        "usage": "!deletebirthday [username]",
        "defaults": {
          "enabled": true,
          "aliases": [
            "bddelete",
            "removebirthday"
          ],
          "requiredAuthority": "anyone",
          "cooldownSec": 10,
          "globalCooldownSec": 5,
          "responseTemplate": "@{user} - birthday removed.",
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          }
        },
        "behavior": "Delete own birthday; another viewer requires moderator handling.",
        "aliases": [
          "bddelete",
          "removebirthday"
        ],
        "responseVariables": [
          "user"
        ]
      }
    },
    {
      "id": "variable.command.deletebirthday.user",
      "kind": "variable",
      "runtimeKey": "command.deletebirthday.user",
      "label": "{user} in !deletebirthday",
      "category": "Command response variables",
      "summary": "Response value in the deletebirthday command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.deletebirthday"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.deletebirthday"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{user}"
        }
      ],
      "details": {
        "syntax": "{user}",
        "canonicalKey": "user",
        "aliases": [],
        "producer": "command.deletebirthday",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "command.tarotcards",
      "kind": "command",
      "runtimeKey": "tarotcards",
      "label": "!tarotcards",
      "category": "Default commands",
      "summary": "Draw Past / Present / Future tarot cards.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.tarotcards"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!tarotcards"
        }
      ],
      "details": {
        "usage": "!tarotcards",
        "defaults": {
          "enabled": true,
          "aliases": [
            "tarot",
            "cards"
          ],
          "requiredAuthority": "anyone",
          "cooldownSec": 30,
          "globalCooldownSec": 10,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          }
        },
        "behavior": "Draw Past / Present / Future tarot cards.",
        "aliases": [
          "tarot",
          "cards"
        ],
        "responseVariables": []
      }
    },
    {
      "id": "command.playclip",
      "kind": "command",
      "runtimeKey": "playclip",
      "label": "!playclip",
      "category": "Default commands",
      "summary": "Queue supported short-form video; disabled by default, with configured limits and eligible sources.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.playclip"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!playclip <URL>"
        }
      ],
      "details": {
        "usage": "!playclip <URL>",
        "defaults": {
          "enabled": false,
          "aliases": [
            "tt",
            "tw",
            "yt",
            "ki",
            "tiktok"
          ],
          "requiredAuthority": "vip",
          "cooldownSec": 30,
          "globalCooldownSec": 10,
          "maxClipSec": 30,
          "clipFormat": "obs",
          "clipSources": {
            "tiktok": true,
            "youtubeShorts": true,
            "instagramReels": true,
            "twitchClips": true,
            "kickClips": true
          },
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true,
            "tiktok": true
          }
        },
        "behavior": "Queue supported short-form video; disabled by default, with configured limits and eligible sources.",
        "aliases": [
          "tt",
          "tw",
          "yt",
          "ki",
          "tiktok"
        ],
        "responseVariables": []
      }
    },
    {
      "id": "command.clip",
      "kind": "command",
      "runtimeKey": "clip",
      "label": "!clip",
      "category": "Default commands",
      "summary": "Create a Twitch clip of previous 5–60 seconds; missing length requests 60.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.clip"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!clip [seconds]"
        }
      ],
      "details": {
        "usage": "!clip [seconds]",
        "defaults": {
          "enabled": false,
          "aliases": [],
          "requiredAuthority": "anyone",
          "cooldownSec": 30,
          "globalCooldownSec": 15,
          "autoPostClip": true,
          "platforms": {
            "twitch": true,
            "youtube": false,
            "kick": false,
            "tiktok": false
          }
        },
        "behavior": "Create a Twitch clip of previous 5–60 seconds; missing length requests 60.",
        "aliases": [],
        "responseVariables": []
      }
    },
    {
      "id": "command.weather",
      "kind": "command",
      "runtimeKey": "weather",
      "label": "!weather",
      "category": "Default commands",
      "summary": "Current weather for a place or coordinates.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.weather"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!weather <place|latitude,longitude>"
        }
      ],
      "details": {
        "usage": "!weather <place|latitude,longitude>",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "requiredAuthority": "anyone",
          "cooldownSec": 15,
          "globalCooldownSec": 5,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          }
        },
        "behavior": "Current weather for a place or coordinates.",
        "aliases": [],
        "responseVariables": []
      }
    },
    {
      "id": "command.trivia",
      "kind": "command",
      "runtimeKey": "trivia",
      "label": "!trivia",
      "category": "Default commands",
      "summary": "Start shared trivia; disabled by default.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.trivia"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!trivia"
        }
      ],
      "details": {
        "usage": "!trivia",
        "defaults": {
          "enabled": false,
          "aliases": [
            "quiz"
          ],
          "requiredAuthority": "moderator",
          "cooldownSec": 0,
          "globalCooldownSec": 0,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true,
            "tiktok": true
          }
        },
        "behavior": "Start shared trivia; disabled by default.",
        "aliases": [
          "quiz"
        ],
        "responseVariables": []
      }
    },
    {
      "id": "command.triviastop",
      "kind": "command",
      "runtimeKey": "triviastop",
      "label": "!triviastop",
      "category": "Default commands",
      "summary": "Stop shared trivia.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.triviastop"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!triviastop"
        }
      ],
      "details": {
        "usage": "!triviastop",
        "defaults": {
          "enabled": false,
          "aliases": [],
          "requiredAuthority": "moderator",
          "cooldownSec": 0,
          "globalCooldownSec": 0,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true,
            "tiktok": true
          }
        },
        "behavior": "Stop shared trivia.",
        "aliases": [],
        "responseVariables": []
      }
    },
    {
      "id": "command.quote",
      "kind": "command",
      "runtimeKey": "quote",
      "label": "!quote",
      "category": "Default commands",
      "summary": "Random quote or lookup.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.quote"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!quote [id|search text]"
        }
      ],
      "details": {
        "usage": "!quote [id|search text]",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "requiredAuthority": "anyone",
          "cooldownSec": 5,
          "globalCooldownSec": 5,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          }
        },
        "behavior": "Random quote or lookup.",
        "aliases": [],
        "responseVariables": []
      }
    },
    {
      "id": "command.quoteadd",
      "kind": "command",
      "runtimeKey": "quoteadd",
      "label": "!quoteadd",
      "category": "Default commands",
      "summary": "Save a quote.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.quoteadd"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!quoteadd <quote text>"
        }
      ],
      "details": {
        "usage": "!quoteadd <quote text>",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "requiredAuthority": "moderator",
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          }
        },
        "behavior": "Save a quote.",
        "aliases": [],
        "responseVariables": []
      }
    },
    {
      "id": "command.quoteremove",
      "kind": "command",
      "runtimeKey": "quoteremove",
      "label": "!quoteremove",
      "category": "Default commands",
      "summary": "Remove a saved quote.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.quoteremove"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!quoteremove <id>"
        }
      ],
      "details": {
        "usage": "!quoteremove <id>",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "requiredAuthority": "moderator",
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          }
        },
        "behavior": "Remove a saved quote.",
        "aliases": [],
        "responseVariables": []
      }
    },
    {
      "id": "command.sr",
      "kind": "command",
      "runtimeKey": "sr",
      "label": "!sr",
      "category": "Default commands",
      "summary": "Request a song.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.sr"
        },
        {
          "path": "src/features/media/mediaCommands.js",
          "symbol": "handleSongRequestCommand"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [
        "variable.command.sr.user",
        "variable.command.sr.title",
        "variable.command.sr.artist"
      ],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!sr <URL|search text>"
        }
      ],
      "details": {
        "usage": "!sr <URL|search text>",
        "defaults": {
          "enabled": true,
          "aliases": [
            "songrequest"
          ],
          "requiredAuthority": "anyone",
          "cooldownSec": 30,
          "globalCooldownSec": 0,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          },
          "responseTemplate": "@{user} â€” \"{title}\" by {artist} added to the queue!"
        },
        "behavior": "Request a song.",
        "aliases": [
          "songrequest"
        ],
        "responseVariables": [
          "user",
          "title",
          "artist"
        ]
      }
    },
    {
      "id": "variable.command.sr.user",
      "kind": "variable",
      "runtimeKey": "command.sr.user",
      "label": "{user} in !sr",
      "category": "Command response variables",
      "summary": "Response value in the sr command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.sr"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.sr"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{user}"
        }
      ],
      "details": {
        "syntax": "{user}",
        "canonicalKey": "user",
        "aliases": [],
        "producer": "command.sr",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "variable.command.sr.title",
      "kind": "variable",
      "runtimeKey": "command.sr.title",
      "label": "{title} in !sr",
      "category": "Command response variables",
      "summary": "Response value in the sr command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.sr"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.sr"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{title}"
        }
      ],
      "details": {
        "syntax": "{title}",
        "canonicalKey": "title",
        "aliases": [],
        "producer": "command.sr",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "variable.command.sr.artist",
      "kind": "variable",
      "runtimeKey": "command.sr.artist",
      "label": "{artist} in !sr",
      "category": "Command response variables",
      "summary": "Response value in the sr command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.sr"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.sr"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{artist}"
        }
      ],
      "details": {
        "syntax": "{artist}",
        "canonicalKey": "artist",
        "aliases": [],
        "producer": "command.sr",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "command.song",
      "kind": "command",
      "runtimeKey": "song",
      "label": "!song",
      "category": "Default commands",
      "summary": "Current song.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.song"
        },
        {
          "path": "src/features/media/mediaCommands.js",
          "symbol": "handleSongRequestCommand"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [
        "variable.command.song.title",
        "variable.command.song.artist",
        "variable.command.song.requested_by"
      ],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!song"
        }
      ],
      "details": {
        "usage": "!song",
        "defaults": {
          "enabled": true,
          "aliases": [
            "currentsong"
          ],
          "requiredAuthority": "anyone",
          "cooldownSec": 5,
          "globalCooldownSec": 5,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          },
          "responseTemplate": "Now playing: {title} by {artist}{requested_by}"
        },
        "behavior": "Current song.",
        "aliases": [
          "currentsong"
        ],
        "responseVariables": [
          "title",
          "artist",
          "requested_by"
        ]
      }
    },
    {
      "id": "variable.command.song.title",
      "kind": "variable",
      "runtimeKey": "command.song.title",
      "label": "{title} in !song",
      "category": "Command response variables",
      "summary": "Response value in the song command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.song"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.song"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{title}"
        }
      ],
      "details": {
        "syntax": "{title}",
        "canonicalKey": "title",
        "aliases": [],
        "producer": "command.song",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "variable.command.song.artist",
      "kind": "variable",
      "runtimeKey": "command.song.artist",
      "label": "{artist} in !song",
      "category": "Command response variables",
      "summary": "Response value in the song command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.song"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.song"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{artist}"
        }
      ],
      "details": {
        "syntax": "{artist}",
        "canonicalKey": "artist",
        "aliases": [],
        "producer": "command.song",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "variable.command.song.requested_by",
      "kind": "variable",
      "runtimeKey": "command.song.requested_by",
      "label": "{requested_by} in !song",
      "category": "Command response variables",
      "summary": "Response value in the song command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.song"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.song"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{requested_by}"
        }
      ],
      "details": {
        "syntax": "{requested_by}",
        "canonicalKey": "requested_by",
        "aliases": [],
        "producer": "command.song",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "command.next",
      "kind": "command",
      "runtimeKey": "next",
      "label": "!next",
      "category": "Default commands",
      "summary": "Next queued song.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.next"
        },
        {
          "path": "src/features/media/mediaCommands.js",
          "symbol": "handleSongRequestCommand"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [
        "variable.command.next.title",
        "variable.command.next.artist"
      ],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!next"
        }
      ],
      "details": {
        "usage": "!next",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "requiredAuthority": "anyone",
          "cooldownSec": 5,
          "globalCooldownSec": 5,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          },
          "responseTemplate": "Next up: {title} by {artist}"
        },
        "behavior": "Next queued song.",
        "aliases": [],
        "responseVariables": [
          "title",
          "artist"
        ]
      }
    },
    {
      "id": "variable.command.next.title",
      "kind": "variable",
      "runtimeKey": "command.next.title",
      "label": "{title} in !next",
      "category": "Command response variables",
      "summary": "Response value in the next command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.next"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.next"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{title}"
        }
      ],
      "details": {
        "syntax": "{title}",
        "canonicalKey": "title",
        "aliases": [],
        "producer": "command.next",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "variable.command.next.artist",
      "kind": "variable",
      "runtimeKey": "command.next.artist",
      "label": "{artist} in !next",
      "category": "Command response variables",
      "summary": "Response value in the next command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.next"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.next"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{artist}"
        }
      ],
      "details": {
        "syntax": "{artist}",
        "canonicalKey": "artist",
        "aliases": [],
        "producer": "command.next",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "command.queue",
      "kind": "command",
      "runtimeKey": "queue",
      "label": "!queue",
      "category": "Default commands",
      "summary": "Show queued songs.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.queue"
        },
        {
          "path": "src/features/media/mediaCommands.js",
          "symbol": "handleSongRequestCommand"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [
        "variable.command.queue.queue"
      ],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!queue"
        }
      ],
      "details": {
        "usage": "!queue",
        "defaults": {
          "enabled": true,
          "aliases": [
            "songqueue"
          ],
          "requiredAuthority": "anyone",
          "cooldownSec": 5,
          "globalCooldownSec": 5,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          },
          "responseTemplate": "Queue: {queue}"
        },
        "behavior": "Show queued songs.",
        "aliases": [
          "songqueue"
        ],
        "responseVariables": [
          "queue"
        ]
      }
    },
    {
      "id": "variable.command.queue.queue",
      "kind": "variable",
      "runtimeKey": "command.queue.queue",
      "label": "{queue} in !queue",
      "category": "Command response variables",
      "summary": "Response value in the queue command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.queue"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.queue"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{queue}"
        }
      ],
      "details": {
        "syntax": "{queue}",
        "canonicalKey": "queue",
        "aliases": [],
        "producer": "command.queue",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "command.wrongsong",
      "kind": "command",
      "runtimeKey": "wrongsong",
      "label": "!wrongsong",
      "category": "Default commands",
      "summary": "Remove your latest request.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.wrongsong"
        },
        {
          "path": "src/features/media/mediaCommands.js",
          "symbol": "handleSongRequestCommand"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [
        "variable.command.wrongsong.user",
        "variable.command.wrongsong.title"
      ],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!wrongsong"
        }
      ],
      "details": {
        "usage": "!wrongsong",
        "defaults": {
          "enabled": true,
          "aliases": [
            "remove"
          ],
          "requiredAuthority": "anyone",
          "cooldownSec": 5,
          "globalCooldownSec": 0,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          },
          "responseTemplate": "@{user} â€” \"{title}\" has been removed from the queue."
        },
        "behavior": "Remove your latest request.",
        "aliases": [
          "remove"
        ],
        "responseVariables": [
          "user",
          "title"
        ]
      }
    },
    {
      "id": "variable.command.wrongsong.user",
      "kind": "variable",
      "runtimeKey": "command.wrongsong.user",
      "label": "{user} in !wrongsong",
      "category": "Command response variables",
      "summary": "Response value in the wrongsong command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.wrongsong"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.wrongsong"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{user}"
        }
      ],
      "details": {
        "syntax": "{user}",
        "canonicalKey": "user",
        "aliases": [],
        "producer": "command.wrongsong",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "variable.command.wrongsong.title",
      "kind": "variable",
      "runtimeKey": "command.wrongsong.title",
      "label": "{title} in !wrongsong",
      "category": "Command response variables",
      "summary": "Response value in the wrongsong command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.wrongsong"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.wrongsong"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{title}"
        }
      ],
      "details": {
        "syntax": "{title}",
        "canonicalKey": "title",
        "aliases": [],
        "producer": "command.wrongsong",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "command.voteskip",
      "kind": "command",
      "runtimeKey": "voteskip",
      "label": "!voteskip",
      "category": "Default commands",
      "summary": "Vote to skip current song.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.voteskip"
        },
        {
          "path": "src/features/media/mediaCommands.js",
          "symbol": "handleSongRequestCommand"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [
        "variable.command.voteskip.user",
        "variable.command.voteskip.votes",
        "variable.command.voteskip.threshold"
      ],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!voteskip"
        }
      ],
      "details": {
        "usage": "!voteskip",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "requiredAuthority": "anyone",
          "cooldownSec": 5,
          "globalCooldownSec": 0,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          },
          "responseTemplate": "@{user} voted to skip! ({votes}/{threshold} votes)",
          "voteskipThreshold": 3
        },
        "behavior": "Vote to skip current song.",
        "aliases": [],
        "responseVariables": [
          "user",
          "votes",
          "threshold"
        ]
      }
    },
    {
      "id": "variable.command.voteskip.user",
      "kind": "variable",
      "runtimeKey": "command.voteskip.user",
      "label": "{user} in !voteskip",
      "category": "Command response variables",
      "summary": "Response value in the voteskip command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.voteskip"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.voteskip"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{user}"
        }
      ],
      "details": {
        "syntax": "{user}",
        "canonicalKey": "user",
        "aliases": [],
        "producer": "command.voteskip",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "variable.command.voteskip.votes",
      "kind": "variable",
      "runtimeKey": "command.voteskip.votes",
      "label": "{votes} in !voteskip",
      "category": "Command response variables",
      "summary": "Response value in the voteskip command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.voteskip"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.voteskip"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{votes}"
        }
      ],
      "details": {
        "syntax": "{votes}",
        "canonicalKey": "votes",
        "aliases": [],
        "producer": "command.voteskip",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "variable.command.voteskip.threshold",
      "kind": "variable",
      "runtimeKey": "command.voteskip.threshold",
      "label": "{threshold} in !voteskip",
      "category": "Command response variables",
      "summary": "Response value in the voteskip command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.voteskip"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.voteskip"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{threshold}"
        }
      ],
      "details": {
        "syntax": "{threshold}",
        "canonicalKey": "threshold",
        "aliases": [],
        "producer": "command.voteskip",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "command.songskip",
      "kind": "command",
      "runtimeKey": "songskip",
      "label": "!songskip",
      "category": "Default commands",
      "summary": "Skip current song.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.songskip"
        },
        {
          "path": "src/features/media/mediaCommands.js",
          "symbol": "handleSongRequestCommand"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [
        "variable.command.songskip.user"
      ],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!songskip"
        }
      ],
      "details": {
        "usage": "!songskip",
        "defaults": {
          "enabled": true,
          "aliases": [
            "skip",
            "sskip"
          ],
          "requiredAuthority": "moderator",
          "cooldownSec": 0,
          "globalCooldownSec": 0,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          },
          "responseTemplate": "@{user} skipped the current song."
        },
        "behavior": "Skip current song.",
        "aliases": [
          "skip",
          "sskip"
        ],
        "responseVariables": [
          "user"
        ]
      }
    },
    {
      "id": "variable.command.songskip.user",
      "kind": "variable",
      "runtimeKey": "command.songskip.user",
      "label": "{user} in !songskip",
      "category": "Command response variables",
      "summary": "Response value in the songskip command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.songskip"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.songskip"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{user}"
        }
      ],
      "details": {
        "syntax": "{user}",
        "canonicalKey": "user",
        "aliases": [],
        "producer": "command.songskip",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "command.songpause",
      "kind": "command",
      "runtimeKey": "songpause",
      "label": "!songpause",
      "category": "Default commands",
      "summary": "Pause playback.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.songpause"
        },
        {
          "path": "src/features/media/mediaCommands.js",
          "symbol": "handleSongRequestCommand"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!songpause"
        }
      ],
      "details": {
        "usage": "!songpause",
        "defaults": {
          "enabled": true,
          "aliases": [
            "pause"
          ],
          "requiredAuthority": "moderator",
          "cooldownSec": 0,
          "globalCooldownSec": 0,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          },
          "responseTemplate": "Playback paused."
        },
        "behavior": "Pause playback.",
        "aliases": [
          "pause"
        ],
        "responseVariables": []
      }
    },
    {
      "id": "command.songresume",
      "kind": "command",
      "runtimeKey": "songresume",
      "label": "!songresume",
      "category": "Default commands",
      "summary": "Resume playback.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.songresume"
        },
        {
          "path": "src/features/media/mediaCommands.js",
          "symbol": "handleSongRequestCommand"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!songresume"
        }
      ],
      "details": {
        "usage": "!songresume",
        "defaults": {
          "enabled": true,
          "aliases": [
            "play"
          ],
          "requiredAuthority": "moderator",
          "cooldownSec": 0,
          "globalCooldownSec": 0,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          },
          "responseTemplate": "Playback resumed."
        },
        "behavior": "Resume playback.",
        "aliases": [
          "play"
        ],
        "responseVariables": []
      }
    },
    {
      "id": "command.songclear",
      "kind": "command",
      "runtimeKey": "songclear",
      "label": "!songclear",
      "category": "Default commands",
      "summary": "Clear queued songs.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.songclear"
        },
        {
          "path": "src/features/media/mediaCommands.js",
          "symbol": "handleSongRequestCommand"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!songclear"
        }
      ],
      "details": {
        "usage": "!songclear",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "requiredAuthority": "moderator",
          "cooldownSec": 0,
          "globalCooldownSec": 0,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          },
          "responseTemplate": "Queue cleared."
        },
        "behavior": "Clear queued songs.",
        "aliases": [],
        "responseVariables": []
      }
    },
    {
      "id": "command.volume",
      "kind": "command",
      "runtimeKey": "volume",
      "label": "!volume",
      "category": "Default commands",
      "summary": "Read or set playback volume.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.volume"
        },
        {
          "path": "src/features/media/mediaCommands.js",
          "symbol": "handleSongRequestCommand"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [
        "variable.command.volume.vol"
      ],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!volume [0–100]"
        }
      ],
      "details": {
        "usage": "!volume [0–100]",
        "defaults": {
          "enabled": true,
          "aliases": [
            "vol"
          ],
          "requiredAuthority": "moderator",
          "cooldownSec": 0,
          "globalCooldownSec": 0,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          },
          "responseTemplate": "Volume: {vol}%",
          "responseSetTemplate": "Volume set to {vol}%."
        },
        "behavior": "Read or set playback volume.",
        "aliases": [
          "vol"
        ],
        "responseVariables": [
          "vol"
        ]
      }
    },
    {
      "id": "variable.command.volume.vol",
      "kind": "variable",
      "runtimeKey": "command.volume.vol",
      "label": "{vol} in !volume",
      "category": "Command response variables",
      "summary": "Response value in the volume command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.volume"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.volume"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{vol}"
        }
      ],
      "details": {
        "syntax": "{vol}",
        "canonicalKey": "vol",
        "aliases": [],
        "producer": "command.volume",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "command.songapprove",
      "kind": "command",
      "runtimeKey": "songapprove",
      "label": "!songapprove",
      "category": "Default commands",
      "summary": "Approve a pending request; missing ID selects the latest pending request.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.songapprove"
        },
        {
          "path": "src/features/media/mediaCommands.js",
          "symbol": "handleSongRequestCommand"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!songapprove [request ID|last]"
        }
      ],
      "details": {
        "usage": "!songapprove [request ID|last]",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "requiredAuthority": "moderator",
          "cooldownSec": 0,
          "globalCooldownSec": 0,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          }
        },
        "behavior": "Approve a pending request; missing ID selects the latest pending request.",
        "aliases": [],
        "responseVariables": []
      }
    },
    {
      "id": "command.songreject",
      "kind": "command",
      "runtimeKey": "songreject",
      "label": "!songreject",
      "category": "Default commands",
      "summary": "Reject a pending request; missing ID selects the latest pending request.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.songreject"
        },
        {
          "path": "src/features/media/mediaCommands.js",
          "symbol": "handleSongRequestCommand"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!songreject [request ID|last]"
        }
      ],
      "details": {
        "usage": "!songreject [request ID|last]",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "requiredAuthority": "moderator",
          "cooldownSec": 0,
          "globalCooldownSec": 0,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          }
        },
        "behavior": "Reject a pending request; missing ID selects the latest pending request.",
        "aliases": [],
        "responseVariables": []
      }
    },
    {
      "id": "command.loadplaylist",
      "kind": "command",
      "runtimeKey": "loadplaylist",
      "label": "!loadplaylist",
      "category": "Default commands",
      "summary": "Load a YouTube or Spotify playlist into song requests.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.loadplaylist"
        },
        {
          "path": "src/features/media/mediaCommands.js",
          "symbol": "handleSongRequestCommand"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!loadplaylist <URL>"
        }
      ],
      "details": {
        "usage": "!loadplaylist <URL>",
        "defaults": {
          "enabled": true,
          "aliases": [
            "srplaylist"
          ],
          "requiredAuthority": "moderator",
          "cooldownSec": 0,
          "globalCooldownSec": 0,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          }
        },
        "behavior": "Load a YouTube or Spotify playlist into song requests.",
        "aliases": [
          "srplaylist"
        ],
        "responseVariables": []
      }
    },
    {
      "id": "command.bansong",
      "kind": "command",
      "runtimeKey": "bansong",
      "label": "!bansong",
      "category": "Default commands",
      "summary": "Block the currently playing song.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.bansong"
        },
        {
          "path": "src/features/media/mediaCommands.js",
          "symbol": "handleSongRequestCommand"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [
        "variable.command.bansong.title"
      ],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!bansong"
        }
      ],
      "details": {
        "usage": "!bansong",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "requiredAuthority": "moderator",
          "cooldownSec": 0,
          "globalCooldownSec": 0,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          },
          "responseTemplate": "\"{title}\" has been added to the blocklist."
        },
        "behavior": "Block the currently playing song.",
        "aliases": [],
        "responseVariables": [
          "title"
        ]
      }
    },
    {
      "id": "variable.command.bansong.title",
      "kind": "variable",
      "runtimeKey": "command.bansong.title",
      "label": "{title} in !bansong",
      "category": "Command response variables",
      "summary": "Response value in the bansong command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.bansong"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.bansong"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{title}"
        }
      ],
      "details": {
        "syntax": "{title}",
        "canonicalKey": "title",
        "aliases": [],
        "producer": "command.bansong",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "command.cmds",
      "kind": "command",
      "runtimeKey": "cmds",
      "label": "!cmds",
      "category": "Default commands",
      "summary": "List music commands.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.cmds"
        },
        {
          "path": "src/features/media/mediaCommands.js",
          "symbol": "handleSongRequestCommand"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [
        "variable.command.cmds.commands"
      ],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!cmds"
        }
      ],
      "details": {
        "usage": "!cmds",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "requiredAuthority": "anyone",
          "cooldownSec": 30,
          "globalCooldownSec": 30,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          },
          "responseTemplate": "Music commands: {commands}"
        },
        "behavior": "List music commands.",
        "aliases": [],
        "responseVariables": [
          "commands"
        ]
      }
    },
    {
      "id": "variable.command.cmds.commands",
      "kind": "variable",
      "runtimeKey": "command.cmds.commands",
      "label": "{commands} in !cmds",
      "category": "Command response variables",
      "summary": "Response value in the cmds command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.cmds"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.cmds"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{commands}"
        }
      ],
      "details": {
        "syntax": "{commands}",
        "canonicalKey": "commands",
        "aliases": [],
        "producer": "command.cmds",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "command.togglesr",
      "kind": "command",
      "runtimeKey": "togglesr",
      "label": "!togglesr",
      "category": "Default commands",
      "summary": "Toggle song requests enabled state.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Enabled command, connected eligible platform, configured authority and cooldown; individual handler requirements also apply."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.togglesr"
        },
        {
          "path": "src/features/media/mediaCommands.js",
          "symbol": "handleSongRequestCommand"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Defaults describe a fresh configuration; existing settings and migration normalization may differ. Platform toggles do not guarantee that a provider API supports the command.",
        "Command triggers/aliases may be customized; use the effective configured trigger."
      ],
      "relatedIds": [
        "variable.command.togglesr.state"
      ],
      "examples": [
        {
          "purpose": "Usage notation: <required>, [optional]; replace placeholders before sending.",
          "format": "command-text",
          "value": "!togglesr"
        }
      ],
      "details": {
        "usage": "!togglesr",
        "defaults": {
          "enabled": true,
          "aliases": [],
          "requiredAuthority": "moderator",
          "cooldownSec": 0,
          "globalCooldownSec": 0,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true
          },
          "responseTemplate": "Song requests are now {state}."
        },
        "behavior": "Toggle song requests enabled state.",
        "aliases": [],
        "responseVariables": [
          "state"
        ]
      }
    },
    {
      "id": "variable.command.togglesr.state",
      "kind": "variable",
      "runtimeKey": "command.togglesr.state",
      "label": "{state} in !togglesr",
      "category": "Command response variables",
      "summary": "Response value in the togglesr command handler's own template.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "DEFAULT_COMMANDS.togglesr"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "command.togglesr"
      ],
      "examples": [
        {
          "purpose": "Use in this command response template, not as a general action output.",
          "format": "template",
          "value": "{state}"
        }
      ],
      "details": {
        "syntax": "{state}",
        "canonicalKey": "state",
        "aliases": [],
        "producer": "command.togglesr",
        "lifetime": "This command reply only.",
        "behavior": "Handler substitutions and global variables are context-dependent; this token is not exported to later actions."
      }
    },
    {
      "id": "context.automation",
      "kind": "context",
      "runtimeKey": "automation",
      "label": "Automation",
      "category": "When / Where / Do",
      "summary": "When an enabled automation matches its trigger and Where filter, extract event variables and run actions in order. Individual failures are logged and later actions continue. Cooldown is per automation/platform, memory-only. Positive trigger offsets schedule the sequence.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "fireEvent"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "configuration",
          "value": {
            "name": "Example welcome",
            "triggerType": "viewer_join",
            "triggerPlatform": "twitch",
            "triggerFilters": {},
            "cooldownSec": 0,
            "actions": [
              {
                "type": "chat",
                "message": "Welcome {user}!",
                "platform": "event"
              }
            ]
          }
        }
      ],
      "details": {
        "fields": [
          "triggerType",
          "triggerPlatform",
          "triggerFilters",
          "cooldownSec",
          "actions"
        ],
        "defaults": {
          "triggerPlatform": "all",
          "cooldownSec": 0
        },
        "behavior": "When an enabled automation matches its trigger and Where filter, extract event variables and run actions in order. Individual failures are logged and later actions continue. Cooldown is per automation/platform, memory-only. Positive trigger offsets schedule the sequence.",
        "pickerRule": "For command/pad, the action picker exposes all nonhidden actions regardless of declared contexts. Runtime requirements still apply.",
        "ui": {
          "path": [
            "Bot",
            "Automations",
            "+ New"
          ],
          "categorySetup": "Before opening a new editor, optionally choose + New Category in the relevant Bot tab, enter Category name and click Save. In the editor choose that Category, or leave Uncategorized. Categories organize items; they do not filter stream categories or events.",
          "initialFields": [
            {
              "label": "Name",
              "value": "Choose a descriptive name."
            },
            {
              "label": "Category",
              "value": "Choose an existing organizational category or Uncategorized."
            },
            {
              "label": "Enable automation",
              "value": "On by default; switch off while preparing if it must not fire yet."
            }
          ],
          "steps": [
            "Open Bot, then Automations. Create an optional organizational category before choosing + New.",
            "Fill Name, Category and the Enable automation toggle at the top of New Automation.",
            "Open When. Choose Trigger category, then Trigger event. For Platform events choose Platform before Trigger event. Fill Trigger filters and Cooldown (seconds); 0 means no cooldown.",
            "Open Where and select Platform from the supported options for this trigger. Changing the trigger can change the available platform choices.",
            "Open Do (for commands also expand Advanced Actions). Choose an action category and action, then click Add action; alternatively search for its exact label. Expand its card and fill the documented fields using real resource pickers. Repeat for every action. Use Move action up / Move action down to set execution order. Actions run sequentially; adding several does not create parallel execution.",
            "Click Create Automation; use Save Changes when editing. Enable it when ready.",
            "Save, reopen and verify the persisted fields and action order. Test only when the effects are intended: chat, audio, ads and external app actions can affect connected services. A synthetic test does not establish that a real incoming event or platform permission works. Confirm a real eligible event separately during live UAT."
          ]
        }
      }
    },
    {
      "id": "context.timer",
      "kind": "context",
      "runtimeKey": "timer",
      "label": "Timer",
      "category": "When / Where / Do",
      "summary": "Fire independently per selected platform at intervalMin (minimum 1, default 5). Require online status when onlineOnly (default true) and chatLines minimum (default 0). Reset platform line count on eligible firing. Multiple chat actions rotate sequentially/randomly: one selected chat moves to the front, then non-chat actions run. Individual failures log and continue. all/event inner targets are scoped to the eligible platform; explicit different targets are skipped.",
      "status": "supported",
      "contexts": [
        "timer"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "_fireTimer / _scopeTimerActionToPlatform"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "configuration",
          "value": {
            "name": "Example reminder",
            "intervalMin": 5,
            "chatLines": 0,
            "onlineOnly": true,
            "platforms": {
              "twitch": true,
              "youtube": false,
              "kick": false,
              "tiktok": false
            },
            "actions": [
              {
                "type": "chat",
                "message": "Community night is Friday!",
                "platform": "event"
              }
            ]
          }
        }
      ],
      "details": {
        "fields": [
          "intervalMin",
          "chatLines",
          "onlineOnly",
          "platforms",
          "rotation",
          "actions"
        ],
        "defaults": {
          "intervalMin": 5,
          "chatLines": 0,
          "onlineOnly": true,
          "rotation": "sequential",
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true,
            "tiktok": false
          }
        },
        "identity": "No incoming viewer. command=timer; timerId/sourceId/sourceName identify the timer.",
        "behavior": "Fire independently per selected platform at intervalMin (minimum 1, default 5). Require online status when onlineOnly (default true) and chatLines minimum (default 0). Reset platform line count on eligible firing. Multiple chat actions rotate sequentially/randomly: one selected chat moves to the front, then non-chat actions run. Individual failures log and continue. all/event inner targets are scoped to the eligible platform; explicit different targets are skipped.",
        "pickerRule": "For command/pad, the action picker exposes all nonhidden actions regardless of declared contexts. Runtime requirements still apply.",
        "ui": {
          "path": [
            "Bot",
            "Timers",
            "+ New"
          ],
          "categorySetup": "Before opening a new editor, optionally choose + New Category in the relevant Bot tab, enter Category name and click Save. In the editor choose that Category, or leave Uncategorized. Categories organize items; they do not filter stream categories or events.",
          "initialFields": [
            {
              "label": "Name",
              "value": "Choose a descriptive timer name."
            },
            {
              "label": "Category",
              "value": "Existing category or Uncategorized."
            },
            {
              "label": "Enable timer",
              "value": "On by default."
            }
          ],
          "steps": [
            "Open Bot, then Timers. Create an optional category before clicking + New.",
            "Fill Name, Category and Enable timer.",
            "Open When. Set Interval (minutes), default 5 and minimum 1, and Min chat lines, default 0. With multiple Send Chat Message actions choose Chat message rotation: Sequential or Random.",
            "Open Where. Set Online only (default on) and Active on platforms (Twitch, YouTube and Kick default on; TikTok off). Each selected platform fires independently. TikTok timers only send supported chat messages.",
            "Open Do (for commands also expand Advanced Actions). Choose an action category and action, then click Add action; alternatively search for its exact label. Expand its card and fill the documented fields using real resource pickers. Repeat for every action. Use Move action up / Move action down to set execution order. Actions run sequentially; adding several does not create parallel execution.",
            "Click Create Timer, or Save Changes when editing.",
            "Save, reopen and verify the persisted fields and action order. Test only when the effects are intended: chat, audio, ads and external app actions can affect connected services. A synthetic test does not establish that a real incoming event or platform permission works. Confirm a real eligible event separately during live UAT."
          ]
        }
      }
    },
    {
      "id": "context.command",
      "kind": "context",
      "runtimeKey": "command",
      "label": "Custom command",
      "category": "When / Where / Do",
      "summary": "Match !name or configured aliases; check enabled status, platform, authority, user/global cooldown and configured response/action output. Built-in triggers take precedence over custom commands, then Marketplace commands. Send the configured response before actions. Custom action failures log and continue; a handler returning without a throw is not proof of an external side effect. Broadcaster actors bypass user/global command cooldowns; these cooldowns persist and are scoped per platform.",
      "status": "supported",
      "contexts": [
        "command"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "handleCustomCommand / handleBotCommand"
        },
        {
          "path": "src/features/custom-commands.js",
          "symbol": "handleCustomCommand / handleBotCommand"
        },
        {
          "path": "src/features/command-authority.js",
          "symbol": "handleCustomCommand / handleBotCommand"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "configuration",
          "value": {
            "name": "hello",
            "response": "Hello {user}!"
          }
        }
      ],
      "details": {
        "fields": [
          "name",
          "aliases",
          "platforms",
          "requiredAuthority",
          "cooldownSec",
          "globalCooldownSec",
          "response",
          "responseReplyMode",
          "actions"
        ],
        "defaults": {
          "requiredAuthority": "anyone",
          "cooldownSec": 5,
          "globalCooldownSec": 5,
          "responseReplyMode": "normal",
          "enabled": true,
          "platforms": {
            "twitch": true,
            "youtube": true,
            "kick": true,
            "tiktok": true
          }
        },
        "limits": {
          "nameCharacters": 32,
          "aliases": 20,
          "actions": 25,
          "responseCharacters": 4000,
          "cooldownSeconds": 3600
        },
        "identity": "Incoming command sender, first-argument target and actor; synthetic automation actors differ from viewers.",
        "authorityLevels": {
          "anyone": 0,
          "follower": 1,
          "subscriber": 2,
          "vip": 3,
          "moderator": 4,
          "super_mod": 5,
          "broadcaster": 6
        },
        "behavior": "Match !name or configured aliases; check enabled status, platform, authority, user/global cooldown and configured response/action output. Built-in triggers take precedence over custom commands, then Marketplace commands. Send the configured response before actions. Custom action failures log and continue; a handler returning without a throw is not proof of an external side effect. Broadcaster actors bypass user/global command cooldowns; these cooldowns persist and are scoped per platform.",
        "pickerRule": "For command/pad, the action picker exposes all nonhidden actions regardless of declared contexts. Runtime requirements still apply.",
        "ui": {
          "path": [
            "Bot",
            "Commands",
            "+ New"
          ],
          "categorySetup": "Before opening a new editor, optionally choose + New Category in the relevant Bot tab, enter Category name and click Save. In the editor choose that Category, or leave Uncategorized. Categories organize items; they do not filter stream categories or events.",
          "initialFields": [
            {
              "label": "Command name",
              "value": "Enter the trigger name; the editor already displays !."
            },
            {
              "label": "Category",
              "value": "Existing category or Uncategorized."
            },
            {
              "label": "Enable command",
              "value": "On by default."
            }
          ],
          "steps": [
            "Open Bot, then Commands. Create an optional category before clicking + New.",
            "Fill Command name, Category and Enable command.",
            "Open When. Add optional Aliases with +. Choose Who can use it (default Anyone); set User cooldown (sec) and Global cooldown (sec), both default 5.",
            "Open Where. Set Active on platforms deliberately; all four platform toggles default on, but connections and platform capabilities still apply.",
            "Open Do. Enter Response, or leave it blank for actions only. Choose Response style (default Send normal message). The response sends before Advanced Actions.",
            "Open Do (for commands also expand Advanced Actions). Choose an action category and action, then click Add action; alternatively search for its exact label. Expand its card and fill the documented fields using real resource pickers. Repeat for every action. Use Move action up / Move action down to set execution order. Actions run sequentially; adding several does not create parallel execution.",
            "Click Create Command, or Save Changes when editing.",
            "Save, reopen and verify the persisted fields and action order. Test only when the effects are intended: chat, audio, ads and external app actions can affect connected services. A synthetic test does not establish that a real incoming event or platform permission works. Confirm a real eligible event separately during live UAT."
          ]
        }
      }
    },
    {
      "id": "context.pad",
      "kind": "context",
      "runtimeKey": "pad",
      "label": "SheevPad action button",
      "category": "When / Where / Do",
      "summary": "Click an enabled action button to execute up to 20 stored actions in order. A thrown failure stops remaining actions; visual state toggles only after success. Synthetic username defaults SheevPad, role broadcaster/authority 99, command sheevpad; missing/invalid requested platform defaults Twitch. Buttons are not viewer-triggered events. Groups organize buttons; visual toggle is appearance, not external-device state.",
      "status": "supported",
      "contexts": [
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "server.js",
          "symbol": "runSheevPadButton / normalizeSheevPadConfig"
        },
        {
          "path": "public/index.html",
          "symbol": "runSheevPadButton / normalizeSheevPadConfig"
        },
        {
          "path": "src/features/sheevpad/visual-toggle-state.js",
          "symbol": "runSheevPadButton / normalizeSheevPadConfig"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "configuration",
          "value": {
            "kind": "button",
            "label": "Play example audio",
            "enabled": true,
            "actions": [
              {
                "type": "send_overlay_audio",
                "mediaId": "fixture-audio",
                "volume": 100
              }
            ]
          }
        }
      ],
      "details": {
        "fields": [
          "kind",
          "groupId",
          "label",
          "enabled",
          "actions",
          "visualToggle",
          "visualActive"
        ],
        "defaults": {
          "kind": "button",
          "enabled": true,
          "visualToggle": false
        },
        "limits": {
          "actionsPerButton": 20,
          "buttons": 80
        },
        "navigation": "See navigation.pad.*; navigation buttons cannot run actions.",
        "behavior": "Click an enabled action button to execute up to 20 stored actions in order. A thrown failure stops remaining actions; visual state toggles only after success. Synthetic username defaults SheevPad, role broadcaster/authority 99, command sheevpad; missing/invalid requested platform defaults Twitch. Buttons are not viewer-triggered events. Groups organize buttons; visual toggle is appearance, not external-device state.",
        "pickerRule": "For command/pad, the action picker exposes all nonhidden actions regardless of declared contexts. Runtime requirements still apply.",
        "ui": {
          "path": [
            "SheevPad",
            "Add Group / Add Button"
          ],
          "categorySetup": "SheevPad uses Group rather than Bot Category. Choose Add Group, fill Group Name, optionally enable Favorite group, then Save Group before assigning buttons.",
          "initialFields": [
            {
              "label": "Name",
              "value": "Button label, up to 40 characters."
            },
            {
              "label": "Type",
              "value": "Action button, or Mobile navigation."
            },
            {
              "label": "Group",
              "value": "Choose a saved group, or Ungrouped."
            },
            {
              "label": "Color",
              "value": "Choose button appearance."
            },
            {
              "label": "Background Image",
              "value": "Optional library image; Upload Images opens the Media Library."
            },
            {
              "label": "Enabled",
              "value": "On by default."
            },
            {
              "label": "Visual On/Off state",
              "value": "Off by default; appearance only. If enabled, Current visual state sets the displayed state."
            }
          ],
          "steps": [
            "Open SheevPad from the app header. Create and save any groups first.",
            "Choose Add Button. Fill Name, Type, Group, Color, optional Background Image and Enabled.",
            "For Action button, optionally configure Visual On/Off state and Current visual state. These do not branch the action list or read external device state.",
            "Open Do (for commands also expand Advanced Actions). Choose an action category and action, then click Add action; alternatively search for its exact label. Expand its card and fill the documented fields using real resource pickers. Repeat for every action. Use Move action up / Move action down to set execution order. Actions run sequentially; adding several does not create parallel execution.",
            "Click Save Button explicitly. Test can execute effects; use it only when safe. Preview arranges the mobile/tablet layout.",
            "Save, reopen and verify the persisted fields and action order. Test only when the effects are intended: chat, audio, ads and external app actions can affect connected services. A synthetic test does not establish that a real incoming event or platform permission works. Confirm a real eligible event separately during live UAT."
          ]
        }
      }
    },
    {
      "id": "routing.action-targets",
      "kind": "routing",
      "runtimeKey": "action-targets",
      "label": "Action output routing",
      "category": "Where / variables",
      "summary": "event/missing means origin; all means Twitch + YouTube + Kick. Explicit TikTok is supported by eligible actions. Local obs, streamlabs or app events are not chat destinations: choose an explicit output platform when required. Stream title/category use separate three-platform toggles; Conversation Starters has four explicit toggles; trivia has base plus extra targets. Timer gates restrict inner all/event routing.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "targetPlatforms / ACTION_PLATFORM_CAPABILITIES"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [],
      "examples": [],
      "details": {
        "behavior": "event/missing means origin; all means Twitch + YouTube + Kick. Explicit TikTok is supported by eligible actions. Local obs, streamlabs or app events are not chat destinations: choose an explicit output platform when required. Stream title/category use separate three-platform toggles; Conversation Starters has four explicit toggles; trivia has base plus extra targets. Timer gates restrict inner all/event routing."
      }
    },
    {
      "id": "routing.variables",
      "kind": "routing",
      "runtimeKey": "variables",
      "label": "Variable resolution",
      "category": "Where / variables",
      "summary": "For action templates, event values substitute first, then the global engine. Context-specific title/message/target values can differ from global aliases. Global keys are case-insensitive; event substitution is case-sensitive. Colon arguments support backslash escaping. Unknown placeholders remain literal; null/error/timeout uses declared fallback (default Unavailable). Resolver timeout defaults 2500 ms; final global output cap 480 characters. No general nested-expression language.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/command-variables.js",
          "symbol": "createCommandVariableEngine"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [],
      "examples": [],
      "details": {
        "behavior": "For action templates, event values substitute first, then the global engine. Context-specific title/message/target values can differ from global aliases. Global keys are case-insensitive; event substitution is case-sensitive. Colon arguments support backslash escaping. Unknown placeholders remain literal; null/error/timeout uses declared fallback (default Unavailable). Resolver timeout defaults 2500 ms; final global output cap 480 characters. No general nested-expression language."
      }
    },
    {
      "id": "routing.extensions",
      "kind": "routing",
      "runtimeKey": "extensions",
      "label": "Installed actions, events and games",
      "category": "Where / variables",
      "summary": "The public built-in inventory does not enumerate arbitrary installed packages. Imported app events require an installed active library and subscription; library mappings define extra event.<key> values. Imported action outputs become available only after the producer runs in the current sequence. Marketplace game commands use package instructions and effective configured triggers/aliases; require compatible enabled installed packages. See the action-library and chat-game creator contracts for schemas.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "integrations/action-library-runtime/execution.js",
          "symbol": "applyImportedActionResponseValues"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [],
      "examples": [],
      "details": {
        "behavior": "The public built-in inventory does not enumerate arbitrary installed packages. Imported app events require an installed active library and subscription; library mappings define extra event.<key> values. Imported action outputs become available only after the producer runs in the current sequence. Marketplace game commands use package instructions and effective configured triggers/aliases; require compatible enabled installed packages. See the action-library and chat-game creator contracts for schemas."
      }
    },
    {
      "id": "navigation.pad.target",
      "kind": "navigation",
      "runtimeKey": "pad.target",
      "label": "SheevPad target",
      "category": "SheevPad navigation",
      "summary": "Scroll to the configured targetGroupId. The selected group must exist.",
      "status": "supported",
      "contexts": [
        "mobile"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Mobile/tablet SheevPad with groups configured."
      },
      "sourceRefs": [
        {
          "path": "public/mobile.html",
          "symbol": "navigateSheevPadMobile"
        },
        {
          "path": "server.js",
          "symbol": "normalizeSheevPadConfig"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Client-side scroll only; no actions run. Server execution rejects navigation buttons. Missing destination gives No matching group found feedback."
      ],
      "relatedIds": [
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "configuration",
          "value": {
            "kind": "navigation",
            "label": "Go target",
            "navMode": "target",
            "targetGroupId": "fixture-group"
          }
        }
      ],
      "details": {
        "behavior": "Scroll to the configured targetGroupId. The selected group must exist.",
        "mode": "target",
        "defaultMode": "target",
        "fields": [
          "targetGroupId"
        ],
        "ui": {
          "path": [
            "SheevPad",
            "Add Button"
          ],
          "initialFields": [
            {
              "label": "Name",
              "value": "Button label, up to 40 characters."
            },
            {
              "label": "Type",
              "value": "Action button, or Mobile navigation."
            },
            {
              "label": "Group",
              "value": "Choose a saved group, or Ungrouped."
            },
            {
              "label": "Color",
              "value": "Choose button appearance."
            },
            {
              "label": "Background Image",
              "value": "Optional library image; Upload Images opens the Media Library."
            },
            {
              "label": "Enabled",
              "value": "On by default."
            }
          ],
          "steps": [
            "SheevPad uses Group rather than Bot Category. Choose Add Group, fill Group Name, optionally enable Favorite group, then Save Group before assigning buttons.",
            "Choose Add Button. Set Name, Type = Mobile navigation, Group, optional appearance and Enabled.",
            "Set Navigation = Target group.",
            "Choose an existing Target Group.",
            "Click Save Button. Open mobile/tablet SheevPad and tap the navigation button to check scrolling. It does not execute actions."
          ]
        }
      }
    },
    {
      "id": "navigation.pad.next",
      "kind": "navigation",
      "runtimeKey": "pad.next",
      "label": "SheevPad next",
      "category": "SheevPad navigation",
      "summary": "Scroll to the next group relative to current scroll position; clamp at the last group, without wrapping.",
      "status": "supported",
      "contexts": [
        "mobile"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Mobile/tablet SheevPad with groups configured."
      },
      "sourceRefs": [
        {
          "path": "public/mobile.html",
          "symbol": "navigateSheevPadMobile"
        },
        {
          "path": "server.js",
          "symbol": "normalizeSheevPadConfig"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Client-side scroll only; no actions run. Server execution rejects navigation buttons. Missing destination gives No matching group found feedback."
      ],
      "relatedIds": [
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "configuration",
          "value": {
            "kind": "navigation",
            "label": "Go next",
            "navMode": "next"
          }
        }
      ],
      "details": {
        "behavior": "Scroll to the next group relative to current scroll position; clamp at the last group, without wrapping.",
        "mode": "next",
        "defaultMode": "target",
        "fields": [],
        "ui": {
          "path": [
            "SheevPad",
            "Add Button"
          ],
          "initialFields": [
            {
              "label": "Name",
              "value": "Button label, up to 40 characters."
            },
            {
              "label": "Type",
              "value": "Action button, or Mobile navigation."
            },
            {
              "label": "Group",
              "value": "Choose a saved group, or Ungrouped."
            },
            {
              "label": "Color",
              "value": "Choose button appearance."
            },
            {
              "label": "Background Image",
              "value": "Optional library image; Upload Images opens the Media Library."
            },
            {
              "label": "Enabled",
              "value": "On by default."
            }
          ],
          "steps": [
            "SheevPad uses Group rather than Bot Category. Choose Add Group, fill Group Name, optionally enable Favorite group, then Save Group before assigning buttons.",
            "Choose Add Button. Set Name, Type = Mobile navigation, Group, optional appearance and Enabled.",
            "Set Navigation = Next group.",
            "Click Save Button. Open mobile/tablet SheevPad and tap the navigation button to check scrolling. It does not execute actions."
          ]
        }
      }
    },
    {
      "id": "navigation.pad.previous",
      "kind": "navigation",
      "runtimeKey": "pad.previous",
      "label": "SheevPad previous",
      "category": "SheevPad navigation",
      "summary": "Scroll to the previous group relative to current scroll position; clamp at the first group, without wrapping.",
      "status": "supported",
      "contexts": [
        "mobile"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Mobile/tablet SheevPad with groups configured."
      },
      "sourceRefs": [
        {
          "path": "public/mobile.html",
          "symbol": "navigateSheevPadMobile"
        },
        {
          "path": "server.js",
          "symbol": "normalizeSheevPadConfig"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Client-side scroll only; no actions run. Server execution rejects navigation buttons. Missing destination gives No matching group found feedback."
      ],
      "relatedIds": [
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "configuration",
          "value": {
            "kind": "navigation",
            "label": "Go previous",
            "navMode": "previous"
          }
        }
      ],
      "details": {
        "behavior": "Scroll to the previous group relative to current scroll position; clamp at the first group, without wrapping.",
        "mode": "previous",
        "defaultMode": "target",
        "fields": [],
        "ui": {
          "path": [
            "SheevPad",
            "Add Button"
          ],
          "initialFields": [
            {
              "label": "Name",
              "value": "Button label, up to 40 characters."
            },
            {
              "label": "Type",
              "value": "Action button, or Mobile navigation."
            },
            {
              "label": "Group",
              "value": "Choose a saved group, or Ungrouped."
            },
            {
              "label": "Color",
              "value": "Choose button appearance."
            },
            {
              "label": "Background Image",
              "value": "Optional library image; Upload Images opens the Media Library."
            },
            {
              "label": "Enabled",
              "value": "On by default."
            }
          ],
          "steps": [
            "SheevPad uses Group rather than Bot Category. Choose Add Group, fill Group Name, optionally enable Favorite group, then Save Group before assigning buttons.",
            "Choose Add Button. Set Name, Type = Mobile navigation, Group, optional appearance and Enabled.",
            "Set Navigation = Previous group.",
            "Click Save Button. Open mobile/tablet SheevPad and tap the navigation button to check scrolling. It does not execute actions."
          ]
        }
      }
    },
    {
      "id": "navigation.pad.favorite",
      "kind": "navigation",
      "runtimeKey": "pad.favorite",
      "label": "SheevPad favorite",
      "category": "SheevPad navigation",
      "summary": "Scroll to layout.favoriteGroupId; a favorite group must be configured and exist.",
      "status": "supported",
      "contexts": [
        "mobile"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Mobile/tablet SheevPad with groups configured."
      },
      "sourceRefs": [
        {
          "path": "public/mobile.html",
          "symbol": "navigateSheevPadMobile"
        },
        {
          "path": "server.js",
          "symbol": "normalizeSheevPadConfig"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [
        "Client-side scroll only; no actions run. Server execution rejects navigation buttons. Missing destination gives No matching group found feedback."
      ],
      "relatedIds": [
        "context.pad"
      ],
      "examples": [
        {
          "purpose": "Illustrative configuration; replace fixture resources in the editor. This is not an import file.",
          "format": "configuration",
          "value": {
            "kind": "navigation",
            "label": "Go favorite",
            "navMode": "favorite"
          }
        }
      ],
      "details": {
        "behavior": "Scroll to layout.favoriteGroupId; a favorite group must be configured and exist.",
        "mode": "favorite",
        "defaultMode": "target",
        "fields": [
          "layout.favoriteGroupId"
        ],
        "ui": {
          "path": [
            "SheevPad",
            "Add Button"
          ],
          "initialFields": [
            {
              "label": "Name",
              "value": "Button label, up to 40 characters."
            },
            {
              "label": "Type",
              "value": "Action button, or Mobile navigation."
            },
            {
              "label": "Group",
              "value": "Choose a saved group, or Ungrouped."
            },
            {
              "label": "Color",
              "value": "Choose button appearance."
            },
            {
              "label": "Background Image",
              "value": "Optional library image; Upload Images opens the Media Library."
            },
            {
              "label": "Enabled",
              "value": "On by default."
            }
          ],
          "steps": [
            "SheevPad uses Group rather than Bot Category. Choose Add Group, fill Group Name, optionally enable Favorite group, then Save Group before assigning buttons.",
            "Choose Add Button. Set Name, Type = Mobile navigation, Group, optional appearance and Enabled.",
            "Set Navigation = Favorite group.",
            "Edit the destination group, enable Favorite group and Save Group.",
            "Click Save Button. Open mobile/tablet SheevPad and tap the navigation button to check scrolling. It does not execute actions."
          ]
        }
      }
    },
    {
      "id": "context.raid-response",
      "kind": "context",
      "runtimeKey": "raid-response",
      "label": "Set up an automatic raid response, snooze ads and pause music",
      "category": "Composing UI instructions",
      "summary": "A complete editor example combining an incoming Twitch raid with an ordered welcome, ad snooze and music pause.",
      "status": "supported",
      "contexts": [
        "automation"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "public/index.html",
          "symbol": "renderAutoEditor / renderActionBuilder / botCategorySelectHtml"
        },
        {
          "path": "src/features/automations.js",
          "symbol": "raid / chat / twitch_snooze_upcoming_ad / song_pause"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "context.automation",
        "trigger.raid",
        "action.chat",
        "action.twitch_snooze_upcoming_ad",
        "action.song_pause"
      ],
      "examples": [],
      "details": {
        "behavior": "One Incoming raid automation runs three actions in sequence. Keep the trigger ad-window filter off so it does not suppress the entire response. Optional action-level ad gating affects only the snooze.",
        "ui": {
          "path": [
            "Bot",
            "Automations",
            "+ New"
          ],
          "categorySetup": "Before opening a new editor, optionally choose + New Category in the relevant Bot tab, enter Category name and click Save. In the editor choose that Category, or leave Uncategorized. Categories organize items; they do not filter stream categories or events.",
          "initialFields": [
            {
              "label": "Name",
              "value": "Incoming Raid Response"
            },
            {
              "label": "Category",
              "value": "Raids (create with + New Category first), or Uncategorized."
            },
            {
              "label": "Enable automation",
              "value": "Off while configuring; turn on and save when ready."
            }
          ],
          "steps": [
            "Connect the Twitch broadcaster account with ad-management access. Have an available ad snooze. Confirm which music source is active: Pause song controls SheevChat song playback or its configured Spotify mode; it does not pause every desktop music app.",
            "Open Bot > Automations. If desired, choose + New Category, enter Raids in Category name, and Save. Click + New.",
            "Set Name to Incoming Raid Response. Set Category to Raids (or Uncategorized). Switch Enable automation off while preparing.",
            "Open When: Trigger category = Raids; Trigger event = Incoming raid. Set Minimum viewers (0 = any) to 0; Only if next Twitch ad is within minutes (0 = off) to 0; Cooldown (seconds) to 0. Keeping the trigger ad filter off lets the response and music pause run even if no ad is imminent.",
            "Open Where: Platform = Twitch. Ad snoozing is Twitch-only; use a separate automation for other raid providers if required.",
            "Open Do. Choose Chat Bot Commands > Send chat message > Add action. Expand its card. Set Message to Thanks for the raid, {user}! Welcome {viewers} raiders! Set Send to to Same platform as event.",
            "Choose Stream Platform Commands > Snooze upcoming Twitch ad > Add action. Set Only if next ad is within minutes (0 = always) to 0 to attempt a snooze for every raid. Optionally use 5 to skip only the snooze action when the captured next-ad schedule is outside five minutes or missing; leave the trigger filter at 0.",
            "Choose Music Controls > Pause song > Add action. Leave Send chat response off unless a playback confirmation is wanted. Leave its output Platform at Same platform as event.",
            "Use Move action up / Move action down to keep Send chat message, Snooze upcoming Twitch ad, Pause song in that order. One raid starts all three in sequence, without adding a delay. They are not simultaneous or transactional; failures are logged and later automation actions continue.",
            "Click Create Automation. Reopen it and verify the saved fields and order. When ready, turn Enable automation on and click Save Changes.",
            "During live UAT, receive an eligible Twitch raid while music is playing and an ad snooze is available. Expect the welcome message, an attempted snooze and paused playback. Check platform results/logs as well as the UI. A synthetic event cannot prove Twitch permissions or delivery."
          ]
        }
      }
    },
    {
      "id": "variable.action.chat_delay.delay",
      "kind": "variable",
      "runtimeKey": "action.chat_delay.delay",
      "label": "{delay}",
      "category": "Action-local variables",
      "summary": "The configured delayed-chat delay in seconds, local to that delayed message.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "src/features/automations.js",
          "symbol": "ACTION_REGISTRY.chat_delay.execute"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "action.chat_delay"
      ],
      "examples": [
        {
          "purpose": "Only inside Send chat message (delayed).",
          "format": "template",
          "value": "Sending after {delay} seconds"
        }
      ],
      "details": {
        "syntax": "{delay}",
        "canonicalKey": "delay",
        "aliases": [],
        "producer": "action.chat_delay",
        "lifetime": "Delayed message only.",
        "behavior": "Not a general output for later actions."
      }
    },
    {
      "id": "variable.imported.lastActionOk",
      "kind": "variable",
      "runtimeKey": "imported.lastActionOk",
      "label": "{lastActionOk}",
      "category": "Imported action outputs",
      "summary": "Imported-action response helper lastActionOk.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "integrations/action-library-runtime/execution.js",
          "symbol": "applyImportedActionResponseValues"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.extensions"
      ],
      "examples": [
        {
          "purpose": "After an imported action that ingests a response; inspect the package output contract.",
          "format": "template",
          "value": "{lastActionOk}"
        }
      ],
      "details": {
        "syntax": "{lastActionOk}",
        "canonicalKey": "lastActionOk",
        "aliases": [],
        "producer": "Imported action with response mapping.",
        "lifetime": "Current sequence, overwritten by subsequent response producers.",
        "behavior": "Set true when a response is applied; not a universal failure-status variable."
      }
    },
    {
      "id": "variable.imported.lastActionType",
      "kind": "variable",
      "runtimeKey": "imported.lastActionType",
      "label": "{lastActionType}",
      "category": "Imported action outputs",
      "summary": "Imported-action response helper lastActionType.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "integrations/action-library-runtime/execution.js",
          "symbol": "applyImportedActionResponseValues"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.extensions"
      ],
      "examples": [
        {
          "purpose": "After an imported action that ingests a response; inspect the package output contract.",
          "format": "template",
          "value": "{lastActionType}"
        }
      ],
      "details": {
        "syntax": "{lastActionType}",
        "canonicalKey": "lastActionType",
        "aliases": [],
        "producer": "Imported action with response mapping.",
        "lifetime": "Current sequence, overwritten by subsequent response producers.",
        "behavior": "Describes the latest applied imported response, its mapped values or missing output keys; JSON/raw helpers are compacted to 4000 characters."
      }
    },
    {
      "id": "variable.imported.lastActionId",
      "kind": "variable",
      "runtimeKey": "imported.lastActionId",
      "label": "{lastActionId}",
      "category": "Imported action outputs",
      "summary": "Imported-action response helper lastActionId.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "integrations/action-library-runtime/execution.js",
          "symbol": "applyImportedActionResponseValues"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.extensions"
      ],
      "examples": [
        {
          "purpose": "After an imported action that ingests a response; inspect the package output contract.",
          "format": "template",
          "value": "{lastActionId}"
        }
      ],
      "details": {
        "syntax": "{lastActionId}",
        "canonicalKey": "lastActionId",
        "aliases": [],
        "producer": "Imported action with response mapping.",
        "lifetime": "Current sequence, overwritten by subsequent response producers.",
        "behavior": "Describes the latest applied imported response, its mapped values or missing output keys; JSON/raw helpers are compacted to 4000 characters."
      }
    },
    {
      "id": "variable.imported.lastActionLabel",
      "kind": "variable",
      "runtimeKey": "imported.lastActionLabel",
      "label": "{lastActionLabel}",
      "category": "Imported action outputs",
      "summary": "Imported-action response helper lastActionLabel.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "integrations/action-library-runtime/execution.js",
          "symbol": "applyImportedActionResponseValues"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.extensions"
      ],
      "examples": [
        {
          "purpose": "After an imported action that ingests a response; inspect the package output contract.",
          "format": "template",
          "value": "{lastActionLabel}"
        }
      ],
      "details": {
        "syntax": "{lastActionLabel}",
        "canonicalKey": "lastActionLabel",
        "aliases": [],
        "producer": "Imported action with response mapping.",
        "lifetime": "Current sequence, overwritten by subsequent response producers.",
        "behavior": "Describes the latest applied imported response, its mapped values or missing output keys; JSON/raw helpers are compacted to 4000 characters."
      }
    },
    {
      "id": "variable.imported.lastActionNamespace",
      "kind": "variable",
      "runtimeKey": "imported.lastActionNamespace",
      "label": "{lastActionNamespace}",
      "category": "Imported action outputs",
      "summary": "Imported-action response helper lastActionNamespace.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "integrations/action-library-runtime/execution.js",
          "symbol": "applyImportedActionResponseValues"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.extensions"
      ],
      "examples": [
        {
          "purpose": "After an imported action that ingests a response; inspect the package output contract.",
          "format": "template",
          "value": "{lastActionNamespace}"
        }
      ],
      "details": {
        "syntax": "{lastActionNamespace}",
        "canonicalKey": "lastActionNamespace",
        "aliases": [],
        "producer": "Imported action with response mapping.",
        "lifetime": "Current sequence, overwritten by subsequent response producers.",
        "behavior": "Describes the latest applied imported response, its mapped values or missing output keys; JSON/raw helpers are compacted to 4000 characters."
      }
    },
    {
      "id": "variable.imported.lastActionOutputKeys",
      "kind": "variable",
      "runtimeKey": "imported.lastActionOutputKeys",
      "label": "{lastActionOutputKeys}",
      "category": "Imported action outputs",
      "summary": "Imported-action response helper lastActionOutputKeys.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "integrations/action-library-runtime/execution.js",
          "symbol": "applyImportedActionResponseValues"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.extensions"
      ],
      "examples": [
        {
          "purpose": "After an imported action that ingests a response; inspect the package output contract.",
          "format": "template",
          "value": "{lastActionOutputKeys}"
        }
      ],
      "details": {
        "syntax": "{lastActionOutputKeys}",
        "canonicalKey": "lastActionOutputKeys",
        "aliases": [],
        "producer": "Imported action with response mapping.",
        "lifetime": "Current sequence, overwritten by subsequent response producers.",
        "behavior": "Describes the latest applied imported response, its mapped values or missing output keys; JSON/raw helpers are compacted to 4000 characters."
      }
    },
    {
      "id": "variable.imported.lastActionOutputSummary",
      "kind": "variable",
      "runtimeKey": "imported.lastActionOutputSummary",
      "label": "{lastActionOutputSummary}",
      "category": "Imported action outputs",
      "summary": "Imported-action response helper lastActionOutputSummary.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "integrations/action-library-runtime/execution.js",
          "symbol": "applyImportedActionResponseValues"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.extensions"
      ],
      "examples": [
        {
          "purpose": "After an imported action that ingests a response; inspect the package output contract.",
          "format": "template",
          "value": "{lastActionOutputSummary}"
        }
      ],
      "details": {
        "syntax": "{lastActionOutputSummary}",
        "canonicalKey": "lastActionOutputSummary",
        "aliases": [],
        "producer": "Imported action with response mapping.",
        "lifetime": "Current sequence, overwritten by subsequent response producers.",
        "behavior": "Describes the latest applied imported response, its mapped values or missing output keys; JSON/raw helpers are compacted to 4000 characters."
      }
    },
    {
      "id": "variable.imported.lastActionMissingOutputKeys",
      "kind": "variable",
      "runtimeKey": "imported.lastActionMissingOutputKeys",
      "label": "{lastActionMissingOutputKeys}",
      "category": "Imported action outputs",
      "summary": "Imported-action response helper lastActionMissingOutputKeys.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "integrations/action-library-runtime/execution.js",
          "symbol": "applyImportedActionResponseValues"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.extensions"
      ],
      "examples": [
        {
          "purpose": "After an imported action that ingests a response; inspect the package output contract.",
          "format": "template",
          "value": "{lastActionMissingOutputKeys}"
        }
      ],
      "details": {
        "syntax": "{lastActionMissingOutputKeys}",
        "canonicalKey": "lastActionMissingOutputKeys",
        "aliases": [],
        "producer": "Imported action with response mapping.",
        "lifetime": "Current sequence, overwritten by subsequent response producers.",
        "behavior": "Describes the latest applied imported response, its mapped values or missing output keys; JSON/raw helpers are compacted to 4000 characters."
      }
    },
    {
      "id": "variable.imported.lastActionValueCount",
      "kind": "variable",
      "runtimeKey": "imported.lastActionValueCount",
      "label": "{lastActionValueCount}",
      "category": "Imported action outputs",
      "summary": "Imported-action response helper lastActionValueCount.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "integrations/action-library-runtime/execution.js",
          "symbol": "applyImportedActionResponseValues"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.extensions"
      ],
      "examples": [
        {
          "purpose": "After an imported action that ingests a response; inspect the package output contract.",
          "format": "template",
          "value": "{lastActionValueCount}"
        }
      ],
      "details": {
        "syntax": "{lastActionValueCount}",
        "canonicalKey": "lastActionValueCount",
        "aliases": [],
        "producer": "Imported action with response mapping.",
        "lifetime": "Current sequence, overwritten by subsequent response producers.",
        "behavior": "Describes the latest applied imported response, its mapped values or missing output keys; JSON/raw helpers are compacted to 4000 characters."
      }
    },
    {
      "id": "variable.imported.lastActionResponseJson",
      "kind": "variable",
      "runtimeKey": "imported.lastActionResponseJson",
      "label": "{lastActionResponseJson}",
      "category": "Imported action outputs",
      "summary": "Imported-action response helper lastActionResponseJson.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "integrations/action-library-runtime/execution.js",
          "symbol": "applyImportedActionResponseValues"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.extensions"
      ],
      "examples": [
        {
          "purpose": "After an imported action that ingests a response; inspect the package output contract.",
          "format": "template",
          "value": "{lastActionResponseJson}"
        }
      ],
      "details": {
        "syntax": "{lastActionResponseJson}",
        "canonicalKey": "lastActionResponseJson",
        "aliases": [],
        "producer": "Imported action with response mapping.",
        "lifetime": "Current sequence, overwritten by subsequent response producers.",
        "behavior": "Describes the latest applied imported response, its mapped values or missing output keys; JSON/raw helpers are compacted to 4000 characters."
      }
    },
    {
      "id": "variable.imported.lastActionValuesJson",
      "kind": "variable",
      "runtimeKey": "imported.lastActionValuesJson",
      "label": "{lastActionValuesJson}",
      "category": "Imported action outputs",
      "summary": "Imported-action response helper lastActionValuesJson.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "integrations/action-library-runtime/execution.js",
          "symbol": "applyImportedActionResponseValues"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.extensions"
      ],
      "examples": [
        {
          "purpose": "After an imported action that ingests a response; inspect the package output contract.",
          "format": "template",
          "value": "{lastActionValuesJson}"
        }
      ],
      "details": {
        "syntax": "{lastActionValuesJson}",
        "canonicalKey": "lastActionValuesJson",
        "aliases": [],
        "producer": "Imported action with response mapping.",
        "lifetime": "Current sequence, overwritten by subsequent response producers.",
        "behavior": "Describes the latest applied imported response, its mapped values or missing output keys; JSON/raw helpers are compacted to 4000 characters."
      }
    },
    {
      "id": "variable.imported.lastActionRaw",
      "kind": "variable",
      "runtimeKey": "imported.lastActionRaw",
      "label": "{lastActionRaw}",
      "category": "Imported action outputs",
      "summary": "Imported-action response helper lastActionRaw.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "integrations/action-library-runtime/execution.js",
          "symbol": "applyImportedActionResponseValues"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.extensions"
      ],
      "examples": [
        {
          "purpose": "After an imported action that ingests a response; inspect the package output contract.",
          "format": "template",
          "value": "{lastActionRaw}"
        }
      ],
      "details": {
        "syntax": "{lastActionRaw}",
        "canonicalKey": "lastActionRaw",
        "aliases": [],
        "producer": "Imported action with response mapping.",
        "lifetime": "Current sequence, overwritten by subsequent response producers.",
        "behavior": "Describes the latest applied imported response, its mapped values or missing output keys; JSON/raw helpers are compacted to 4000 characters."
      }
    },
    {
      "id": "variable.imported.mapping.last",
      "kind": "variable",
      "runtimeKey": "imported.mapping.last",
      "label": "{last.<key>}",
      "category": "Imported action outputs",
      "summary": "Package-defined mapped response value.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "integrations/action-library-runtime/execution.js",
          "symbol": "applyImportedActionResponseValues"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.extensions"
      ],
      "examples": [
        {
          "purpose": "Replace namespace/key with the installed action’s declared output; syntax is a pattern.",
          "format": "template",
          "value": "{last.<key>}"
        }
      ],
      "details": {
        "syntax": "{last.<key>}",
        "canonicalKey": "last.<key>",
        "aliases": [],
        "producer": "Installed action responseMap.",
        "lifetime": "Current sequence only.",
        "behavior": "The response map supplies values. last.<key> is overwritten by a later producer of that key. Namespace and action ID forms reference the same mapped value; a sanitized namespace alias may also be present."
      }
    },
    {
      "id": "variable.imported.mapping.namespace",
      "kind": "variable",
      "runtimeKey": "imported.mapping.namespace",
      "label": "{<namespace>.<key>}",
      "category": "Imported action outputs",
      "summary": "Package-defined mapped response value.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "integrations/action-library-runtime/execution.js",
          "symbol": "applyImportedActionResponseValues"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.extensions"
      ],
      "examples": [
        {
          "purpose": "Replace namespace/key with the installed action’s declared output; syntax is a pattern.",
          "format": "template",
          "value": "{<namespace>.<key>}"
        }
      ],
      "details": {
        "syntax": "{<namespace>.<key>}",
        "canonicalKey": "<namespace>.<key>",
        "aliases": [],
        "producer": "Installed action responseMap.",
        "lifetime": "Current sequence only.",
        "behavior": "The response map supplies values. last.<key> is overwritten by a later producer of that key. Namespace and action ID forms reference the same mapped value; a sanitized namespace alias may also be present."
      }
    },
    {
      "id": "variable.imported.mapping.action",
      "kind": "variable",
      "runtimeKey": "imported.mapping.action",
      "label": "{<actionId>.<key>}",
      "category": "Imported action outputs",
      "summary": "Package-defined mapped response value.",
      "status": "supported",
      "contexts": [
        "automation",
        "timer",
        "command",
        "pad"
      ],
      "availability": {
        "verifiedIn": "2.8.0-beta.28",
        "requirements": "Use the matching SheevChat version."
      },
      "sourceRefs": [
        {
          "path": "integrations/action-library-runtime/execution.js",
          "symbol": "applyImportedActionResponseValues"
        }
      ],
      "reviewStatus": "source-verified",
      "limitations": [],
      "relatedIds": [
        "routing.extensions"
      ],
      "examples": [
        {
          "purpose": "Replace namespace/key with the installed action’s declared output; syntax is a pattern.",
          "format": "template",
          "value": "{<actionId>.<key>}"
        }
      ],
      "details": {
        "syntax": "{<actionId>.<key>}",
        "canonicalKey": "<actionId>.<key>",
        "aliases": [],
        "producer": "Installed action responseMap.",
        "lifetime": "Current sequence only.",
        "behavior": "The response map supplies values. last.<key> is overwritten by a later producer of that key. Namespace and action ID forms reference the same mapped value; a sanitized namespace alias may also be present."
      }
    }
  ]
}
