An evidence whose config contains a chain step referencing ITSELF is now
unrolled at compile time into a bounded transitive closure: a union of paths
— base, hop+base, hop²+base, …, hop^N+base — where `hop` is the recursive
chain's steps before the self-reference and the depth N comes from the
pattern's `limit N` (or the compiler's maxRecursionDepth default, 3). The
base (the evidence's non-recursive statements) is verified as a condition
step at each path's terminal node, so the engine needs no new machinery.
- Chain configs carry the pattern's `limit` as maxDepth.
- resolveEvidenceReferences detects a self-reference (_findSelfReference),
extracts the base (_extractBase), and unrolls (_unrollRecursiveEvidence).
- Pure recursion with no base case is a compile-time error; mutual cycles
between distinct evidence remain a compile-time error.
Example: can_access_via = can_access OR (reports_to + can_access_via) up to
the declared limit grants access inherited up a reporting chain.
Tests: Recursion (unroll shape, base + multi-hop grants, depth-limit
enforcement, default depth, pure-recursion error, mutual-cycle guard).
The Evidence DSL (ADR-000) is a thin declarative layer that compiles to
engine rule types. It has zero runtime coupling to the core engine
(DSLCompiler takes an arbiter as a duck-typed argument; the only shared
code was the ip-utils helpers, now local). Extracting it into its own
package keeps the core artifact free of the DSL surface.
- @arbiter/evidence-dsl depends on @arbiter/core (config formats are the
compilation target)
- deep-path exports for the compiler, parser, generator, validation,
and built-in functions (the surface the core's DSL tests consume)
- tests moved alongside; generate-parser script + peggy devDep local
- CI: test on push, publish on v* tags