Loop Engine

Packages

@loop-engine/guards

@loop-engine/guards provides deterministic policy checks that run inside transition execution.

Install

1npm install @loop-engine/guards

Guard model

Guards in this package are synchronous policy assertions wrapped as async functions. They do not call LLMs or network services.

GuardResult:

1interface GuardResult {
2 passed: boolean
3 code?: string
4 message?: string
5 metadata?: Record<string, unknown>
6}

Registry API

1class GuardRegistry {
2 register(guardId: GuardId, fn: GuardFunction): void
3 get(guardId: GuardId): GuardFunction | undefined
4 createEvaluator(): GuardEvaluator
5}
1import { createGuardRegistry } from "@loop-engine/guards"
2import { guardId } from "@loop-engine/core"
3 
4const registry = createGuardRegistry()
5registry.register(guardId("budget_available"), async (context) => ({
6 passed: context.evidence.budget_ok === true,
7 message: "Budget check failed"
8}))

Built-in guards

defaultRegistry pre-registers:

  • actor_has_permission (actorPermissionGuard)
  • approval_obtained (approvalObtainedGuard)
  • deadline_not_exceeded (deadlineNotExceededGuard)
  • duplicate_check_passed (duplicateCheckPassedGuard)
  • field_value_constraint (fieldValueConstraintGuard)

Built-in evidence keys:

  • approval_obtained reads evidence.approved === true
  • actor_has_permission reads required_role and roles
  • deadline_not_exceeded reads deadline_iso
  • duplicate_check_passed reads duplicate_found
  • field_value_constraint reads constraint with operators eq | gt | lt | in

Hard and soft behavior

Hard/soft severity is defined on each GuardSpec in @loop-engine/core. Runtime blocks on hard failures and records soft failures under _softGuardWarnings in transition evidence.