feedback_*.md) become runtime tool-invocation defenses — no PR per lesson. The crux is a safe predicate DSL: rules come from memory files, so there is no eval anywhere.Static TS registry (#1883) wins on id collision; memory rules are advisory-only.
```ork-lint
[
{ "id": "no-no-verify", "tool_name": "Bash",
"predicate": { "field": "command", "op": "contains", "value": "--no-verify" },
"severity": "warn", "message": "do not bypass hooks", "see": "CLAUDE.md" }
]
```
Fenced JSON (not YAML) — hooks are zero-dep, so JSON.parse beats a hand-rolled YAML parser.
| op | matches when field… |
|---|---|
eq / neq | equals / (present and ≠) value |
in | equals one of value[] |
prefix / contains | starts-with / contains value |
exists / absent | is present / missing |
compilePredicate is a pure switch; value:"process.exit(1)" is a literal string compared with ===, never executed.warn/info only; severity:"block" is rejected at load. A memory file can never halt a tool call.__proto__/constructor never resolve).27 unit/integration cases: DSL eval · prototype guard · no-eval injection · block-severity rejection · malformed-JSON degrade · dir resolution · full linter integration ([memory:<file>] advisory fires) opt-out: ORK_NO_MEMORY_LINT=1 · promotion path → static registry (#1883)