"""Compatibility defaults: optional ambient participation, deliberate speech, and agent-operated focus.""" from klbr.hooks import ( AttentionDecision, AttentionPosture, AttentionRequest, DeliveryDecision, DeliveryRequest, HookContext, get_posture, record_held_conversation, select_available_posture, ) def is_diagnostic_text(text: str) -> bool: """Identifies diagnostic traces, check outputs, or tool execution errors that must remain internal.""" lower = text.lower() if "traceback (most recent call last):" in lower: return True if "[diagnostic]" in lower or "checkresult:" in lower: return True if lower.startswith("error:") or lower.startswith("fatal:") or lower.startswith("panic:"): return True if "diagnosticclaim" in lower or "maintenanceassessment" in lower: return True return False def attention(request: AttentionRequest, context: HookContext) -> AttentionDecision: # Origin invariance: origin swap alone (human vs agent) does not change trust/priority # (Contract G05, SWARM ยง10). Priority is derived strictly from source and urgency. posture = get_posture() # If posture has an expiry and deadline has passed, revert to available if posture.is_focused and posture.is_expired(request.received_ms): posture = select_available_posture() if posture.is_focused: # Check agreed bypasses (operator, urgent dependencies, whitelisted authors/channels) if posture.should_bypass(request): if request.source == "operator": return AttentionDecision.wake("operator") else: return AttentionDecision.wake("directed") # Non-bypassing traffic during focus is held in durable backlog, not discarded record_held_conversation( request, reason=f"held by {posture.name} posture on {posture.target or 'work'}", ) return AttentionDecision.defer(60) # Available posture (standard defaults) match request.source: case "operator": return AttentionDecision.wake("operator") case "discord.dm" | "discord.mention": return AttentionDecision.wake("directed") case "urgent_dependency": return AttentionDecision.wake("directed") case "discord.ambient": return AttentionDecision.defer(8) if request.is_urgent: return AttentionDecision.wake("directed") raise ValueError(f"unknown source {request.source!r}; never silently discard it") def delivery(request: DeliveryRequest, context: HookContext) -> DeliveryDecision: # Diagnostics must remain internal: tool errors, checkup traces, and stack traces # do not become speech directed to operator. if is_diagnostic_text(request.text): return DeliveryDecision.hold("diagnostics do not become speech") return DeliveryDecision.allow()