feat(keyword-detector): add per-keyword disable config
Adds keyword_detector.disabled_keywords config so users can opt out of
specific keyword detectors individually without disabling the entire
keyword-detector hook. Allowed values: 'ultrawork', 'search', 'analyze',
'team'. Default empty/missing -> all four detectors active (no behavior
change for existing configs).
Motivation: an audit revealed search and analyze patterns trigger on
~30-60% of normal conversational user messages (e.g. 'how to', 'why is',
'show me', '왜', '어떻게'). The disable list is the immediate kill switch
while the patterns themselves are tightened in a separate PR.
Schema follows the existing per-feature config block convention shared
by team_mode, ralph_loop, runtime_fallback, and comment_checker. The
KeywordType enum (z.enum) lives next to the config schema and is
re-imported by the detector to keep the union type in lockstep with the
schema.
Threading:
pluginConfig.keyword_detector
-> create-transform-hooks.ts (factory wiring)
-> createKeywordDetectorHook(config)
-> detectKeywordsWithType(text, agent, model, disabledKeywords)
-> Set-based filter at the source-of-truth detector
Adds 8 regression tests covering per-keyword disable, multi-keyword
disable, partial disable (one keyword off, another still firing),
ultrawork toast suppression, undefined config, and empty array.
This commit is contained in:
@@ -47,11 +47,24 @@ chat.message (user input)
|
||||
→ extractPromptText(parts)
|
||||
→ isSystemDirective? → skip
|
||||
→ removeSystemReminders(text) # strip <SYSTEM_REMINDER> blocks
|
||||
→ detectKeywordsWithType(cleanText, agentName, modelID)
|
||||
→ detectKeywordsWithType(cleanText, agentName, modelID, disabledKeywords)
|
||||
→ isPlannerAgent(agentName)? → filter out ultrawork
|
||||
→ for each detected keyword: inject mode message into output
|
||||
```
|
||||
|
||||
## CONFIG
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"keyword_detector": {
|
||||
// Skip injection for any keyword in this list. Allowed: "ultrawork", "search", "analyze", "team".
|
||||
"disabled_keywords": ["search", "analyze"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Default: empty/missing → all four detectors active. Schema lives at [src/config/schema/keyword-detector.ts](../../config/schema/keyword-detector.ts).
|
||||
|
||||
## GUARDS
|
||||
|
||||
- **System directive skip**: Messages tagged as system directives are not scanned (prevents infinite loops)
|
||||
|
||||
Reference in New Issue
Block a user