relations: Phase 2 reachability + roots/leaves + cycles (engine.sx, kind-parameterized closure) + 24 tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 1m0s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 1m0s
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -18,7 +18,7 @@ links. Reuses `lib/datalog/` — does not reimplement the engine.
|
||||
|
||||
## Status (rolling)
|
||||
|
||||
`bash lib/relations/conformance.sh` → **22/22** (Phase 1 complete)
|
||||
`bash lib/relations/conformance.sh` → **46/46** (Phases 1–2 complete)
|
||||
|
||||
## Ground rules
|
||||
|
||||
@@ -72,11 +72,11 @@ lib/relations/federation.sx
|
||||
|
||||
## Phase 2 — Reachability + cycles
|
||||
|
||||
- [ ] recursive reachability rules: `ancestors`, `descendants`, `reachable?(A,B)`
|
||||
- [x] recursive reachability rules: `ancestors`, `descendants`, `reachable?(A,B)`
|
||||
(transitive closure over a kind, the acl inheritance shape)
|
||||
- [ ] `roots` / `leaves` (no parents / no children) for a kind
|
||||
- [ ] cycle detection: `cycle?(X)` ⇔ `reachable(X, X)`; `acyclic?(db, kind)`
|
||||
- [ ] `lib/relations/tests/reach.sx` — deep chains, diamonds, disconnected nodes,
|
||||
- [x] `roots` / `leaves` (no parents / no children) for a kind
|
||||
- [x] cycle detection: `cycle?(X)` ⇔ `reachable(X, X)`; `acyclic?(db, kind)`
|
||||
- [x] `lib/relations/tests/reach.sx` — deep chains, diamonds, disconnected nodes,
|
||||
self-loops, multi-kind isolation
|
||||
|
||||
## Phase 3 — Typed relations + path explanation
|
||||
@@ -100,6 +100,21 @@ lib/relations/federation.sx
|
||||
|
||||
## Progress log
|
||||
|
||||
- **Phase 2 — reachability + cycles** (46/46). New `engine.sx` is one Datalog
|
||||
ruleset. Reachability is kind-parameterised — `reach(K,X,Y)` carries the kind as
|
||||
its first arg so a transitive walk over `parent` never leaks through `reply`
|
||||
edges (the acl inheritance shape, but closures can't cross kinds). `rnode`
|
||||
collects touched nodes; `root`/`leaf` use stratified negation over
|
||||
`has_parent`/`has_child`. Cycles are data, not errors: `cycle?(node,kind)` ⇔
|
||||
`reach(K,node,node)` holds, `acyclic?(kind)` ⇔ no `reach(K,X,X)`. Engine fns:
|
||||
`relations-descendants/-ancestors/-reachable?/-roots/-leaves/-cycle?/-acyclic?`;
|
||||
api.sx grew matching `relations/...` current-db wrappers. `relations-rules` and
|
||||
`relations-pluck` moved from api.sx into engine.sx (engine now loads before api
|
||||
in conformance.conf). reach.sx covers diamonds, deep chains, disconnected
|
||||
components, self-loops, c1<->c2 cycles, and multi-kind isolation. acl
|
||||
convergence: the `reach(X,Y):-edge(X,Y)` / `reach(X,Y):-edge(X,Z),reach(Z,Y)`
|
||||
closure shape is shared with acl's eff_grant/eff_deny inheritance — flagged, not
|
||||
extracted (per ground rules).
|
||||
- **Phase 1 — schema + direct relations** (22/22). `schema.sx`: `rel(Src,Dst,Kind)`
|
||||
fact constructor + accessors, open kind vocabulary (`parent member reply variant
|
||||
origin link`), `relations-fact-valid?`/`relations-known-kind?`. `api.sx`: db built
|
||||
|
||||
Reference in New Issue
Block a user