feed: feed/home capstone — fanout∘inbox∘dedupe∘ACL∘rank∘take as one line + 6 tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 42s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 42s
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -13,7 +13,7 @@ if [ ! -x "$SX_SERVER" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
SUITES=(basic fanout rank integration content notify)
|
SUITES=(basic fanout rank integration content notify home)
|
||||||
|
|
||||||
OUT_JSON="lib/feed/scoreboard.json"
|
OUT_JSON="lib/feed/scoreboard.json"
|
||||||
OUT_MD="lib/feed/scoreboard.md"
|
OUT_MD="lib/feed/scoreboard.md"
|
||||||
@@ -39,6 +39,7 @@ run_suite() {
|
|||||||
(load "lib/feed/fed.sx")
|
(load "lib/feed/fed.sx")
|
||||||
(load "lib/feed/content.sx")
|
(load "lib/feed/content.sx")
|
||||||
(load "lib/feed/notify.sx")
|
(load "lib/feed/notify.sx")
|
||||||
|
(load "lib/feed/home.sx")
|
||||||
(epoch 2)
|
(epoch 2)
|
||||||
(eval "(define feed-test-pass 0)")
|
(eval "(define feed-test-pass 0)")
|
||||||
(eval "(define feed-test-fail 0)")
|
(eval "(define feed-test-fail 0)")
|
||||||
|
|||||||
23
lib/feed/home.sx
Normal file
23
lib/feed/home.sx
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
; feed/home — the capstone. A user's home timeline is the whole pipeline as one
|
||||||
|
; line: fan all activities out over the follow graph, take the events landing in
|
||||||
|
; the viewer's inbox, dedupe cross-posts, apply the viewer's ACL, rank, take N.
|
||||||
|
;
|
||||||
|
; Requires: fanout.sx, dedupe.sx, acl.sx (feed/timeline), rank.sx, stream.sx.
|
||||||
|
|
||||||
|
; the activities in a user's inbox, as a stream
|
||||||
|
(define
|
||||||
|
feed/inbox-stream
|
||||||
|
(fn (inbox user) (feed/stream (feed/inbox-activities inbox user))))
|
||||||
|
|
||||||
|
; fanout ∘ inbox ∘ dedupe ∘ ACL ∘ rank ∘ take
|
||||||
|
(define
|
||||||
|
feed/home
|
||||||
|
(fn
|
||||||
|
(stream graph viewer permit? score-fn n)
|
||||||
|
(feed/timeline
|
||||||
|
(feed/dedupe-activities
|
||||||
|
(feed/inbox-stream (feed/fanout stream graph) viewer))
|
||||||
|
viewer
|
||||||
|
permit?
|
||||||
|
score-fn
|
||||||
|
n)))
|
||||||
@@ -5,9 +5,10 @@
|
|||||||
"rank": {"pass": 24, "fail": 0},
|
"rank": {"pass": 24, "fail": 0},
|
||||||
"integration": {"pass": 22, "fail": 0},
|
"integration": {"pass": 22, "fail": 0},
|
||||||
"content": {"pass": 15, "fail": 0},
|
"content": {"pass": 15, "fail": 0},
|
||||||
"notify": {"pass": 8, "fail": 0}
|
"notify": {"pass": 8, "fail": 0},
|
||||||
|
"home": {"pass": 6, "fail": 0}
|
||||||
},
|
},
|
||||||
"total_pass": 128,
|
"total_pass": 134,
|
||||||
"total_fail": 0,
|
"total_fail": 0,
|
||||||
"total": 128
|
"total": 134
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,4 +10,5 @@ _Generated by `lib/feed/conformance.sh`_
|
|||||||
| integration | 22 | 0 | 22 |
|
| integration | 22 | 0 | 22 |
|
||||||
| content | 15 | 0 | 15 |
|
| content | 15 | 0 | 15 |
|
||||||
| notify | 8 | 0 | 8 |
|
| notify | 8 | 0 | 8 |
|
||||||
| **Total** | **128** | **0** | **128** |
|
| home | 6 | 0 | 6 |
|
||||||
|
| **Total** | **134** | **0** | **134** |
|
||||||
|
|||||||
73
lib/feed/tests/home.sx
Normal file
73
lib/feed/tests/home.sx
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
; Follow-up — feed/home capstone pipeline. (feed-test name got expected)
|
||||||
|
|
||||||
|
; alice follows star and bob (edges: follower followee)
|
||||||
|
(define
|
||||||
|
G
|
||||||
|
(feed/follow-graph (list (list "alice" "star") (list "alice" "bob"))))
|
||||||
|
|
||||||
|
; star posts s1 then s2; bob posts b1; star re-posts s1 (cross-post dup);
|
||||||
|
; zoe posts z1 (alice does NOT follow zoe)
|
||||||
|
(define
|
||||||
|
S
|
||||||
|
(feed/stream
|
||||||
|
(list
|
||||||
|
(feed/activity "star" "post" "s1" 10 (list))
|
||||||
|
(feed/activity "star" "post" "s2" 20 (list))
|
||||||
|
(feed/activity "bob" "post" "b1" 15 (list))
|
||||||
|
(feed/activity "star" "post" "s1" 5 (list))
|
||||||
|
(feed/activity "zoe" "post" "z1" 30 (list)))))
|
||||||
|
|
||||||
|
(define rec (feed/recency 100 10))
|
||||||
|
|
||||||
|
(feed-test
|
||||||
|
"home count (deduped, followed only)"
|
||||||
|
(feed/count (feed/home S G "alice" feed/permit-public? rec 10))
|
||||||
|
3)
|
||||||
|
|
||||||
|
(feed-test
|
||||||
|
"home order by recency"
|
||||||
|
(map
|
||||||
|
(fn (a) (get a :object))
|
||||||
|
(feed/items (feed/home S G "alice" feed/permit-public? rec 10)))
|
||||||
|
(list "s2" "b1" "s1"))
|
||||||
|
|
||||||
|
(feed-test
|
||||||
|
"home excludes unfollowed zoe"
|
||||||
|
(feed/-elem?
|
||||||
|
"z1"
|
||||||
|
(map
|
||||||
|
(fn (a) (get a :object))
|
||||||
|
(feed/items (feed/home S G "alice" feed/permit-public? rec 10))))
|
||||||
|
false)
|
||||||
|
|
||||||
|
(feed-test
|
||||||
|
"home top-2"
|
||||||
|
(map
|
||||||
|
(fn (a) (get a :object))
|
||||||
|
(feed/items (feed/home S G "alice" feed/permit-public? rec 2)))
|
||||||
|
(list "s2" "b1"))
|
||||||
|
|
||||||
|
(feed-test
|
||||||
|
"home dedupes cross-post (one s1)"
|
||||||
|
(len
|
||||||
|
(filter
|
||||||
|
(fn (o) (equal? o "s1"))
|
||||||
|
(map
|
||||||
|
(fn (a) (get a :object))
|
||||||
|
(feed/items
|
||||||
|
(feed/home S G "alice" feed/permit-public? rec 10)))))
|
||||||
|
1)
|
||||||
|
|
||||||
|
; ACL applied per-viewer in the home pipeline
|
||||||
|
(define
|
||||||
|
Sacl
|
||||||
|
(feed/stream
|
||||||
|
(list (feed/normalize {:actor "star" :object "pub" :at 20}) (feed/normalize {:actor "star" :object "sec" :visible-to (list "carol") :at 25}))))
|
||||||
|
(define Gacl (feed/follow-graph (list (list "alice" "star"))))
|
||||||
|
|
||||||
|
(feed-test
|
||||||
|
"home hides activity alice not permitted"
|
||||||
|
(map
|
||||||
|
(fn (a) (get a :object))
|
||||||
|
(feed/items (feed/home Sacl Gacl "alice" feed/permit-acl? rec 10)))
|
||||||
|
(list "pub"))
|
||||||
@@ -14,7 +14,7 @@ APL, ACL visibility filtering via `lib/acl/`, federation via fed-sx.
|
|||||||
|
|
||||||
## Status (rolling)
|
## Status (rolling)
|
||||||
|
|
||||||
`bash lib/feed/conformance.sh` → **128/128** (Phases 1–4 + TF-IDF + notifications)
|
`bash lib/feed/conformance.sh` → **134/134** (Phases 1–4 + TF-IDF + notifications + home)
|
||||||
|
|
||||||
## Ground rules
|
## Ground rules
|
||||||
|
|
||||||
@@ -144,6 +144,9 @@ are function parameters. Real acl-sx / fed-sx wire in at the call site unchanged
|
|||||||
- [x] Notification feed (verb-filtered, per-recipient) — `notify.sx`:
|
- [x] Notification feed (verb-filtered, per-recipient) — `notify.sx`:
|
||||||
`feed/notifications`, `feed/notify-verbs`, `feed/notify-digest` (collapses
|
`feed/notifications`, `feed/notify-verbs`, `feed/notify-digest` (collapses
|
||||||
"X, Y liked Z" by (verb,object), sorted-deterministic); 8 tests. (128/128 total.)
|
"X, Y liked Z" by (verb,object), sorted-deterministic); 8 tests. (128/128 total.)
|
||||||
|
- [x] **Capstone** `feed/home` — the whole pipeline as one line: fanout ∘ inbox ∘
|
||||||
|
dedupe ∘ ACL ∘ rank ∘ take (`home.sx`); 6 tests incl. per-viewer ACL + cross-post
|
||||||
|
dedupe. (134/134 total.)
|
||||||
|
|
||||||
(none)
|
(none)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user