klieo-ops 0.2.0

Operational layer above klieo-core: supervisor, governor, gates, escalation, worklog, handoff.
Documentation
//! `Gate` trait + decision enum.

use async_trait::async_trait;

/// Inputs to a gate evaluation.
#[derive(Clone, Debug)]
#[non_exhaustive]
pub struct GateRequest {
    /// Tool being invoked.
    pub tool_name: String,
    /// Tool arguments (JSON).
    pub args: serde_json::Value,
}

impl GateRequest {
    /// Construct a `GateRequest`. Use this instead of struct literal
    /// syntax — `#[non_exhaustive]` blocks cross-crate struct literals.
    pub fn new(tool_name: impl Into<String>, args: serde_json::Value) -> Self {
        Self {
            tool_name: tool_name.into(),
            args,
        }
    }
}

/// Stable policy code for audit trails (Phase A: free-form string).
pub type PolicyCode = String;

/// Outcome of a gate evaluation.
#[derive(Clone, Debug)]
#[non_exhaustive]
pub enum GateDecision {
    /// Permit the call.
    Allow,
    /// Refuse the call.
    Deny {
        /// Stable code identifying the rule.
        code: PolicyCode,
        /// Reason text.
        reason: String,
    },
    /// Require human approval. Phase A: surfaces as `ToolError::Permanent`
    /// because escalation primitive is Phase B.
    RequireApproval {
        /// Ticket identifier reserved for Phase B escalation wiring.
        ticket: String,
        /// Quorum count.
        quorum: u8,
    },
}

/// Pre-effect policy gate.
#[async_trait]
pub trait Gate: Send + Sync {
    /// Evaluate against the supplied request.
    async fn evaluate(&self, req: GateRequest) -> GateDecision;

    /// Stable gate name (used for audit).
    fn name(&self) -> &'static str;
}