fed-sx-m2: Step 2a — Person/Service/Group genesis object-types
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 35s

Three new DefineObject artefacts in next/genesis/object-types/ for
the canonical actor object-types per design §9.1:

- Person: human-controlled identity (display name + handle + bio)
- Service: automated / programmatic actor (bot, feed, organisation)
- Group: multi-controller actor (member-set managed via Add/Remove)

Each is a small SX form with :name / :doc / :schema, identical
shape to existing object-types (note.sx, sx-artifact.sx etc) so the
existing bootstrap:populate_registry walk picks them up without
code changes. Manifest extended (object-types: 10 -> 13, total
entries: 31 -> 34).

Tests:
- genesis_parse.sh +7 cases (head form, :name, manifest membership);
  57/57.
- Hardcoded counts bumped in bootstrap_read.sh, bootstrap_load.sh,
  bootstrap_populate.sh, bootstrap_start.sh.
- bootstrap_build.sh 12/12 (bundle CID computed dynamically).

Conformance 761/761 preserved. 211/211 across 12 Step-2-adjacent
suites.
This commit is contained in:
2026-06-06 11:19:22 +00:00
parent 089d1445a1
commit 0c44a10c8f
10 changed files with 100 additions and 21 deletions

View File

@@ -24,6 +24,9 @@
:object-types ("object-types/sx-artifact.sx" :object-types ("object-types/sx-artifact.sx"
"object-types/note.sx" "object-types/note.sx"
"object-types/tombstone.sx" "object-types/tombstone.sx"
"object-types/person.sx"
"object-types/service.sx"
"object-types/group.sx"
"object-types/define-activity.sx" "object-types/define-activity.sx"
"object-types/define-object.sx" "object-types/define-object.sx"
"object-types/define-projection.sx" "object-types/define-projection.sx"

View File

@@ -0,0 +1,11 @@
;; next/genesis/object-types/group.sx
;;
;; Per design §9.1: a Group is a multi-controller actor — typically
;; a working group, channel, or collective whose membership is
;; managed via Add/Remove activities. Sig-suite validation honours
;; the current key-set rather than a single keypair.
(DefineObject
:name "Group"
:doc "Multi-controller actor. :name is the group's display name; :preferredUsername is the local handle; :summary is the description; :icon is a CID or URL; :members is the current member list (managed via Add/Remove)."
:schema (fn (obj) (string? (-> obj :name))))

View File

@@ -0,0 +1,11 @@
;; next/genesis/object-types/person.sx
;;
;; Per design §9.1: a Person is the canonical actor type for a
;; human-controlled identity. Bootstrapped via Create{Person{...}}
;; as the actor's first activity (see nx_kernel:bootstrap_actor/4).
;; ActivityPub-Person-compatible.
(DefineObject
:name "Person"
:doc "Human-controlled actor. :name is the display name; :preferredUsername is the local handle; :summary is the profile bio; :icon is a CID or URL."
:schema (fn (obj) (string? (-> obj :name))))

View File

@@ -0,0 +1,11 @@
;; next/genesis/object-types/service.sx
;;
;; Per design §9.1: a Service is a non-human actor — a bot, an
;; automated feed, an organisational publisher. Same activity
;; surface as Person, different ActivityPub Actor type. Tooling
;; treats a Service identically to a Person except for UX hints.
(DefineObject
:name "Service"
:doc "Automated / programmatic actor. :name is the display name; :preferredUsername is the local handle; :summary is the profile bio; :icon is a CID or URL."
:schema (fn (obj) (string? (-> obj :name))))

View File

@@ -107,7 +107,7 @@ check 11 "strip suffix hello unchanged" "true"
check 12 "strip suffix .sx -> empty" "true" check 12 "strip suffix .sx -> empty" "true"
check 13 "load_genesis rejects bad shape" "ok" check 13 "load_genesis rejects bad shape" "ok"
check 20 "loaded activity_types count = 3" "3" check 20 "loaded activity_types count = 3" "3"
check 21 "loaded object_types count = 10" "10" check 21 "loaded object_types count = 13" "13"
check 22 "loaded projections count = 7" "7" check 22 "loaded projections count = 7" "7"
check 23 "loaded validators count = 3" "3" check 23 "loaded validators count = 3" "3"
check 24 "loaded codecs count = 3" "3" check 24 "loaded codecs count = 3" "3"

View File

@@ -99,9 +99,9 @@ check() {
check 2 "gen_server loaded" "gen_server" check 2 "gen_server loaded" "gen_server"
check 3 "registry loaded" "registry" check 3 "registry loaded" "registry"
check 4 "bootstrap loaded" "bootstrap" check 4 "bootstrap loaded" "bootstrap"
check 10 "populate returns total 31" "31" check 10 "populate returns total 34" "34"
check 20 "activity_types count = 3" "3" check 20 "activity_types count = 3" "3"
check 21 "object_types count = 10" "10" check 21 "object_types count = 13" "13"
check 22 "projections count = 7" "7" check 22 "projections count = 7" "7"
check 23 "validators count = 3" "3" check 23 "validators count = 3" "3"
check 24 "codecs count = 3" "3" check 24 "codecs count = 3" "3"

View File

@@ -103,7 +103,7 @@ check 11 "ends_with_sx create.sx" "true"
check 12 "ends_with_sx hello" "false" check 12 "ends_with_sx hello" "false"
check 13 "ends_with_sx empty" "false" check 13 "ends_with_sx empty" "false"
check 20 "section activity_types count" "3" check 20 "section activity_types count" "3"
check 21 "section object_types count" "10" check 21 "section object_types count" "13"
check 22 "section projections count" "7" check 22 "section projections count" "7"
check 23 "section validators count" "3" check 23 "section validators count" "3"
check 24 "section codecs count" "3" check 24 "section codecs count" "3"

View File

@@ -116,9 +116,9 @@ check() {
check 10 "bootstrap module loaded" "bootstrap" check 10 "bootstrap module loaded" "bootstrap"
check 20 "whereis(nx_kernel) is Pid" "true" check 20 "whereis(nx_kernel) is Pid" "true"
check 21 "activity_types count = 3" "3" check 21 "activity_types count = 3" "3"
check 22 "object_types count = 10" "10" check 22 "object_types count = 13" "13"
check 23 "projections count = 7" "7" check 23 "projections count = 7" "7"
check 24 "total entries = 31" "31" check 24 "total entries = 34" "34"
check 25 "fresh log_tip = 0" "0" check 25 "fresh log_tip = 0" "0"
check 26 "publish advances tip to 1" "1" check 26 "publish advances tip to 1" "1"
check 27 "actor_id = alice" "true" check 27 "actor_id = alice" "true"

View File

@@ -64,6 +64,20 @@ cat > "$TMPFILE" <<'EPOCHS'
(eval "(get (apply dict (rest (parse (file-read \"next/genesis/object-types/define-sig-suite.sx\")))) :name)") (eval "(get (apply dict (rest (parse (file-read \"next/genesis/object-types/define-sig-suite.sx\")))) :name)")
(epoch 40) (epoch 40)
(eval "(get (apply dict (rest (parse (file-read \"next/genesis/object-types/snapshot.sx\")))) :name)") (eval "(get (apply dict (rest (parse (file-read \"next/genesis/object-types/snapshot.sx\")))) :name)")
(epoch 42)
(eval "(first (parse (file-read \"next/genesis/object-types/person.sx\")))")
(epoch 43)
(eval "(get (apply dict (rest (parse (file-read \"next/genesis/object-types/person.sx\")))) :name)")
(epoch 44)
(eval "(first (parse (file-read \"next/genesis/object-types/service.sx\")))")
(epoch 45)
(eval "(get (apply dict (rest (parse (file-read \"next/genesis/object-types/service.sx\")))) :name)")
(epoch 46)
(eval "(first (parse (file-read \"next/genesis/object-types/group.sx\")))")
(epoch 47)
(eval "(get (apply dict (rest (parse (file-read \"next/genesis/object-types/group.sx\")))) :name)")
(epoch 48)
(eval "(some (fn (p) (= p \"object-types/person.sx\")) (get (apply dict (rest (parse (file-read \"next/genesis/manifest.sx\")))) :object-types))")
(epoch 41) (epoch 41)
(eval "(len (get (apply dict (rest (parse (file-read \"next/genesis/manifest.sx\")))) :object-types))") (eval "(len (get (apply dict (rest (parse (file-read \"next/genesis/manifest.sx\")))) :object-types))")
(epoch 50) (epoch 50)
@@ -166,7 +180,14 @@ check 37 "define-validator.sx name" "DefineValidator"
check 38 "define-codec.sx name" "DefineCodec" check 38 "define-codec.sx name" "DefineCodec"
check 39 "define-sig-suite.sx name" "DefineSigSuite" check 39 "define-sig-suite.sx name" "DefineSigSuite"
check 40 "snapshot.sx name" "Snapshot" check 40 "snapshot.sx name" "Snapshot"
check 41 "manifest has 10 object-types" "10" check 42 "person.sx head form" "DefineObject"
check 43 "person.sx name" "Person"
check 44 "service.sx head form" "DefineObject"
check 45 "service.sx name" "Service"
check 46 "group.sx head form" "DefineObject"
check 47 "group.sx name" "Group"
check 48 "manifest lists person.sx" "true"
check 41 "manifest has 13 object-types" "13"
check 50 "activity-log.sx head form" "DefineProjection" check 50 "activity-log.sx head form" "DefineProjection"
check 51 "activity-log.sx name" "activity-log" check 51 "activity-log.sx name" "activity-log"
check 52 "by-type.sx name" "by-type" check 52 "by-type.sx name" "by-type"

View File

@@ -158,21 +158,32 @@ publicKey rotation history, profile fields, follower counts, etc.
**Deliverables:** **Deliverables:**
- Genesis additions: `DefineObject{Person}` / `DefineObject{Service}` / - [x] **2a** Genesis additions: `DefineObject{Person}` /
`DefineObject{Group}` — three object-type SX files. `DefineObject{Service}` / `DefineObject{Group}` — three new SX
- Actor-state projection fold (Erlang-fun stand-in, mirrors Step 5d-pure): files in `next/genesis/object-types/` plus manifest entries (now
- On `Create{Person|Service|Group}`: register the actor's profile. 13 object-types total, 34 total genesis entries). Each defines
- On `Update{Person, patch}`: apply patch. `:name`, `:doc`, `:schema (fn (obj) (string? (-> obj :name)))`.
`next/tests/genesis_parse.sh` extended +7 cases (head form +
:name + manifest membership), now 57/57. Bootstrap suite
count assertions bumped (`bootstrap_read.sh` 15/15,
`bootstrap_load.sh` 15/15, `bootstrap_populate.sh` 14/14,
`bootstrap_start.sh` 10/10). `bootstrap_build.sh` 12/12 picks
up the new bundle CID dynamically.
- [ ] **2b** — Actor-state projection fold (Erlang-fun stand-in,
mirrors Step 5d-pure's `define_registry`):
- On `Create{Person|Service|Group}`: register the actor's profile
in `{ActorId => #{type, name, preferredUsername, summary, icon,
public_keys, created}}`.
- On `Update{Person|Service|Group, patch}`: deep-merge the patch.
- On `Move`: record `:movedTo` pointer. - On `Move`: record `:movedTo` pointer.
- `nx_kernel:bootstrap_actor/4(ActorId, Profile, KeySpec, State)` - `next/kernel/actor_state.erl` with `fold_fn/0` plugging into
publishes `Create{Person{...}}` as the actor's first activity, `projection:start_link/3`. Pure-functional + gen_server-bridged
bootstrapping their own log. tests as a single `actor_state_pure.sh`.
- [ ] **2c** — `nx_kernel:bootstrap_actor/4(ActorId, Profile,
**Tests:** KeySpec, State)` — publishes `Create{Person{...}}` as the actor's
first activity, exercising the full pipeline. Integration test
- `Create{Person}` registers the actor. in `actor_lifecycle.sh` ties 2a artefacts (SX files), 2b
- Two actors created via lifecycle activities have independent state. projection, and 2c bootstrap together.
- Profile updates apply.
**Acceptance:** `bash next/tests/actor_lifecycle.sh` passes 10+ cases. **Acceptance:** `bash next/tests/actor_lifecycle.sh` passes 10+ cases.
@@ -680,6 +691,17 @@ proceed.
Newest first. Newest first.
- **2026-06-06** — Step 2a: genesis Person/Service/Group object-
types. Three new SX files in `next/genesis/object-types/` with
the same shape as `note.sx` / `sx-artifact.sx` (`:name`, `:doc`,
`:schema` checking `(string? (-> obj :name))`). Manifest extended
to 13 object-types / 34 total entries. `genesis_parse.sh` +7
cases (57/57). Hardcoded counts bumped in `bootstrap_read.sh`,
`bootstrap_load.sh`, `bootstrap_populate.sh`, `bootstrap_start.sh`
(66/66 across those four). `bootstrap_build.sh` 12/12 (bundle CID
computed dynamically). Conformance 761/761 preserved. 211 / 211
across 12 Step-2-adjacent suites.
- **2026-06-06** — Step 1b: gen_server multi-actor calls. - **2026-06-06** — Step 1b: gen_server multi-actor calls.
`nx_kernel` exports `add_actor/3`, `publish_to/2`, `log_tip_for/1`, `nx_kernel` exports `add_actor/3`, `publish_to/2`, `log_tip_for/1`,
`actors/0`, `state_for/1`, `bucket_for/1`, `actors/0`, `state_for/1`, `bucket_for/1`,