relations: Phase 3 path explanation + distance + mixed-kind reachability (explain.sx, reach_any) + 24 tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 53s

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-07 12:06:04 +00:00
parent 7a1696490c
commit ffe3ec25ac
7 changed files with 331 additions and 10 deletions

View File

@@ -18,7 +18,7 @@ links. Reuses `lib/datalog/` — does not reimplement the engine.
## Status (rolling)
`bash lib/relations/conformance.sh`**46/46** (Phases 12 complete)
`bash lib/relations/conformance.sh`**70/70** (Phases 13 complete)
## Ground rules
@@ -81,11 +81,11 @@ lib/relations/federation.sx
## Phase 3 — Typed relations + path explanation
- [ ] multiple kinds coexisting; mixed-kind vs single-kind reachability
- [ ] `lib/relations/explain.sx``(path db a b kind)` returns the connecting
- [x] multiple kinds coexisting; mixed-kind vs single-kind reachability
- [x] `lib/relations/explain.sx``(path db a b kind)` returns the connecting
chain (the relationship equivalent of acl's proof tree), nil if unreachable
- [ ] `(distance db a b kind)` (hops) + shortest-path selection
- [ ] `lib/relations/tests/path.sx` — path correctness, shortest among many, no-path
- [x] `(distance db a b kind)` (hops) + shortest-path selection
- [x] `lib/relations/tests/path.sx` — path correctness, shortest among many, no-path
## Phase 4 — Federation
@@ -100,6 +100,24 @@ lib/relations/federation.sx
## Progress log
- **Phase 3 — typed relations + path explanation** (70/70). New `explain.sx`:
`relations-path(db,a,b,kind)` is relations' answer to acl's proof tree — the
`reach(K,a,b)` derivation read off as the node chain. lib/datalog/ keeps no
provenance, so the chain is re-derived breadth-first over the saturated edge set
(`relations-children-of` per frontier node) so the returned path is a SHORTEST
derivation; every consecutive pair is a real `rel` fact (no invented edges) and
a visited set makes cyclic data terminate. `relations-distance` = hops (0 for
a=b, nil if unreachable). Mixed-kind reachability added to engine.sx as a
kind-agnostic `reach_any` closure (`relations-descendants-any`,
`relations-reachable-any?`) — distinct from single-kind `reach`, so tests show a
parent+member graph where a→m is reachable cross-kind but not under `parent`
alone. api/explain grew `relations/path`, `/distance`, `/descendants-any`,
`/reachable-any?` current-db wrappers. path.sx covers shortest-among-many
(a→c→d beats a→b→c→d), direct edge, self path, no-path/disconnected, kind
isolation in paths, mixed vs single kind, and path-out-of-a-cycle. Note: the
dict-mode conformance driver has no per-suite timeout and the shared machine is
contended by sibling loops — a full run can take a few minutes; the path suite
alone runs in <1s.
- **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`