datalog: cooking-posts canonical demo (Phase 10, 162/162)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 55s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 55s
Adds the canonical Phase 10 example from the plan: "Posts about cooking by people I follow (transitively)." dl-demo-cooking-rules defines reach over the follow graph (recursive transitive closure) and cooking-post-by-network joining reach + authored + (tagged P cooking). 3 new demo tests cover transitive network, direct-only follow, and empty-network cases.
This commit is contained in:
@@ -64,6 +64,26 @@
|
|||||||
(subgroup-trans X Z <- (subgroup X Y) (subgroup-trans Y Z))
|
(subgroup-trans X Z <- (subgroup X Y) (subgroup-trans Y Z))
|
||||||
(can-access A R <- (in-group A G) (allowed G R)))))
|
(can-access A R <- (in-group A G) (allowed G R)))))
|
||||||
|
|
||||||
|
;; ── Demo 4: cooking-posts (the canonical Phase 10 query) ────────
|
||||||
|
;; "Posts about cooking by people I follow (transitively)."
|
||||||
|
;; Combines federation (follows + transitive reach), authoring,
|
||||||
|
;; tagging — the rose-ash multi-domain join.
|
||||||
|
;;
|
||||||
|
;; EDB:
|
||||||
|
;; (follows ACTOR-A ACTOR-B)
|
||||||
|
;; (authored ACTOR POST)
|
||||||
|
;; (tagged POST TAG)
|
||||||
|
(define
|
||||||
|
dl-demo-cooking-rules
|
||||||
|
(quote
|
||||||
|
((reach Me Them <- (follows Me Them))
|
||||||
|
(reach Me Them <- (follows Me X) (reach X Them))
|
||||||
|
(cooking-post-by-network Me P
|
||||||
|
<-
|
||||||
|
(reach Me Author)
|
||||||
|
(authored Author P)
|
||||||
|
(tagged P cooking)))))
|
||||||
|
|
||||||
;; ── Loader stub ──────────────────────────────────────────────────
|
;; ── Loader stub ──────────────────────────────────────────────────
|
||||||
;; Wiring to PostgreSQL would replace these helpers with calls into
|
;; Wiring to PostgreSQL would replace these helpers with calls into
|
||||||
;; rose-ash's internal HTTP RPC (fetch_data → /internal/data/...).
|
;; rose-ash's internal HTTP RPC (fetch_data → /internal/data/...).
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"lang": "datalog",
|
"lang": "datalog",
|
||||||
"total_passed": 159,
|
"total_passed": 162,
|
||||||
"total_failed": 0,
|
"total_failed": 0,
|
||||||
"total": 159,
|
"total": 162,
|
||||||
"suites": [
|
"suites": [
|
||||||
{"name":"tokenize","passed":26,"failed":0,"total":26},
|
{"name":"tokenize","passed":26,"failed":0,"total":26},
|
||||||
{"name":"parse","passed":18,"failed":0,"total":18},
|
{"name":"parse","passed":18,"failed":0,"total":18},
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
{"name":"negation","passed":10,"failed":0,"total":10},
|
{"name":"negation","passed":10,"failed":0,"total":10},
|
||||||
{"name":"aggregates","passed":13,"failed":0,"total":13},
|
{"name":"aggregates","passed":13,"failed":0,"total":13},
|
||||||
{"name":"api","passed":9,"failed":0,"total":9},
|
{"name":"api","passed":9,"failed":0,"total":9},
|
||||||
{"name":"demo","passed":10,"failed":0,"total":10}
|
{"name":"demo","passed":13,"failed":0,"total":13}
|
||||||
],
|
],
|
||||||
"generated": "2026-05-08T09:02:31+00:00"
|
"generated": "2026-05-08T09:05:25+00:00"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# datalog scoreboard
|
# datalog scoreboard
|
||||||
|
|
||||||
**159 / 159 passing** (0 failure(s)).
|
**162 / 162 passing** (0 failure(s)).
|
||||||
|
|
||||||
| Suite | Passed | Total | Status |
|
| Suite | Passed | Total | Status |
|
||||||
|-------|--------|-------|--------|
|
|-------|--------|-------|--------|
|
||||||
@@ -13,4 +13,4 @@
|
|||||||
| negation | 10 | 10 | ok |
|
| negation | 10 | 10 | ok |
|
||||||
| aggregates | 13 | 13 | ok |
|
| aggregates | 13 | 13 | ok |
|
||||||
| api | 9 | 9 | ok |
|
| api | 9 | 9 | ok |
|
||||||
| demo | 10 | 10 | ok |
|
| demo | 13 | 13 | ok |
|
||||||
|
|||||||
@@ -179,6 +179,41 @@
|
|||||||
(quote (can-access X blog)))
|
(quote (can-access X blog)))
|
||||||
(list {:X (quote carol)}))
|
(list {:X (quote carol)}))
|
||||||
|
|
||||||
|
;; ── Cooking posts (canonical Phase 10 example) ─────────
|
||||||
|
(dl-demo-test-set! "cooking posts by network"
|
||||||
|
(dl-query
|
||||||
|
(dl-demo-make
|
||||||
|
(quote
|
||||||
|
((follows me alice) (follows alice bob) (follows alice carol)
|
||||||
|
(authored alice p1) (authored bob p2)
|
||||||
|
(authored carol p3) (authored carol p4)
|
||||||
|
(tagged p1 travel) (tagged p2 cooking)
|
||||||
|
(tagged p3 cooking) (tagged p4 books)))
|
||||||
|
dl-demo-cooking-rules)
|
||||||
|
(quote (cooking-post-by-network me P)))
|
||||||
|
(list {:P (quote p2)} {:P (quote p3)}))
|
||||||
|
|
||||||
|
(dl-demo-test-set! "cooking — direct follow only"
|
||||||
|
(dl-query
|
||||||
|
(dl-demo-make
|
||||||
|
(quote
|
||||||
|
((follows me bob)
|
||||||
|
(authored bob p1) (authored bob p2)
|
||||||
|
(tagged p1 cooking) (tagged p2 books)))
|
||||||
|
dl-demo-cooking-rules)
|
||||||
|
(quote (cooking-post-by-network me P)))
|
||||||
|
(list {:P (quote p1)}))
|
||||||
|
|
||||||
|
(dl-demo-test-set! "cooking — none in network"
|
||||||
|
(dl-query
|
||||||
|
(dl-demo-make
|
||||||
|
(quote
|
||||||
|
((follows me bob)
|
||||||
|
(authored bob p1) (tagged p1 books)))
|
||||||
|
dl-demo-cooking-rules)
|
||||||
|
(quote (cooking-post-by-network me P)))
|
||||||
|
(list))
|
||||||
|
|
||||||
(dl-demo-test-set! "no access without grant"
|
(dl-demo-test-set! "no access without grant"
|
||||||
(dl-query
|
(dl-query
|
||||||
(dl-demo-make
|
(dl-demo-make
|
||||||
|
|||||||
@@ -243,6 +243,9 @@ large graphs.
|
|||||||
`(interesting Me P)` joining follows + authored + popular.
|
`(interesting Me P)` joining follows + authored + popular.
|
||||||
- **Permissions**: `(member A G)`, `(subgroup C P)`, `(allowed G R)`
|
- **Permissions**: `(member A G)`, `(subgroup C P)`, `(allowed G R)`
|
||||||
→ `(in-group A G)` over transitive subgroups, `(can-access A R)`.
|
→ `(in-group A G)` over transitive subgroups, `(can-access A R)`.
|
||||||
|
- **Cooking-posts** (the canonical example): `(reach Me Them)` over
|
||||||
|
the follow graph, then `(cooking-post-by-network Me P)` joining
|
||||||
|
reach + authored + `(tagged P cooking)`.
|
||||||
- [ ] Loader `dl-load-from-db!` — out of scope for this loop
|
- [ ] Loader `dl-load-from-db!` — out of scope for this loop
|
||||||
(would need to edit `shared/services/` outside `lib/datalog/`).
|
(would need to edit `shared/services/` outside `lib/datalog/`).
|
||||||
Programs in `demo.sx` already document the EDB shape expected
|
Programs in `demo.sx` already document the EDB shape expected
|
||||||
@@ -270,6 +273,14 @@ large graphs.
|
|||||||
|
|
||||||
_Newest first._
|
_Newest first._
|
||||||
|
|
||||||
|
- 2026-05-08 — Phase 10 demo + canonical query. Added the "cooking
|
||||||
|
posts by people I follow (transitively)" example from the plan:
|
||||||
|
`dl-demo-cooking-rules` defines `reach` over the follow graph
|
||||||
|
(recursive transitive closure) and `cooking-post-by-network` that
|
||||||
|
joins reach with `authored` and `(tagged P cooking)`. 3 demo
|
||||||
|
tests cover transitive network, direct-only follow, and
|
||||||
|
empty-network cases.
|
||||||
|
|
||||||
- 2026-05-08 — Phase 8 extension: `findall L V Goal` aggregate. Bind
|
- 2026-05-08 — Phase 8 extension: `findall L V Goal` aggregate. Bind
|
||||||
L to the list of distinct V values for which Goal holds (or the
|
L to the list of distinct V values for which Goal holds (or the
|
||||||
empty list when no matches). Implemented as a one-line case in
|
empty list when no matches). Implemented as a one-line case in
|
||||||
|
|||||||
Reference in New Issue
Block a user