Core Concepts
Guards and Policy
What guards are
Guards are deterministic policy checks evaluated before state advancement.
In this runtime, a guard is a GuardFunction returning { passed, code?, message?, metadata? }.
Hard vs soft
| | Hard | Soft |
|---|---|---|
| Blocks transition | Yes | No |
| State advances | No | Yes |
| Emitted event on failure | loop.guard.failed | Failure warning is attached to _softGuardWarnings evidence |
| Typical use | Mandatory policy | Warning and monitoring |
evaluatedBy
GuardSpec.evaluatedBy:
runtime- evaluated by registeredGuardFunctionmodule- declared for module-level policy contractexternal- caller provides result context in evidence contract
Built-in guards
actor_has_permission
- Reads:
required_role,roles - Fails when
required_roleis missing fromroles
approval_obtained
- Reads:
approved - Fails when
approved !== true
deadline_not_exceeded
- Reads:
deadline_iso - Fails when deadline format is invalid or current time exceeds deadline
duplicate_check_passed
- Reads:
duplicate_found - Fails when
duplicate_found === true
field_value_constraint
- Reads:
constraintplus referenced field - Supported operators:
eq,gt,lt,in
Add a custom guard
1import { guardId } from '@loop-engine/core'2import { createGuardRegistry } from '@loop-engine/guards'3 4const registry = createGuardRegistry()5registry.register(guardId('my_custom_guard'), async (context) => {6 const passed = context.evidence.budget_available === true7 return {8 passed,9 message: passed ? 'Budget available' : 'Insufficient budget'10 }11})Use this registry in createLoopSystem({ loops, guards: registry }).