fed-sx-m2: Step 1a — nx_kernel per-actor bucket refactor + 17 tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 20s

State shape becomes [{actors, [{Id, Bucket}, ...]}, {next_actor_seq, N}]
with ActorBucket = [{key_spec, KS}, {actor_state, AS}, {log, L},
{projections, [Name]}, {next_published, N}]. Pure-functional multi-
actor APIs (new/0, add_actor/4, has_actor/2, actors/1, actor_count/1,
publish/3, per-actor accessors, with_actor_projections/3) join the
legacy single-actor accessors, which now read from the first bucket.
Every M1 test continues to pass via bootstrap:start/3 -> new/3 ->
first-bucket lookup.

Local has_keyed/find_keyed/set_keyed/set_bucket helpers cover the
keyed-list ops since lists:keymember/keyfind aren't registered in
this substrate.

next/tests/nx_kernel_multi.sh 17/17. M1 nx_kernel-adjacent suites
green (bootstrap_start 10/10, nx_kernel_server 11/11, http_publish
10/10, smoke_app_pure 12/12, http_post_format 13/13, http_publish_fold
10/10, http_marshal 10/10). Erlang conformance 761/761 preserved.

Blockers entry added for pre-existing http_server_tcp.sh 0/5
regression (78eae9ef left dead helper references in runtime.sx:1593) —
substrate-side, out of m2 scope, confirmed pre-existing by reverting
1a's changes and re-running.
This commit is contained in:
2026-06-06 09:46:24 +00:00
parent 9b04769a27
commit 6a9bd054c7
4 changed files with 440 additions and 87 deletions

View File

@@ -115,36 +115,31 @@ actors.
**Deliverables:**
```erlang
%% nx_kernel state shape becomes:
%% [{actors, [{ActorId, ActorBucket}, ...]},
%% {next_actor_seq, NextN}]
%%
%% ActorBucket = [{key_spec, KS}, {actor_state, AS},
%% {log, LogState}, {projections, [Name]},
%% {next_published, NextSeq}]
-export([new/0, add_actor/4, has_actor/2,
publish/2, publish/3, %% /2 = first actor only
actor_log_tip/2, actor_state/2, ...]).
new() -> [{actors, []}, {next_actor_seq, 1}].
add_actor(ActorId, KeySpec, AS, State) -> {ok, NewState}.
publish(ActorId, Request, State) -> ... %% per-actor
```
`bootstrap:start/3` continues to work — it adds one actor named `alice`
to a fresh kernel — preserving every M1 test that uses the
single-actor entry point.
**Tests:**
- New kernel has no actors.
- add_actor + has_actor round-trip.
- Two actors maintain independent logs + sequences.
- publish/3 advances only the named actor's bucket.
- Concurrent gen_server-mediated publishes for different actors don't
serialise.
- [x] **1a** — Pure-functional bucket APIs. State shape becomes
`[{actors, [{ActorId, ActorBucket}, ...]}, {next_actor_seq, N}]`
with `ActorBucket = [{key_spec, KS}, {actor_state, AS}, {log, L},
{projections, [Name]}, {next_published, N}]`. New exports: `new/0`,
`add_actor/4`, `has_actor/2`, `actors/1`, `actor_count/1`,
`next_actor_seq/1`, `actor_bucket/2`, `publish/3`, per-actor
accessors (`actor_log_state/2`, `actor_log_tip/2`, `actor_key_spec/2`,
`actor_state/2`, `actor_projections/2`, `actor_next_published/2`),
`with_actor_projections/3`. Legacy single-actor accessors
(`actor_id/1`, `key_spec/1`, `actor_state/1`, `log_state/1`,
`log_tip/1`, `projections/1`, `next_published/1`,
`with_projections/2`, legacy `publish/2`) continue to read from the
first bucket — every M1 test passes via `bootstrap:start/3`
`new/3` → first-bucket lookup. `lists:keymember`/`keyfind` not in
the substrate; local `has_keyed`/`find_keyed`/`set_keyed`/
`set_bucket` helpers handle the keyed-list ops.
`next/tests/nx_kernel_multi.sh` 17/17.
- [ ] **1b** — Multi-actor gen_server. `start_link/3` still works as
the single-actor entry; add `add_actor/3` (gen_server call,
bumps bucket), `publish_to/2(ActorId, Request)`, `log_tip_for/1`,
`actors/0`, `state_for/1`, `with_projections_for/2`. Existing
`publish/1`/`log_tip/0`/etc route through bucket-0 unchanged.
Concurrent publishes to distinct actors don't serialise across the
mailbox (multiple casts queued before each is processed). New tests
extend `nx_kernel_multi.sh` with 6-8 gen_server-mediated cases.
**Acceptance:** `bash next/tests/nx_kernel_multi.sh` passes 12+ cases.
@@ -650,3 +645,48 @@ Things still under-specified; resolve as work begins.
via /inbox, does A keep B's signed envelope verbatim (for re-broadcast
on Announce), or does A re-construct + re-sign with A's own key?
AP-canon: keep verbatim. Confirm at Step 5.
---
## Blockers
Pre-existing regressions inherited from the M1 closeout. Out of m2
scope (substrate, not `next/**`), tracked here so iteration can
proceed.
1. **`next/tests/http_server_tcp.sh` 0/5** — pre-existing regression
introduced by `78eae9ef` (`fed-sx-m1: 8b-bridge cleanup`).
`lib/erlang/runtime.sx:1593` still references `er-http-resp-to-sx`
and `er-http-req-of-sx` in `er-bif-http-listen`'s sx-handler body,
but the cleanup commit removed both helpers without rewriting the
BIF. Listener binds (TCP socket accepts), but every request handler
crashes on first call to the undefined helpers — curl gets 000 /
empty body. Fix needs to rewrite the sx-handler body around the
live `er-request-dict-to-proplist` / `er-proplist-to-dict`
helpers (which the cleanup commit's message claimed are already
in use, but which the BIF body never picked up). Substrate work,
belongs on `loops/erlang`. m2 work continues against the in-process
HTTP layer (`http_marshal.sh` 10/10, `http_publish_fold.sh` 10/10)
until resolved. Confirmed pre-existing by stashing 1a's changes and
re-running on the unmodified m1 closeout HEAD.
---
## Progress log
Newest first.
- **2026-06-06** — Step 1a: per-actor bucket refactor of `nx_kernel`.
State shape now `[{actors, [{Id, Bucket}, …]}, {next_actor_seq, N}]`;
added pure-functional multi-actor APIs (`new/0`, `add_actor/4`,
`has_actor/2`, `actors/1`, `publish/3`, per-actor accessors,
`with_actor_projections/3`). Legacy single-actor accessors
preserved as bucket-0 lookups so every M1 test continues to
pass via `bootstrap:start/3``new/3` → first-bucket read.
Local `has_keyed`/`find_keyed`/`set_keyed`/`set_bucket` helpers
cover the keyed-list ops since `lists:keymember`/`keyfind` aren't
registered in this substrate. New test suite
`next/tests/nx_kernel_multi.sh` 17/17; all M1 nx_kernel-adjacent
suites green (`bootstrap_start`, `nx_kernel_server`, `http_publish`,
`smoke_app_pure`, `http_post_format`, `http_publish_fold`,
`http_marshal`). Erlang conformance 761/761 preserved.