Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
46f8141
feat(game-macros): deny economy names on FactCommand fields
patrickleet Oct 20, 2026
61dc71b
feat(game): stamp facts with wall time, activation and config
patrickleet Oct 20, 2026
7a32cc8
feat(game): typed ticket extension claims
patrickleet Oct 20, 2026
326cfb4
feat(game): async zone factory with allocation records
patrickleet Oct 20, 2026
c20225c
feat(game): host-emitted player lifecycle facts
patrickleet Oct 20, 2026
d9a3fd9
feat(game): typed zone inbox with kick and admin route
patrickleet Oct 20, 2026
4de4347
feat(cell-host): re-armable cell alarms sharing the DO alarm
patrickleet Oct 20, 2026
dd35d4a
feat(saga): fan-out steps to N cells chosen at run time
patrickleet Oct 20, 2026
290b944
ci: build every domain crate for wasm32 in a required job
patrickleet Oct 20, 2026
8898386
feat(graphql): leaderboard roots, @live boards and TS client
patrickleet Oct 20, 2026
6f2f879
feat(game): CelldFactSink routes zone facts to celld cells
patrickleet Oct 20, 2026
fa6e3b9
feat(game): zone leases as celld cells with alarm expiry
patrickleet Oct 20, 2026
4fc1408
fix(game): order same-tick facts and report dropped sockets
patrickleet Oct 20, 2026
2e04351
feat(game): project zone entities into replicated views
patrickleet Oct 20, 2026
2eb4f9f
feat(macros): #[command] on aggregate methods
patrickleet Oct 20, 2026
633d309
feat(game)!: run Mob Pit cells on celld, drop cell-sqlite
patrickleet Oct 20, 2026
fac1cf3
feat(game)!: hibernate zones in celld cells, all demos on celld
patrickleet Oct 20, 2026
22bb63f
feat(game)!: list Mob Pit crawlers from a projection, drop roster
patrickleet Oct 20, 2026
20d1421
feat(game)!: zone status read model for lease and snapshot events
patrickleet Oct 20, 2026
7f63c74
fix(game): retry a locked shared projection bus open
patrickleet Oct 20, 2026
cd89746
feat!: portable aggregate schedules and clock, command fact sink
patrickleet Oct 20, 2026
edae35c
fix(e2e)!: pin celld 0.6.2 and move the profile off :18080
patrickleet Oct 20, 2026
bbae056
docs: fix dangling paths to e2e-ui code and test dirs
patrickleet Oct 20, 2026
617a452
docs(e2e-ui): match README samples and claims to the code
patrickleet Oct 20, 2026
358a9e7
docs(e2e-ui): make walkthrough samples match the code
patrickleet Oct 20, 2026
fa6c5b5
docs(game)!: drop pre-celld wording, rename the shared cells worker
patrickleet Oct 20, 2026
875dc2c
feat(cli)!: contracts under hops service, real catalog by default
patrickleet Oct 20, 2026
2597265
chore(e2e-ui): remove the orphaned gitops tree and unused scripts
patrickleet Oct 20, 2026
67e3362
test(e2e-celld): run the full Playwright suite on celld + NATS
patrickleet Oct 20, 2026
866a726
feat(schedule): schedule worker for SQL and in-memory repositories
patrickleet Oct 20, 2026
99e7582
feat(leaderboard): board change notices over the bus for @live
patrickleet Oct 20, 2026
b847e71
feat: leaderboards in application manifests and SvelteKit helpers
patrickleet Oct 21, 2026
f9c199a
feat(game)!: Mob Pit SvelteKit shows the Redis board live via GraphQL
patrickleet Oct 21, 2026
68359a2
test: expect migration 13 in the migration version assertions
patrickleet Oct 21, 2026
8138354
test(schedule): make the worker crash test robust on Postgres
patrickleet Oct 21, 2026
0c4a940
fix(game): give REDIS_URL only to the SvelteKit test in run.sh smoke
patrickleet Oct 21, 2026
ab368c5
test(js): expect leaderboard and ticket exports in pack smoke
patrickleet Oct 21, 2026
b397cff
fix(game): release a refused transfer before rejecting the client
patrickleet Oct 21, 2026
c274d07
test(game): wait for every kill to settle before board checks
patrickleet Oct 21, 2026
13973be
test(cli): run the lifecycle executor fixture through sh
patrickleet Oct 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions .celld-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0.6.2
3 changes: 2 additions & 1 deletion .github/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ existing unbounded-tech quality provider plus the integration/* jobs below —
| [`test-all-features.yaml`](./test-all-features.yaml) | yes | **This repo:** workspace `--all-features` |
| [`integration-*.yaml`](./) | yes | **This repo:** broker / DB / CLI / observability / GraphQL identity+OIDC |
| [`integration-e2e-ui.yaml`](./integration-e2e-ui.yaml) | yes | **This repo:** `tests/e2e-ui` offline suite, compose Playwright e2e, and kind local-GitOps Playwright e2e |
| [`integration-celld.yaml`](./integration-celld.yaml) | yes | **This repo:** `tests/e2e-celld` workspace tests + live Azurite+celld+NATS |
| [`integration-celld.yaml`](./integration-celld.yaml) | yes | **This repo:** `tests/e2e-celld` workspace tests, celld storage and cell-alarm proofs (`celld dev`), live celld+NATS |
| [`integration-wasm32-domains.yaml`](./integration-wasm32-domains.yaml) | yes | **This repo:** every domain crate builds for `wasm32-unknown-unknown` (`scripts/check-wasm32-domains.sh`), and a native-only fixture must fail |
| [`integration-js.yaml`](./integration-js.yaml) | yes | **This repo:** install, typecheck, test, build, and packed-consumer smoke test for `js/` |
| [`on-pr-quality.yaml`](./on-pr-quality.yaml) | entry | **This repo** PR gate (not the consumer quality contract) |
| [`on-push-main-version-and-tag.yaml`](./on-push-main-version-and-tag.yaml) | entry | **This repo** main → **vnext** tag |
Expand Down
50 changes: 38 additions & 12 deletions .github/workflows/integration-celld.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ name: celld (live + e2e-celld)
# make -C tests/e2e-celld test
# make -C tests/e2e-ui up && make -C tests/e2e-ui up-celld-nats
# WATCH=0 WATCH_WORKER=0 make -C tests/e2e-celld run
# E2E_UI_ORIGIN=http://localhost:8791 npx --prefix tests/e2e-ui playwright test \
# todos.user.spec.ts chat.user.spec.ts --project chromium-user
# make -C tests/e2e-celld test-browser # the full Playwright suite
#
# Default `cargo test` (quality) still runs fixture-only celld checks and
# skips live HTTP unless CELLD_URL is set. This job sets CELLD_URL / NATS_URL.
Expand Down Expand Up @@ -39,7 +38,10 @@ jobs:
targets: wasm32-unknown-unknown
- uses: Swatinem/rust-cache@v2
with:
workspaces: tests/celld/worker -> tests/celld/worker/target
workspaces: |
tests/celld/worker -> tests/celld/worker/target
tests/celld/alarm-worker -> tests/celld/alarm-worker/target
tests/celld/fact-worker -> tests/celld/fact-worker/target
shared-key: celld-storage
- uses: actions/setup-node@v4
with:
Expand All @@ -49,13 +51,37 @@ jobs:
sudo apt-get update && sudo apt-get install -y sqlite3
npm install -g esbuild
cargo install worker-build --locked
curl -fsSL https://celld.dev/install.sh | sh
# The pinned celld (/.celld-version) is the one the zone-state R2
# path, fact routing and every profile below are proven on.
scripts/celld.sh install
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
- name: Build isolated fault-probe Worker
working-directory: tests/celld/worker
run: worker-build --release --features storage-conformance
- name: Prove SQL atomicity, fencing, autonomous recovery and growth
run: node tests/celld/storage-conformance.mjs
- name: Build the cell-alarm Ticker Worker
working-directory: tests/celld/alarm-worker
run: worker-build --release
- name: Prove re-armable cell alarms (atomic arm, cadence, watchdog, restart)
run: node tests/celld/alarms.mjs
- name: Build the zone-fact cells Worker
working-directory: tests/celld/fact-worker
run: worker-build --release
- name: Route zone facts to celld cells (CelldFactSink, outage and restart)
env:
CELLD_FACTS_REQUIRED: "1"
run: cargo test -p distributed_game --features celld,runtime --test celld_facts
- name: Zone leases in celld cells (CellZoneOwnership, alarm expiry, GameServer)
env:
CELLD_FACTS_REQUIRED: "1"
run: cargo test -p distributed_game --features celld,runtime,net --test celld_zone_lease
- name: Zone hibernation state in celld cells (inline + R2 snapshots, crash, GameServer)
env:
CELLD_FACTS_REQUIRED: "1"
run: |
cargo test -p distributed_game --features celld,runtime --test celld_zone_state
cargo test -p distributed_game --features celld,net,lease --test world
- name: Retain storage proof results and logs
if: always()
uses: actions/upload-artifact@v4
Expand All @@ -64,6 +90,8 @@ jobs:
path: |
/tmp/distributed-cell-storage-*/results.json
/tmp/distributed-cell-storage-*/celld-*.log
/tmp/distributed-cell-alarms-*/results.json
/tmp/distributed-cell-alarms-*/celld-*.log
if-no-files-found: ignore

e2e-celld:
Expand All @@ -87,7 +115,7 @@ jobs:
run: cargo test --workspace --verbose

live:
name: celld 0.4 live (local store + Queue + NATS)
name: celld live (local store + Queue + NATS)
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
Expand Down Expand Up @@ -126,9 +154,9 @@ jobs:
- name: Install worker-build
run: cargo install worker-build --locked || cargo install worker-build

- name: Install celld CLI
- name: Install celld CLI (pinned in /.celld-version)
run: |
curl -fsSL https://celld.dev/install.sh | sh
scripts/celld.sh install
echo "$HOME/.local/bin" >> "$GITHUB_PATH"

- name: Bring up Postgres + Zitadel and bootstrap OIDC
Expand All @@ -155,7 +183,7 @@ jobs:
working-directory: tests/e2e-ui
run: npx playwright install chromium --with-deps

- name: Bring up celld 0.4 + Queue relay + NATS
- name: Bring up celld + Queue relay + NATS
run: |
command -v celld
command -v worker-build
Expand Down Expand Up @@ -266,11 +294,9 @@ jobs:
-H "x-distributed-internal-secret: $DISTRIBUTED_INTERNAL_SECRET" \
-d '{"ids":["forged"]}'

- name: Todo + Chat browser lifecycle through celld
- name: Full Playwright suite through celld (user, admin, anon)
working-directory: tests/e2e-ui
run: >-
npx playwright test todos.user.spec.ts chat.user.spec.ts
--project chromium-user
run: npx playwright test
env:
E2E_UI_ORIGIN: http://localhost:8791
E2E_API_ORIGIN: http://127.0.0.1:8791
Expand Down
25 changes: 23 additions & 2 deletions .github/workflows/integration-game-demos.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ name: Game demos smoke
# headless tests, and the SvelteKit demo end to end: `distributed build
# examples/game/server` (GraphQL client, svelte-check, vite build), then
# Playwright against the production build, a real Mob Pit server and the real
# mobpit-service read model (SQLite only; no external services).
# mobpit-service read model. Mob Pit's durable cells run on celld: the tests
# start their own `celld dev` (CELLD_BIN, pinned in /.celld-version; no Docker) serving
# examples/game/cells, built with worker-build.
on:
workflow_call:

Expand All @@ -17,7 +19,8 @@ jobs:
runs-on: ubuntu-latest
env:
CARGO_TERM_COLOR: always
# The shared ticket rate limiter's Lua script runs against a real Redis.
# The shared ticket rate limiter's Lua script and the leaderboard store
# (conformance suite, projector, GraphQL boards) run against a real Redis.
services:
redis:
image: redis:7-alpine
Expand All @@ -43,11 +46,29 @@ jobs:
js/package-lock.json
examples/game/client/package-lock.json
examples/game/sveltekit/package-lock.json
- uses: Swatinem/rust-cache@v2
with:
workspaces: |
examples/game/server -> target
examples/game/cells -> target
shared-key: game-demos
- name: Install celld (pinned) and worker-build
run: |
scripts/celld.sh install
echo "CELLD_BIN=$HOME/.local/bin/celld" >> "$GITHUB_ENV"
cargo install worker-build --locked
- name: Install SvelteKit demo dependencies and Chromium
working-directory: examples/game/sveltekit
run: npm ci --no-audit --no-fund && npx playwright install --with-deps chromium
- name: Run examples/game smoke
env:
# The SvelteKit leaderboard is the Redis board (GraphQL board roots).
REDIS_URL: redis://127.0.0.1:6379
run: examples/game/run.sh smoke
- name: Leaderboard conformance and GraphQL boards against real Redis
env:
REDIS_URL: redis://127.0.0.1:6379
run: cargo test --features redis,graphql,sqlite --test redis_leaderboard -- --nocapture
- name: Ticket rate limiter against real Redis
working-directory: js
env:
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/integration-postgres.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ jobs:
cargo test --test distributed_read_model --no-default-features --features postgres --verbose
cargo test --test sql_lock_manager --no-default-features --features postgres --verbose
cargo test --test graphql_literal_text --no-default-features --features graphql,postgres --verbose
# Schedule worker: claim with FOR UPDATE SKIP LOCKED, crash/restart and
# concurrent workers fire each (owner, name, generation) once.
cargo test --test schedule_worker --no-default-features --features graphql,postgres --verbose
- name: Verify source fencing and snapshot rebuild against PostgreSQL
env:
DISTRIBUTED_SNAPSHOT_TEST_POSTGRES_URL: postgres://postgres:postgres@localhost:5432/distributed_snapshots
Expand Down
33 changes: 33 additions & 0 deletions .github/workflows/integration-wasm32-domains.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: wasm32 domain crates

# Reusable workflow: referenced via `uses: ./.github/workflows/integration-wasm32-domains.yaml`.
# Domain crates run inside celld cells (wasm32 Durable Objects), so each must
# build for wasm32-unknown-unknown without Tokio sockets, native SQLite or
# other native-only dependencies (game-services decision D4). The script also
# proves the check bites: tests/fixtures/wasm32-native-domain must fail.
#
# Local parity: scripts/check-wasm32-domains.sh
on:
workflow_call:

jobs:
wasm32-domains:
name: Domain crates build for wasm32-unknown-unknown
runs-on: ubuntu-latest
timeout-minutes: 30
env:
CARGO_TERM_COLOR: always
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8
with:
toolchain: stable
targets: wasm32-unknown-unknown
- uses: Swatinem/rust-cache@v2
with:
shared-key: wasm32-domains
cache-directories: target/wasm32-domains
- name: Build every domain crate for wasm32 (and reject the native fixture)
run: scripts/check-wasm32-domains.sh
10 changes: 4 additions & 6 deletions .github/workflows/on-pr-quality.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,7 @@ jobs:
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Run contracts check
run: |
if [ -f contracts/catalog.json ]; then
cargo run -p distributed_cli --quiet -- contracts check --root . --catalog contracts/catalog.json --output json
else
echo "No contracts/catalog.json yet; gate is present and ready for producers."
fi
run: cargo run -p distributed_cli --quiet -- contracts check --root . --catalog distributed.contracts.json --output json

# Framework monorepo keeps its existing quality provider. The reusable
# quality.yaml in this directory is the contract for *consumers* (domain
Expand Down Expand Up @@ -82,3 +77,6 @@ jobs:

celld:
uses: ./.github/workflows/integration-celld.yaml

wasm32-domains:
uses: ./.github/workflows/integration-wasm32-domains.yaml
5 changes: 4 additions & 1 deletion .github/workflows/on-push-main-version-and-tag.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,14 @@ jobs:
celld:
uses: ./.github/workflows/integration-celld.yaml

wasm32-domains:
uses: ./.github/workflows/integration-wasm32-domains.yaml

# This uses commit logs and tags from git to determine the next version number and create a tag for the release.
# Some commits such as chore: will not trigger a version bump and tag; this is by design.
version-and-tag:
name: Version and Tag
needs: [quality, all-features, postgres, nats, rabbitmq, kafka, distributed-cli, observability, graphql, e2e-ui, js-client, celld]
needs: [quality, all-features, postgres, nats, rabbitmq, kafka, distributed-cli, observability, graphql, e2e-ui, js-client, celld, wasm32-domains]
uses: unbounded-tech/workflow-vnext-tag/.github/workflows/workflow.yaml@v1.22.2
secrets:
DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ tests/celld/worker/build/
tests/celld/worker/.celld/
tests/celld/relay-worker/target/
tests/celld/relay-worker/build/
tests/celld/alarm-worker/target/
tests/celld/alarm-worker/build/
tests/celld/alarm-worker/.celld/
tests/celld/fact-worker/target/
tests/celld/fact-worker/build/
tests/celld/fact-worker/.celld/

# Build output of CLI test fixture crates
/distributed_cli/tests/fixtures/*/target/
11 changes: 1 addition & 10 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[workspace]
members = ["distributed_macros", "distributed_cli", "distributed_game", "distributed_game_macros"]
exclude = ["tests/e2e-ui", "tests/celld/worker", "tests/celld/relay-worker", "examples/game/server"]
exclude = ["tests/e2e-ui", "tests/celld/worker", "tests/celld/relay-worker", "tests/celld/alarm-worker", "tests/celld/fact-worker", "tests/fixtures/wasm32-native-domain", "examples/game/server"]
resolver = "2"

[workspace.package]
Expand Down Expand Up @@ -62,10 +62,6 @@ redis = ["dep:redis", "dep:tokio", "leaderboard-background"]
# task) without Redis, e.g. over `InMemoryLeaderboard`.
leaderboard-background = ["dep:tokio"]
workers-rs = ["dep:worker"]
# Native durable aggregate cells: one synchronous SQLite file per cell, same
# SQL store and one-transaction-per-command contract as Durable Object cells.
# Separate from `sqlite` (async SQLx pool + tokio); no-op on wasm32.
cell-sqlite = ["dep:rusqlite"]
otel = ["dep:opentelemetry", "dep:opentelemetry_sdk", "dep:tracing", "dep:tracing-opentelemetry"]
graphql = ["dep:async-graphql", "dep:async-graphql-axum", "dep:hmac", "dep:jsonwebtoken", "http", "axum?/ws"]

Expand Down Expand Up @@ -109,11 +105,6 @@ uuid = { version = "1", features = ["v7"] }
url = { version = "2", optional = true }
worker = { version = "0.8", features = ["queue"], optional = true }

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
# libsqlite3-sys 0.37 stays inside SQLx 0.9's accepted range, so `sqlite` and
# `cell-sqlite` link one bundled SQLite when enabled together.
rusqlite = { version = "0.39", features = ["bundled"], optional = true }

[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies]
js-sys = "0.3"
uuid = { version = "1", features = ["v7", "js"] }
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,4 @@ compose-down:

## Read-only aggregate contract lifecycle check (never writes tracked files).
contracts-check:
$(CARGO) run -p distributed_cli --quiet -- contracts check --root . --catalog contracts/catalog.json --output human
$(CARGO) run -p distributed_cli --quiet -- contracts check --root . --catalog distributed.contracts.json --output human
Loading
Loading