Guards

Deterministic guard evaluation engine with weighted voting and multi-agent consensus decisions.

Overview

@consensus-tools/guards is the deterministic guard evaluation engine for consensus-tools. It evaluates agent actions against 7 built-in guard types, tallies weighted votes across multiple evaluators, and computes ALLOW / BLOCK / REWRITE / REQUIRE_HUMAN decisions.

Installation

pnpm add @consensus-tools/guards

Peer dependency

This package requires @consensus-tools/schemas as a peer dependency.

Quick start

Run the built-in evaluators against an action and finalize a decision:

import { evaluatorVotes, finalizeVotes } from "@consensus-tools/guards";
import type { GuardEvaluateInput } from "@consensus-tools/schemas";

const input: GuardEvaluateInput = {
  action: { type: "code_merge", payload: { files: ["src/auth/login.ts"] } },
  context: {},
};

const votes = evaluatorVotes(input);
const result = finalizeVotes(votes, "code_merge");
// => { decision: "REQUIRE_HUMAN", reason: "Sensitive file touched", risk_score: 0.82, next_step: { ... } }

API reference

evaluatorVotes(input)

Built-in deterministic evaluator for all 7 guard types.

function evaluatorVotes(input: GuardEvaluateInput): GuardVote[]
  • input GuardEvaluateInput -- the action and context to evaluate
  • Returns GuardVote[] -- array of votes from built-in evaluators

finalizeVotes(votes, actionType, policy?)

Single-evaluator decision path. Takes votes and produces a final guard result.

function finalizeVotes(votes: GuardVote[], actionType: string, policy?: GuardPolicy): GuardResult
  • votes GuardVote[] -- votes from evaluators
  • actionType string -- the guard type (e.g. "code_merge")
  • policy GuardPolicy (optional) -- quorum and risk threshold overrides
  • Returns GuardResult -- { decision, reason, risk_score, next_step }

computeDecision(votes, policy, mode?)

Multi-agent consensus path with weighted voting.

function computeDecision(
  votes: WeightedGuardVote[],
  policy: GuardPolicy,
  mode?: "static" | "reputation" | "hybrid"
): { decision: string; tally: VoteTally; quorumMet: boolean; combinedRisk: number }
  • votes WeightedGuardVote[] -- votes with weight and reputation fields
  • policy GuardPolicy -- { quorum, riskThreshold }
  • mode -- weighting mode: "static" (raw weight), "reputation" (reputation/100), "hybrid" (weight * reputation/100). Defaults to "static".
  • Returns decision result with tally, quorum status, and combined risk
import { computeDecision } from "@consensus-tools/guards";
import type { WeightedGuardVote, GuardPolicy } from "@consensus-tools/schemas";

const votes: WeightedGuardVote[] = [
  { vote: "YES", risk: 0.3, confidence: 0.9, weight: 1, reputation: 95, evaluator: "a", reason: "ok" },
  { vote: "YES", risk: 0.2, confidence: 0.8, weight: 1, reputation: 80, evaluator: "b", reason: "ok" },
  { vote: "NO",  risk: 0.9, confidence: 0.95, weight: 1, reputation: 90, evaluator: "c", reason: "risky" },
];

const policy: GuardPolicy = { quorum: 0.6, riskThreshold: 0.7 };
const { decision, tally, quorumMet, combinedRisk } = computeDecision(votes, policy, "hybrid");

computeEffectiveWeight(weight, reputation, mode?)

Compute a single voter's effective weight based on the weighting mode.

function computeEffectiveWeight(weight: number, reputation: number, mode?: string): number
const ew = computeEffectiveWeight(1.0, 85, "hybrid"); // => 0.85

tallyVotes(votes, mode?)

Tally an array of weighted votes into aggregate counts.

function tallyVotes(votes: WeightedGuardVote[], mode?: string): VoteTally
  • Returns { yes, no, rewrite, totalWeight, weightedYes, weightedNo, weightedRewrite, voterCount }

reachesQuorum(tally, quorum)

Check if a tally meets the required quorum threshold.

function reachesQuorum(tally: VoteTally, quorum: number): boolean

createGuardEvaluatorRegistry()

Factory that returns a GuardEvaluatorRegistry pre-loaded with all 7 built-in guard types.

function createGuardEvaluatorRegistry(): GuardEvaluatorRegistry

Examples

Custom evaluator registry

Register custom evaluators or override built-in ones:

import { createGuardEvaluatorRegistry } from "@consensus-tools/guards";
import type { GuardEvaluateInput, GuardVote } from "@consensus-tools/schemas";

const registry = createGuardEvaluatorRegistry();
// 7 built-in types: send_email, code_merge, publish,
// support_reply, agent_action, deployment, permission_escalation

registry.register("custom_action", (input: GuardEvaluateInput): GuardVote[] => {
  return [{ evaluator: "custom", vote: "YES", reason: "Custom check passed", risk: 0.1 }];
});

const votes = registry.evaluate({ action: { type: "custom_action", payload: {} }, context: {} });
const types = registry.listTypes(); // all registered guard types

Vote tallying

import { computeEffectiveWeight, tallyVotes, reachesQuorum } from "@consensus-tools/guards";

const tally = tallyVotes(votes, "hybrid");
const met = reachesQuorum(tally, 0.6);