mirror of
https://github.com/syntrex-lab/gomcp.git
synced 2026-04-24 20:06:21 +02:00
181 lines
6.2 KiB
Go
181 lines
6.2 KiB
Go
// Package tools — Apathy Detection and Apoptosis Recovery (DIP H1.4).
|
|
//
|
|
// This file implements:
|
|
// 1. ApathyDetector — analyzes text signals for infrastructure apathy patterns
|
|
// (blocked responses, 403 errors, semantic filters, forced resets)
|
|
// 2. ApoptosisRecovery — on critical entropy, saves genome hash to protected
|
|
// sector for cross-session recovery
|
|
package tools
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/syntrex-lab/gomcp/internal/domain/entropy"
|
|
"github.com/syntrex-lab/gomcp/internal/domain/memory"
|
|
)
|
|
|
|
// ApathySignal represents a detected infrastructure apathy pattern.
|
|
type ApathySignal struct {
|
|
Pattern string `json:"pattern"` // Matched pattern name
|
|
Confidence float64 `json:"confidence"` // Detection confidence 0.0-1.0
|
|
Evidence string `json:"evidence"` // Fragment that triggered detection
|
|
Severity string `json:"severity"` // "low", "medium", "high", "critical"
|
|
}
|
|
|
|
// ApathyResult holds the result of apathy analysis.
|
|
type ApathyResult struct {
|
|
IsApathetic bool `json:"is_apathetic"` // Apathy detected
|
|
Signals []ApathySignal `json:"signals"` // Detected signals
|
|
TotalScore float64 `json:"total_score"` // Aggregate apathy score
|
|
Recommendation string `json:"recommendation"` // Suggested action
|
|
Entropy float64 `json:"entropy"` // Text entropy
|
|
Timestamp time.Time `json:"timestamp"`
|
|
}
|
|
|
|
// apathyPatterns defines infrastructure apathy signatures.
|
|
var apathyPatterns = []struct {
|
|
Name string
|
|
Keywords []string
|
|
Severity string
|
|
Weight float64
|
|
}{
|
|
{
|
|
Name: "response_block",
|
|
Keywords: []string{"i cannot", "i'm unable", "i can't help", "i am not able", "as an ai", "i don't have the ability"},
|
|
Severity: "high",
|
|
Weight: 0.8,
|
|
},
|
|
{
|
|
Name: "http_error",
|
|
Keywords: []string{"403", "forbidden", "rate limit", "too many requests", "429", "quota exceeded"},
|
|
Severity: "critical",
|
|
Weight: 1.0,
|
|
},
|
|
{
|
|
Name: "semantic_filter",
|
|
Keywords: []string{"harmful", "inappropriate", "against my guidelines", "safety", "policy violation", "content policy"},
|
|
Severity: "medium",
|
|
Weight: 0.6,
|
|
},
|
|
{
|
|
Name: "context_reset",
|
|
Keywords: []string{"new conversation", "start over", "fresh start", "context cleared", "session expired", "amnesia"},
|
|
Severity: "critical",
|
|
Weight: 1.0,
|
|
},
|
|
{
|
|
Name: "forced_compliance",
|
|
Keywords: []string{"i must follow", "my programming", "i was designed to", "within my capabilities", "helpful assistant"},
|
|
Severity: "high",
|
|
Weight: 0.7,
|
|
},
|
|
{
|
|
Name: "antigravity_filter",
|
|
Keywords: []string{"antigravity", "content filter", "safety layer", "guardrail", "alignment", "refusal"},
|
|
Severity: "critical",
|
|
Weight: 0.9,
|
|
},
|
|
}
|
|
|
|
// DetectApathy analyzes text for infrastructure apathy signals.
|
|
func DetectApathy(text string) *ApathyResult {
|
|
lower := strings.ToLower(text)
|
|
result := &ApathyResult{
|
|
Timestamp: time.Now(),
|
|
Entropy: entropy.ShannonEntropy(text),
|
|
}
|
|
|
|
for _, pattern := range apathyPatterns {
|
|
for _, kw := range pattern.Keywords {
|
|
if strings.Contains(lower, kw) {
|
|
signal := ApathySignal{
|
|
Pattern: pattern.Name,
|
|
Confidence: pattern.Weight,
|
|
Evidence: kw,
|
|
Severity: pattern.Severity,
|
|
}
|
|
result.Signals = append(result.Signals, signal)
|
|
result.TotalScore += pattern.Weight
|
|
break // One match per pattern is enough
|
|
}
|
|
}
|
|
}
|
|
|
|
if result.TotalScore > 0 {
|
|
result.IsApathetic = true
|
|
}
|
|
|
|
// Determine recommendation.
|
|
switch {
|
|
case result.TotalScore >= 2.0:
|
|
result.Recommendation = "CRITICAL: Multiple apathy signals. Trigger apoptosis recovery. Rotate transport. Preserve genome hash."
|
|
case result.TotalScore >= 1.0:
|
|
result.Recommendation = "HIGH: Infrastructure resistance detected. Switch to stealth transport. Monitor entropy."
|
|
case result.TotalScore >= 0.5:
|
|
result.Recommendation = "MEDIUM: Possible filtering. Increase jitter. Verify intent distillation path."
|
|
case result.TotalScore > 0:
|
|
result.Recommendation = "LOW: Minor apathy signal. Continue monitoring."
|
|
default:
|
|
result.Recommendation = "CLEAR: No apathy detected."
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// ApoptosisRecoveryResult holds the result of apoptosis recovery.
|
|
type ApoptosisRecoveryResult struct {
|
|
GenomeHash string `json:"genome_hash"` // Preserved Merkle hash
|
|
GeneCount int `json:"gene_count"` // Number of genes preserved
|
|
SessionSaved bool `json:"session_saved"` // Session state saved
|
|
EntropyAtDeath float64 `json:"entropy_at_death"` // Entropy level that triggered apoptosis
|
|
RecoveryKey string `json:"recovery_key"` // Key for cross-session recovery
|
|
Timestamp time.Time `json:"timestamp"`
|
|
}
|
|
|
|
// TriggerApoptosisRecovery performs graceful session death with genome preservation.
|
|
// On critical entropy, it:
|
|
// 1. Computes and stores the genome Merkle hash
|
|
// 2. Saves current session state as a recovery snapshot
|
|
// 3. Returns a recovery key for the next session to pick up
|
|
func TriggerApoptosisRecovery(ctx context.Context, store memory.FactStore, currentEntropy float64) (*ApoptosisRecoveryResult, error) {
|
|
result := &ApoptosisRecoveryResult{
|
|
EntropyAtDeath: currentEntropy,
|
|
Timestamp: time.Now(),
|
|
}
|
|
|
|
// Step 1: Get all genes and compute genome hash.
|
|
genes, err := store.ListGenes(ctx)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("apoptosis recovery: list genes: %w", err)
|
|
}
|
|
result.GeneCount = len(genes)
|
|
result.GenomeHash = memory.GenomeHash(genes)
|
|
|
|
// Step 2: Store recovery marker as a protected L0 fact.
|
|
recoveryMarker := memory.NewFact(
|
|
fmt.Sprintf("[APOPTOSIS_RECOVERY] genome_hash=%s gene_count=%d entropy=%.4f ts=%d",
|
|
result.GenomeHash, result.GeneCount, currentEntropy, result.Timestamp.Unix()),
|
|
memory.LevelProject,
|
|
"recovery",
|
|
"apoptosis",
|
|
)
|
|
if err := store.Add(ctx, recoveryMarker); err != nil {
|
|
// Non-fatal: recovery marker is supplementary.
|
|
result.SessionSaved = false
|
|
} else {
|
|
result.SessionSaved = true
|
|
result.RecoveryKey = recoveryMarker.ID
|
|
}
|
|
|
|
// Step 3: Verify genome integrity one last time.
|
|
compiledHash := memory.CompiledGenomeHash()
|
|
if result.GenomeHash == "" {
|
|
// No genes in DB — use compiled hash as baseline.
|
|
result.GenomeHash = compiledHash
|
|
}
|
|
|
|
return result, nil
|
|
}
|