;; lib/datalog/demo.sx — example programs over rose-ash-shaped data.
;;
;; Phase 10 prototypes Datalog as a rose-ash query language. Wiring
;; the EDB to actual PostgreSQL is out of scope for this loop (it
;; would touch service code outside lib/datalog/), but the programs
;; below show the shape of queries we want, and the test suite runs
;; them against synthetic in-memory tuples loaded via dl-program-data.
;;
;; Seven thematic demos:
;;
;;   1. Federation — follow graph, transitive reach, mutuals, FOAF.
;;   2. Content    — posts, tags, likes, popularity, "for you" feed.
;;   3. Permissions — group membership and resource access.
;;   4. Cooking-posts — canonical "posts about cooking by people I
;;                      follow (transitively)" multi-domain query.
;;   5. Tag co-occurrence — distinct (T1, T2) pairs with counts.
;;   6. Shortest path  — weighted-DAG path enumeration + min agg.
;;   7. Org chart      — transitive subordinate + headcount per mgr.

;; ── Demo 1: federation follow graph ─────────────────────────────
;; EDB: (follows ACTOR-A ACTOR-B) — A follows B.
;; IDB:
;;   (mutual A B)            — A follows B and B follows A
;;   (reachable A B)         — transitive follow closure
;;   (foaf A C)              — friend of a friend (mutual filter)
(define
  dl-demo-federation-rules
  (quote
    ((mutual A B <- (follows A B) (follows B A))
     (reachable A B <- (follows A B))
     (reachable A C <- (follows A B) (reachable B C))
     (foaf A C <- (follows A B) (follows B C) (!= A C)))))

;; ── Demo 2: content recommendation ──────────────────────────────
;; EDB:
;;   (authored ACTOR POST)
;;   (tagged POST TAG)
;;   (liked ACTOR POST)
;; IDB:
;;   (post-likes POST N)            — count of likes per post
;;   (popular POST)                 — posts with >= 3 likes
;;   (tagged-by-mutual ACTOR POST)  — post tagged TOPIC by someone
;;                                    A's mutuals follow.
(define
  dl-demo-content-rules
  (quote
    ((post-likes P N <- (authored Author P) (count N L (liked L P)))
     (popular P <- (authored Author P) (post-likes P N) (>= N 3))
     (interesting Me P
       <-
       (follows Me Buddy)
       (authored Buddy P)
       (popular P)))))

;; ── Demo 3: role-based permissions ──────────────────────────────
;; EDB:
;;   (member ACTOR GROUP)
;;   (subgroup CHILD PARENT)
;;   (allowed GROUP RESOURCE)
;; IDB:
;;   (in-group ACTOR GROUP)         — direct or via subgroup chain
;;   (can-access ACTOR RESOURCE)    — actor inherits group permission
(define
  dl-demo-perm-rules
  (quote
    ((in-group A G <- (member A G))
     (in-group A G <- (member A H) (subgroup-trans H G))
     (subgroup-trans X Y <- (subgroup X Y))
     (subgroup-trans X Z <- (subgroup X Y) (subgroup-trans Y Z))
     (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)))))

;; ── Demo 5: tag co-occurrence ───────────────────────────────────
;; "Posts tagged with both T1 AND T2." Useful for narrowed-down
;; recommendations like "vegetarian cooking" posts.
;;
;; EDB:
;;   (tagged POST TAG)
;; IDB:
;;   (cotagged POST T1 T2)        — post has both T1 and T2 (T1 != T2)
;;   (popular-pair T1 T2 N)       — count of posts cotagged (T1, T2)
(define
  dl-demo-tag-cooccur-rules
  (quote
    ((cotagged P T1 T2 <- (tagged P T1) (tagged P T2) (!= T1 T2))
     ;; Distinct (T1, T2) pairs that occur somewhere.
     (tag-pair T1 T2 <- (cotagged P T1 T2))
     (tag-pair-count T1 T2 N
       <-
       (tag-pair T1 T2)
       (count N P (cotagged P T1 T2))))))

;; ── Demo 6: weighted-DAG shortest path ─────────────────────────
;; "What's the cheapest way from X to Y?" Edge weights with `is`
;; arithmetic to sum costs, then `min` aggregation to pick the
;; shortest. Termination requires the graph to be a DAG (cycles
;; would produce infinite distances without a bound; programs
;; built on this should add a depth filter `(<, D, MAX)` if cycles
;; are possible).
;;
;; EDB:
;;   (edge FROM TO COST)
;; IDB:
;;   (path FROM TO COST)            — any path
;;   (shortest FROM TO COST)        — minimum cost path
(define
  dl-demo-shortest-path-rules
  (quote
    ((path X Y W <- (edge X Y W))
     (path X Z W
       <-
       (edge X Y W1)
       (path Y Z W2)
       (is W (+ W1 W2)))
     (shortest X Y W <- (path X Y _) (min W C (path X Y C))))))

;; ── Demo 7: org chart + transitive headcount ───────────────────
;; Manager graph: each employee has a single manager. Compute the
;; transitive subordinate set and headcount per manager.
;;
;; EDB:
;;   (manager EMP MGR)            — EMP reports directly to MGR
;; IDB:
;;   (subordinate MGR EMP)        — EMP is in MGR's subtree
;;   (headcount MGR N)            — number of subordinates under MGR
(define
  dl-demo-org-rules
  (quote
    ((subordinate Mgr Emp <- (manager Emp Mgr))
     (subordinate Mgr Emp
       <- (manager Mid Mgr) (subordinate Mid Emp))
     (headcount Mgr N
       <- (subordinate Mgr Anyone) (count N E (subordinate Mgr E))))))

;; ── Loader stub ──────────────────────────────────────────────────
;; Wiring to PostgreSQL would replace these helpers with calls into
;; rose-ash's internal HTTP RPC (fetch_data → /internal/data/...).
;; The shape returned by dl-load-from-edb! is the same in either case.
(define
  dl-demo-make
  (fn
    (facts rules)
    (dl-program-data facts rules)))
