diff --git a/next/genesis/activity-types/announce.sx b/next/genesis/activity-types/announce.sx new file mode 100644 index 00000000..a5b15e59 --- /dev/null +++ b/next/genesis/activity-types/announce.sx @@ -0,0 +1,14 @@ +;; next/genesis/activity-types/announce.sx +;; +;; Bootstrap definition of the Announce verb per design §13.5 / m2 +;; Step 11. An Announce re-broadcasts a peer's activity to the +;; announcer's followers: the announcer's outbox carries an Announce +;; envelope whose :object is the original activity's CID. Followers +;; can re-fetch the wrapped activity from the original instance if +;; their projection wants to fold the body. + +(DefineActivity + :name "Announce" + :doc "Re-broadcast a peer's activity to followers. :object is the CID of the activity being announced. Recipients see the Announce in their inbox / feed; their projection decides whether to fetch the wrapped activity body." + :schema (fn (act) (string? (-> act :object))) + :semantics (fn (state act) state)) diff --git a/next/genesis/activity-types/endorse.sx b/next/genesis/activity-types/endorse.sx new file mode 100644 index 00000000..16a3b886 --- /dev/null +++ b/next/genesis/activity-types/endorse.sx @@ -0,0 +1,13 @@ +;; next/genesis/activity-types/endorse.sx +;; +;; Bootstrap definition of the Endorse verb per design §13.5 / m2 +;; Step 11. An Endorse expresses cross-actor signal on a target +;; activity (like / share / etc.). :object is the target activity's +;; CID; :kind is the endorsement variant (string). Projections +;; aggregate endorsements into counters / heat / ranking signals. + +(DefineActivity + :name "Endorse" + :doc "Cross-actor signal on a target activity. :object is the target activity's CID; :kind is the endorsement variant (e.g. 'like', 'share'). Projections aggregate endorsements into counters / heat / ranking signals." + :schema (fn (act) (and (string? (-> act :object)) (string? (-> act :kind)))) + :semantics (fn (state act) state)) diff --git a/next/genesis/manifest.sx b/next/genesis/manifest.sx index 1684af3d..7cdceff2 100644 --- a/next/genesis/manifest.sx +++ b/next/genesis/manifest.sx @@ -20,7 +20,9 @@ :kernel-version "1.0.0-m1" :activity-types ("activity-types/create.sx" "activity-types/update.sx" - "activity-types/delete.sx") + "activity-types/delete.sx" + "activity-types/announce.sx" + "activity-types/endorse.sx") :object-types ("object-types/sx-artifact.sx" "object-types/note.sx" "object-types/tombstone.sx" diff --git a/next/tests/bootstrap_load.sh b/next/tests/bootstrap_load.sh index b5229914..26c29ec9 100755 --- a/next/tests/bootstrap_load.sh +++ b/next/tests/bootstrap_load.sh @@ -106,7 +106,7 @@ check 10 "strip suffix create.sx -> create" "true" check 11 "strip suffix hello unchanged" "true" check 12 "strip suffix .sx -> empty" "true" check 13 "load_genesis rejects bad shape" "ok" -check 20 "loaded activity_types count = 3" "3" +check 20 "loaded activity_types count = 5" "5" check 21 "loaded object_types count = 13" "13" check 22 "loaded projections count = 7" "7" check 23 "loaded validators count = 3" "3" diff --git a/next/tests/bootstrap_populate.sh b/next/tests/bootstrap_populate.sh index 0362be3b..724541d9 100755 --- a/next/tests/bootstrap_populate.sh +++ b/next/tests/bootstrap_populate.sh @@ -75,7 +75,7 @@ cat > "$TMPFILE" <>) of {ok, B} -> is_binary(B); _ -> false end\") :name)") EPOCHS -OUTPUT=$(timeout 300 "$SX_SERVER" < "$TMPFILE" 2>/dev/null) +OUTPUT=$(timeout 600 "$SX_SERVER" < "$TMPFILE" 2>/dev/null) check() { local epoch="$1" desc="$2" expected="$3" @@ -99,8 +99,8 @@ check() { check 2 "gen_server loaded" "gen_server" check 3 "registry loaded" "registry" check 4 "bootstrap loaded" "bootstrap" -check 10 "populate returns total 34" "34" -check 20 "activity_types count = 3" "3" +check 10 "populate returns total 36" "36" +check 20 "activity_types count = 5" "5" check 21 "object_types count = 13" "13" check 22 "projections count = 7" "7" check 23 "validators count = 3" "3" diff --git a/next/tests/bootstrap_read.sh b/next/tests/bootstrap_read.sh index 6e2a7810..cccc2ae9 100755 --- a/next/tests/bootstrap_read.sh +++ b/next/tests/bootstrap_read.sh @@ -102,7 +102,7 @@ check 10 "sections/0 length" "7" check 11 "ends_with_sx create.sx" "true" check 12 "ends_with_sx hello" "false" check 13 "ends_with_sx empty" "false" -check 20 "section activity_types count" "3" +check 20 "section activity_types count" "5" check 21 "section object_types count" "13" check 22 "section projections count" "7" check 23 "section validators count" "3" @@ -111,7 +111,7 @@ check 25 "section sig_suites count" "2" check 26 "section audience count" "3" check 30 "read_genesis returns 7 sections" "7" check 31 "first section name" "activity_types" -check 32 "first section entry count" "3" +check 32 "first section entry count" "5" TOTAL=$((PASS+FAIL)) if [ $FAIL -eq 0 ]; then diff --git a/next/tests/bootstrap_start.sh b/next/tests/bootstrap_start.sh index c3cc97fe..453d3f7f 100755 --- a/next/tests/bootstrap_start.sh +++ b/next/tests/bootstrap_start.sh @@ -115,10 +115,10 @@ check() { check 10 "bootstrap module loaded" "bootstrap" check 20 "whereis(nx_kernel) is Pid" "true" -check 21 "activity_types count = 3" "3" +check 21 "activity_types count = 5" "5" check 22 "object_types count = 13" "13" check 23 "projections count = 7" "7" -check 24 "total entries = 34" "34" +check 24 "total entries = 36" "36" check 25 "fresh log_tip = 0" "0" check 26 "publish advances tip to 1" "1" check 27 "actor_id = alice" "true" diff --git a/next/tests/genesis_parse.sh b/next/tests/genesis_parse.sh index 65c7dc37..570d2e57 100755 --- a/next/tests/genesis_parse.sh +++ b/next/tests/genesis_parse.sh @@ -40,6 +40,14 @@ cat > "$TMPFILE" <<'EPOCHS' (eval "(first (parse (file-read \"next/genesis/activity-types/delete.sx\")))") (epoch 18) (eval "(get (apply dict (rest (parse (file-read \"next/genesis/activity-types/delete.sx\")))) :name)") +(epoch 27) +(eval "(first (parse (file-read \"next/genesis/activity-types/announce.sx\")))") +(epoch 28) +(eval "(get (apply dict (rest (parse (file-read \"next/genesis/activity-types/announce.sx\")))) :name)") +(epoch 29) +(eval "(first (parse (file-read \"next/genesis/activity-types/endorse.sx\")))") +(epoch 200) +(eval "(get (apply dict (rest (parse (file-read \"next/genesis/activity-types/endorse.sx\")))) :name)") (epoch 19) (eval "(len (get (apply dict (rest (parse (file-read \"next/genesis/manifest.sx\")))) :activity-types))") (epoch 30) @@ -168,7 +176,11 @@ check 15 "update.sx head form" "DefineActivity" check 16 "update.sx name is Update" "Update" check 17 "delete.sx head form" "DefineActivity" check 18 "delete.sx name is Delete" "Delete" -check 19 "manifest has 3 activity-types" "3" +check 27 "announce.sx head form" "DefineActivity" +check 28 "announce.sx name is Announce" "Announce" +check 29 "endorse.sx head form" "DefineActivity" +check 200 "endorse.sx name is Endorse" "Endorse" +check 19 "manifest has 5 activity-types" "5" check 30 "sx-artifact.sx head form" "DefineObject" check 31 "sx-artifact.sx name" "SXArtifact" check 32 "note.sx name" "Note" diff --git a/plans/fed-sx-milestone-2.md b/plans/fed-sx-milestone-2.md index a76f761c..624fa60d 100644 --- a/plans/fed-sx-milestone-2.md +++ b/plans/fed-sx-milestone-2.md @@ -726,7 +726,16 @@ re-broadcast another actor's content to their own followers. **Deliverables:** -- Three new SX files in a `next/genesis/runtime-verbs/` directory. +- [x] **11a** — Announce + Endorse genesis activity-types + (Note already exists as an object-type from M1 — Create{Note} + is the publish path). Two new `DefineActivity` SX files in + `next/genesis/activity-types/` with `:name`, `:doc`, + `:schema` (Announce: `:object` must be a string CID; Endorse: + `:object` and `:kind` must both be strings). Manifest updated + to 5 activity-types / 36 total entries. Hardcoded count + assertions bumped in `bootstrap_read.sh`, `bootstrap_load.sh`, + `bootstrap_populate.sh`, `bootstrap_start.sh`. `genesis_parse.sh` + +4 cases for the two new files (head form + name). - Each is shipped to a fresh instance via a bootstrap manifest entry *or* published as the first activity on the actor's outbox; either works because of the verb-extensibility mechanism. @@ -985,6 +994,21 @@ proceed. Newest first. +- **2026-06-07** — Step 11a: Announce + Endorse genesis + activity-types. Two new DefineActivity SX files in + `next/genesis/activity-types/`: announce.sx (`:object` is a + CID string — the referenced activity to re-broadcast), + endorse.sx (`:object` is a CID, `:kind` is a string variant + like 'like' or 'share'). Manifest extended to 5 activity-types / + 36 total entries. Bootstrap suite count assertions bumped + (`bootstrap_read`, `bootstrap_load`, `bootstrap_populate`, + `bootstrap_start`). `genesis_parse.sh` +4 cases. M1's Note + object-type is unchanged — Create{Note{...}} is still the + publish path. The runtime-publish demo (verb extensibility + via `Create{DefineActivity{...}}` at runtime) from M1 §9a + still works; these files are the genesis pre-shipped + variants for v2 baseline. + - **2026-06-07** — Step 10b: webfinger HTTP route. `GET /.well-known/webfinger?resource=acct:user@host` lands in `http_server.erl` next to the existing