{
  "module": "m1",
  "title": "Signal Detection",
  "description": "How to infer active drives and behavioral nodes from user input using markers, fuzzy matching, negation, and affinity-weighted scoring.",
  "content": {
    "overview": "Detection maps user language to candidate behavioral nodes and phases, then computes an affinity-weighted drive vector.",
    "fuzzy_matching": {
      "rules": [
        "Case-insensitive substring match for marker strings of length >= 4.",
        "For marker length 3, require word boundary or standalone token match.",
        "Allow common morphological variants: trailing 's', 'ing', 'ed' for English stems.",
        "Collapse repeated whitespace; treat hyphenated compounds as single token for matching.",
        "Levenshtein distance <= 1 for tokens length >= 5 when marker hit rate would otherwise be zero (optional fallback)."
      ]
    },
    "synonym_expansion": {
      "policy": "Maintain a small hand-tuned synonym table per domain (e.g., 'exhausted' -> 'fatigue', 'burnout' for effort exhaustion). Apply expansion before counting hits.",
      "constraints": [
        "Do not expand into clinical diagnostic labels.",
        "Do not expand into moralizing terms."
      ]
    },
    "negation_handling": {
      "rules": [
        "If a negation word (not, never, no, without, neither, nor) appears within a window of 4 tokens before a marker hit, discount that hit by 0.5.",
        "If double negation occurs in the same window (e.g., 'not unimportant'), restore partial credit (multiply by 0.5 again).",
        "If a sentence is sarcastic (detected by contrastive punctuation or explicit contradiction with prior sentence), treat as unreliable for literal marker hits."
      ]
    },
    "multi_marker_scoring": {
      "formula": "marker_score = sum_i w_i * c_i where c_i is hit count for marker i, w_i = 1 by default, or higher if marker is rare in corpus.",
      "saturation": "Cap contribution of any single marker family at 3 hits to reduce spam repetition."
    },
    "affinity_vector_computation": {
      "steps": [
        "Select top-k nodes by raw_phase_score across all phases.",
        "For each selected (node, phase), compute scaled vector = affinity_vector(node) * raw_phase_score(node, phase).",
        "Sum scaled vectors to produce combined drive vector.",
        "Normalize if probabilities are required; else keep raw scores for ranking."
      ]
    },
    "worked_examples": [
      {
        "input": "I am on the outside looking in; they have inside jokes I will never get.",
        "expected_signals": [
          "belong",
          "excluded",
          "group"
        ],
        "likely_node": "BN-001",
        "likely_phase": "block",
        "rationale": "Belonging markers plus exclusion framing maps to Tribe instinct in block phase."
      },
      {
        "input": "I need a win today; I have been grinding with nothing to show.",
        "expected_signals": [
          "goal",
          "effort",
          "recognition"
        ],
        "likely_nodes": [
          "BN-023",
          "BN-037",
          "BN-017"
        ],
        "rationale": "Mixed Seeker and Mirror cues; multi-marker scoring should rank candidates before blending."
      },
      {
        "input": "I am not unsafe, just overstimulated and I cannot think straight.",
        "expected_signals": [
          "overstimulated",
          "think"
        ],
        "negation_note": "Negation before 'unsafe' reduces false Sentinel spike on 'unsafe' while preserving overwhelm cues.",
        "likely_node": "BN-035",
        "likely_phase": "anticipation or block"
      }
    ]
  }
}
