Phronesis is a RETE rules engine. RETE —
developed by Charles Forgy at Carnegie Mellon in the late
1970s and published in its canonical 1982 paper Rete: A
Fast Algorithm for the Many Pattern / Many Object Pattern
Match Problem — has lived inside production-rule
systems ever since: expert systems, business-rules
platforms, event-correlation engines, the JBoss Drools
framework one of the authors used in earlier
participatory-modeling work, and any number of others.
The algorithm is straightforward. Facts enter a network.
Conditions match against them in a compiled discrimination
graph. Consequences fire when every condition of a rule is
satisfied. Think of a card-game referee: each card laid on
the table is a fact; the rules of the game are the
conditions; the referee speaks up only when something is
out of bounds — a card from the wrong suit, a play out of
turn. That is the engine's whole job.
Our use of the algorithm is not especially novel. The new
thing is the purpose. We use RETE to lint LLM tool
calls.
Phr-MCP is the wrapper around the engine:
a single Rust binary that exposes it three ways. It runs as
an MCP server over stdio, for any MCP-capable client. It
runs as a set of CLI subcommands that bind directly to the
Claude Code and Gemini CLI hook protocols. And it runs as a
whole-tree audit tool. The hooks are where the durability
property comes from. They are invoked by the host (Claude
Code, Gemini CLI) at well-defined moments — before a tool
fires, after it applies, when a session opens, when the
user submits a prompt — and they re-read the rules file
from disk on every invocation.
That last property is the structural point. The hook does
not cache anything between invocations. It does not depend
on the model's memory or on any state retained in the
conversation. It opens a file, parses it, runs the network
against the facts extracted from the current tool call,
prints a result, and exits. Whatever the model has
forgotten, the hook still has access to — because the hook
never knew anything to begin with, and reads the rules
fresh from disk every time it is asked to fire.