Packages
Loading
Loading
Packages
@loop-engine/signals ships SignalRegistry for declaring and validating signal specs. The pattern-detection engine (SignalEngine) is on the roadmap for 1.1.0+.
1npm install @loop-engine/signalsThe current public surface is a registry that declares each signal's identity, optional Zod schema, and human-readable metadata. Runtime code uses it to look up and validate signal payloads.
1class SignalRegistry {2 register(spec: SignalSpec): void3 get(signalId: SignalId): SignalSpec | undefined4 validatePayload(signalId: SignalId, payload: unknown): { valid: boolean; error?: string }5 list(): SignalSpec[]6}7 8interface SignalSpec {9 signalId: SignalId10 name: string11 description?: string12 schema?: ZodType13 tags?: string[]14}1import { z } from "zod"2import { SignalRegistry } from "@loop-engine/signals"3import { signalId } from "@loop-engine/core"4 5const registry = new SignalRegistry()6registry.register({7 signalId: signalId("expense.submitted"),8 name: "Expense submitted",9 description: "A user has submitted an expense report for review.",10 schema: z.object({11 amount: z.number().positive(),12 currency: z.string().length(3)13 })14})15 16const check = registry.validatePayload(signalId("expense.submitted"), {17 amount: 1200,18 currency: "USD"19})20"cmt">// => { valid: true }1interface SignalEngine {2 registerRule(rule: SignalRule): void3 process(events: LoopEvent[]): Signal[]4 subscribe(handler: (signal: Signal) => void): () => void5}6 7createSignalEngine(): SignalEnginePlanned built-in rule factories:
thresholdBreachRule(config: ThresholdRuleConfig): SignalRulestateDwellRule(config: StateDwellRuleConfig): SignalRulerepeatedGuardFailureRule(config: RepeatedGuardFailureConfig): SignalRuleloopNotStartedRule(config: LoopNotStartedConfig): SignalRuleSignals are detections, not actors. Application code decides what to do with them — including whether to start or transition loops in response.