{"record":{"id":"3cbe969a0af8ce06","repo":"block/buzz","slug":"plugin-json-defaults-triggers-unknown-key-key","errorCode":null,"errorMessage":"plugin.json defaults.triggers: unknown key \"{key}\"","messagePattern":"plugin\\.json defaults\\.triggers: unknown key \"(.+?)\"","errorType":"validation","errorClass":"ValidationDiagnostic::Warning","httpStatus":null,"severity":"warning","filePath":"crates/buzz-persona/src/validate.rs","lineNumber":343,"sourceCode":"    // Unknown keys in `defaults`.\n    if let Some(defaults) = obj.get(\"defaults\").and_then(|v| v.as_object()) {\n        let known_behavioral: HashSet<&str> = KNOWN_BEHAVIORAL_KEYS.iter().copied().collect();\n        for key in defaults.keys() {\n            if !known_behavioral.contains(key.as_str()) {\n                report.warn(format!(\"plugin.json defaults: unknown key \\\"{key}\\\"\"));\n            }\n        }\n\n        // Unknown keys in `defaults.triggers` (or legacy `defaults.respond_to`).\n        let triggers_obj = defaults\n            .get(\"triggers\")\n            .or_else(|| defaults.get(\"respond_to\"))\n            .and_then(|v| v.as_object());\n        if let Some(rt) = triggers_obj {\n            let known_rt: HashSet<&str> = KNOWN_RESPOND_TO_KEYS.iter().copied().collect();\n            for key in rt.keys() {\n                if !known_rt.contains(key.as_str()) {\n                    report.warn(format!(\n                        \"plugin.json defaults.triggers: unknown key \\\"{key}\\\"\"\n                    ));\n                }\n            }\n        }\n    }\n}\n\n/// For each skill directory referenced by a loaded persona, check that the\n/// SKILL.md `name:` field matches the directory name. Emits warnings.\nfn advisory_check_skill_names(\n    pack_dir: &Path,\n    loaded: &pack::LoadedPack,\n    report: &mut ValidationReport,\n) {\n    // Collect all skill paths referenced by any persona.\n    let mut skill_paths: Vec<std::path::PathBuf> = Vec::new();\n    for persona in &loaded.personas {","sourceCodeStart":325,"sourceCodeEnd":361,"githubUrl":"https://github.com/block/buzz/blob/934f3325c3fdaa3a6f23134b74518139aac8ca3f/crates/buzz-persona/src/validate.rs#L325-L361","documentation":"Advisory lint during persona pack validation: inside defaults.triggers (or the legacy defaults.respond_to alias), a key is present that is not one of the accepted sub-keys mentions, keywords, all_messages. Emitted as a warning on the ValidationReport; the pack still loads and the unknown trigger key is ignored.","triggerScenarios":"Adding speculative trigger configuration (e.g. 'channels', 'schedule', 'regex') that the trigger engine does not read; misspelling 'keywords'; migrating from another pack format whose trigger options differ.","commonSituations":"Persona authors assuming richer trigger semantics than implemented; copy-paste between pack versions; a trigger silently never firing because its key is unknown.","solutions":["Restrict defaults.triggers to mentions, keywords, and all_messages (see KNOWN_RESPOND_TO_KEYS at crates/buzz-persona/src/validate.rs:133)","Fix misspellings so the intended trigger actually arms","Move behavior that needs custom conditions into hooks_config or workflow logic instead of unsupported trigger keys"],"exampleFix":"// before (plugin.json)\n\"triggers\": { \"keywords\": [\"help\"], \"channels\": [\"random\"] }\n\n// after\n\"triggers\": { \"keywords\": [\"help\"] }","handlingStrategy":"validation","validationCode":"const KNOWN_TRIGGER_KEYS = new Set([\"mentions\", \"keywords\", \"all_messages\"]);\nconst triggers = manifest.defaults?.triggers ?? manifest.defaults?.respond_to ?? {};\nfor (const key of Object.keys(triggers)) {\n  if (!KNOWN_TRIGGER_KEYS.has(key)) throw new Error(`defaults.triggers: unknown key: ${key}`);\n}","typeGuard":"const isKnownTriggerKey = (k: string): k is TriggerKey => KNOWN_TRIGGER_KEYS.has(k as TriggerKey);","tryCatchPattern":null,"preventionTips":["Limit triggers to mentions/keywords/all_messages; put custom activation logic in hooks_config or workflows","After changing trigger config, verify with a live mention/keyword that the trigger actually fires","Remember respond_to is the legacy alias — do not carry both spellings with divergent keys"],"tags":["rust","plugin-json","triggers","lint","persona","validation"],"backgroundTag":"unknown-manifest-key","analyzedSha":"934f3325c3fdaa3a6f23134b74518139aac8ca3f","analyzedAt":"2026-08-20T04:38:24.874Z","contentChangedAt":"2026-08-20T04:38:24.874Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}