Framework Triggering Mechanics =============================== This document explains in detail how the BioMapper Framework Triad automatically detects and activates the appropriate framework based on natural language input. The detection system is implemented in the ``UnifiedBiomapperAgent`` and ``FrameworkRouter`` classes. .. important:: The framework names ("surgical", "circuitous", "interstitial") ARE valid triggers and will directly activate their respective frameworks. Additionally, the system detects problem descriptions, so you can describe issues naturally without knowing framework names. Detection Pipeline ------------------ The ``FrameworkRouter`` selection process follows this pipeline: 1. **Pattern Compilation** - Pre-compiled regex patterns cached for performance (~5ms initialization) 2. **Pattern Matching** - Check message against framework-specific patterns using ``_score_all_frameworks`` 3. **Confidence Scoring** - Calculate match confidence with pattern weight + base score (0.3) 4. **Keyword Boosting** - Apply secondary keyword bonuses (+0.1 per keyword) 5. **Ambiguity Resolution** - Handle multiple matches using priority order 6. **Threshold Check** - Ensure minimum confidence (40% - ``ACTIVATION_THRESHOLD``) 7. **Framework Activation** - Route to selected framework with target extraction Pattern Matching (Primary Detection) ------------------------------------- Each framework has specific regex patterns compiled from constants defined in their respective implementation classes: Surgical Framework Patterns ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Detects issues with internal logic, calculations, and statistics: .. code-block:: python # From ActionSurgeon.SURGICAL_PATTERNS (loaded by FrameworkRouter) SURGICAL_PATTERNS = [ r"surgical", # Direct framework name trigger r"fix.*(counting|calculation|logic|statistics).*in.*(action|visualization)", r"(update|refine|correct|adjust).*without.*(breaking|affecting|changing).*pipeline", r"(internal|surgical|careful).*change", r"preserve.*structure.*while.*(fixing|updating|correcting)", r"entity.*counting.*(wrong|incorrect|inflated)", r"statistics.*(show|display|count).*(wrong|incorrect|inflated|expanded)", r"output.*correct.*but.*numbers.*wrong", r"counting.*expanded.*records.*instead.*unique", r"should.*show.*unique.*(entities|proteins|metabolites)", r"\d+.*but.*should.*(be|show).*\d+" # "3675 but should be 1200" ] **Example matches:** - ✅ "Use surgical mode to fix this" - ✅ "This needs surgical precision" - ✅ "The statistics show wrong counts" - ✅ "Fix the calculation logic in the action" - ✅ "3675 proteins but should be 1172" Circuitous Framework Patterns ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Detects pipeline orchestration and parameter flow issues: .. code-block:: python # From CircuitousFramework.CIRCUITOUS_PATTERNS (loaded by FrameworkRouter) CIRCUITOUS_PATTERNS = [ r"circuitous", # Direct framework name trigger r"parameters?.*not.*(flow|pass|work).*between", r"(strategy|pipeline).*orchestration.*(broken|failing|issue)", r"(step|action).*sequence.*(wrong|incorrect|broken)", r"parameter.*substitution.*(failing|broken|not.*work)", r"context.*(not.*pass|broken|missing).*between", r"\$\{.*\}.*not.*(resolv|work|substitut)", r"data.*not.*(flow|pass).*from.*to", r"output.*not.*(reach|available).*next.*step", r"(handoff|transfer).*between.*steps.*(fail|broken)", r"yaml.*strategy.*(broken|issue|problem)" ] **Example matches:** - ✅ "Use circuitous mode to trace the flow" - ✅ "This needs circuitous analysis" - ✅ "Parameters not flowing between steps" - ✅ "${parameters.input_file} not substituting" - ✅ "Pipeline orchestration is broken" Interstitial Framework Patterns ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Detects interface compatibility and API evolution issues: .. code-block:: python # From InterstitialFramework.INTERSTITIAL_PATTERNS (loaded by FrameworkRouter) INTERSTITIAL_PATTERNS = [ r"interstitial", # Direct framework name trigger r"(handoff|interface).*between.*actions.*(failing|broken)", r"(contract|compatibility).*(issue|problem|broken)", r"action.*boundary.*(change|modify|update)", r"backward.*compatibility.*(maintain|preserve|break)", r"parameter.*interface.*(evolve|change|update)", r"output.*structure.*(modify|change).*compatibility", r"version.*compatibility.*(issue|problem)", r"api.*(evolution|change|update).*break", r"(new|added).*parameter.*broke.*existing", r"interface.*contract.*(violat|broken)" ] **Example matches:** - ✅ "Use interstitial mode for compatibility" - ✅ "This needs interstitial protection" - ✅ "Backward compatibility broken" - ✅ "New parameter broke existing strategies" - ✅ "API evolution breaking changes" Confidence Scoring Algorithm ----------------------------- Each pattern match contributes to a confidence score: .. code-block:: python # Implemented in FrameworkRouter._score_framework def calculate_confidence(message, patterns): matched_patterns = [] total_score = 0.0 message_lower = message.lower() for pattern in patterns: match = pattern.search(message_lower) if match: matched_patterns.append(pattern.pattern) # Longer patterns are more specific pattern_weight = len(pattern.pattern) / 100.0 # Base score 0.3 + specificity bonus total_score += min(1.0, 0.3 + pattern_weight) # Normalize by pattern count if matched_patterns: confidence = min(1.0, total_score / max(1, len(patterns) * 0.3)) else: confidence = 0.0 return confidence **Confidence Thresholds:** - **0.4 (40%)** - Minimum for activation - **0.7 (70%)** - High confidence - **1.0 (100%)** - Maximum (multiple patterns + keywords) Keyword Boosting (Secondary) ----------------------------- After pattern matching, specific keywords add confidence bonuses: .. list-table:: Keyword Bonuses :header-rows: 1 :widths: 20 40 20 * - Framework - Keywords - Bonus per keyword * - Surgical - fix, internal, logic, counting, statistics - +0.1 * - Circuitous - flow, pipeline, parameter, yaml, strategy - +0.1 * - Interstitial - interface, compatibility, backward, contract, api - +0.1 **Example calculation:** .. code-block:: text Message: "Fix the internal counting logic" Pattern match: 0.6 (base confidence) Keywords found: "fix" (+0.1), "internal" (+0.1), "counting" (+0.1), "logic" (+0.1) Final confidence: 1.0 (capped at maximum) Framework Name Detection ------------------------ The framework names themselves are now direct triggers: - **Surgical**: ``r"surgical"`` (first pattern, high priority) - **Circuitous**: ``r"circuitous"`` (first pattern, high priority) - **Interstitial**: ``r"interstitial"`` (first pattern, high priority) Using the framework name directly: - Guarantees framework activation - Provides highest confidence score - Works anywhere in the message - Case-insensitive matching Additionally, "surgical" appears in: ``r"(internal|surgical|careful).*change"`` for more contextual matches. Ambiguity Resolution -------------------- When multiple frameworks have similar confidence (within 15%): **Priority Order:** 1. **Surgical** (most specific - action internals) 2. **Interstitial** (interface-specific) 3. **Circuitous** (pipeline-wide) **Example:** .. code-block:: text Message: "The action parameter handling is broken internally" Surgical confidence: 0.65 Circuitous confidence: 0.60 Difference: 0.05 (< 0.15 threshold) Result: Surgical wins (higher priority) Target Extraction ----------------- The system also extracts specific targets from messages: **Surgical Framework:** - Looks for action names in ACTION_REGISTRY - Example: "Fix GENERATE_MAPPING_VISUALIZATIONS" → Target: GENERATE_MAPPING_VISUALIZATIONS **Circuitous Framework:** - Looks for strategy patterns: ``\w+_\w+_to_\w+_v[\d.]+`` - Example: "prot_arv_to_kg2c_v3.0 broken" → Target: prot_arv_to_kg2c_v3.0 **Interstitial Framework:** - Looks for common action keywords - Example: "export compatibility" → Target: EXPORT_DATASET Real-World Scoring Examples --------------------------- Example 1: Clear Surgical Intent ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: text Message: "The visualization shows 3675 proteins but should show 1172 unique ones" Pattern matches: - "statistics.*(show|display|count).*(wrong|incorrect|inflated|expanded)" ✓ - "\d+.*but.*should.*(be|show).*\d+" ✓ - "should.*show.*unique.*(entities|proteins|metabolites)" ✓ Base confidence: 0.75 Keywords: "statistics" (+0.1) Final: 0.85 → Surgical Framework (high confidence) Example 2: Clear Circuitous Intent ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: text Message: "The ${parameters.input_file} isn't being substituted in the pipeline" Pattern matches: - "\$\{.*\}.*not.*(resolv|work|substitut)" ✓ - "parameter.*substitution.*(failing|broken|not.*work)" ✓ Base confidence: 0.65 Keywords: "parameter" (+0.1), "pipeline" (+0.1) Final: 0.85 → Circuitous Framework (high confidence) Example 3: Ambiguous Intent ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: text Message: "Something is wrong with the action" Pattern matches: None Base confidence: 0.0 Keywords: None Final: 0.0 → No framework activated Example 4: Multiple Matches ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: text Message: "Fix the internal parameter flow" Surgical patterns: "fix.*(counting|calculation|logic)" (partial) Circuitous patterns: "parameter.*flow" (partial) Surgical confidence: 0.5 Circuitous confidence: 0.45 Keywords: "fix" (+0.1 surgical), "internal" (+0.1 surgical), "parameter" (+0.1 circuitous), "flow" (+0.1 circuitous) Final: Surgical 0.7, Circuitous 0.65 Result: Surgical wins (higher confidence) Performance Characteristics --------------------------- - **Pattern compilation**: Pre-compiled on initialization (~5ms) - **Message processing**: <10ms for typical messages - **Memory usage**: ~5MB for pattern cache - **Scalability**: O(n*p) where n=message length, p=patterns (~30 total) Debugging Framework Selection ------------------------------ To understand why a framework was selected: 1. **Check matched patterns** in the IntentScore 2. **Review confidence calculation** 3. **Identify keyword bonuses applied** 4. **Verify threshold was met (≥0.4)** 5. **Check for ambiguity resolution** Tips for Better Detection ------------------------- **DO:** - Describe the problem clearly - Use specific terms like "counting", "flow", "compatibility" - Include action/strategy names - Provide examples of incorrect behavior **DON'T:** - Use framework names as primary request - Be vague ("something wrong") - Mix multiple problems in one message - Override automatic detection unnecessarily Manual Override --------------- If automatic detection fails, use slash commands: - ``/biomapper-surgical ACTION_NAME`` - ``/biomapper-circuitous STRATEGY_NAME`` - ``/biomapper-interstitial ACTION_TYPE`` See :doc:`slash_commands` for details. --- ## Verification Sources *Last verified: 2025-01-22* This documentation was verified against the following project resources: - ``/biomapper/src/core/safety/unified_agent.py`` (FrameworkRouter class with pattern compilation and scoring) - ``/biomapper/src/core/safety/action_surgeon.py`` (ActionSurgeon.SURGICAL_PATTERNS constants) - ``/biomapper/src/core/safety/circuitous_framework.py`` (CircuitousFramework.CIRCUITOUS_PATTERNS) - ``/biomapper/src/core/safety/interstitial_framework.py`` (InterstitialFramework.INTERSTITIAL_PATTERNS) - ``/biomapper/src/actions/registry.py`` (ACTION_REGISTRY for target extraction patterns) - ``/biomapper/CLAUDE.md`` (Pattern documentation and framework triggering examples)