Files
wehub-resource-sync 426e9eeabd
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Waiting to run
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Waiting to run
Build Agent Image / build-and-push (push) Waiting to run
Chat shell gestures / Chat shell gesture + parity e2e (push) Waiting to run
ci / test (push) Waiting to run
ci / lint-and-format (push) Waiting to run
ci / build (push) Waiting to run
ci / dev-startup (push) Waiting to run
Cloud Gateway Discord / Test (push) Waiting to run
Cloud Gateway Webhook / Test (push) Waiting to run
Cloud Tests / lint-and-types (push) Waiting to run
Cloud Tests / unit-tests (push) Waiting to run
Cloud Tests / integration-tests (push) Waiting to run
Cloud Tests / e2e-tests (push) Blocked by required conditions
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Deploy Apps Worker (Product 2) / Determine environment (push) Waiting to run
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Blocked by required conditions
Deploy Eliza Provisioning Worker / Determine environment (push) Waiting to run
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Blocked by required conditions
Dev Smoke / Classify changed paths (push) Waiting to run
Dev Smoke / bun run dev onboarding chat (push) Blocked by required conditions
Dev Smoke / Vite HMR dependency-level smoke (push) Blocked by required conditions
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Waiting to run
gitleaks / gitleaks (push) Waiting to run
Markdown Links / Relative Markdown Links (push) Waiting to run
Publish @elizaos/example-code / check_npm (push) Waiting to run
Publish @elizaos/example-code / publish_npm (push) Blocked by required conditions
Publish @elizaos/plugin-elizacloud / verify_version (push) Waiting to run
Publish @elizaos/plugin-elizacloud / publish_npm (push) Blocked by required conditions
Quality (Extended) / Homepage Build (PR smoke) (push) Waiting to run
Quality (Extended) / Comment-only diff guard (push) Waiting to run
Quality (Extended) / Format + Type Safety Ratchet (push) Waiting to run
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Waiting to run
Quality (Extended) / Develop Gate (lint) (push) Waiting to run
Sandbox Live Smoke / Sandbox live smoke (push) Waiting to run
Snap Build & Test / Build Snap (amd64) (push) Waiting to run
Snap Build & Test / Build Snap (arm64) (push) Waiting to run
supply-chain / sbom (push) Waiting to run
supply-chain / vulnerability-scan (push) Waiting to run
Build, Push & Deploy to Phala Cloud / build-and-push (push) Waiting to run
Test Packaging / Validate Packaging Configs (push) Waiting to run
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Waiting to run
Test Packaging / Pack & Test JS Tarballs (push) Waiting to run
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Waiting to run
UI Fixture E2E / ui-fixture-e2e (push) Waiting to run
UI Fixture E2E / fixture-e2e (push) Waiting to run
UI Story Gate / story-gate (push) Waiting to run
vault-ci / test (macos-latest) (push) Waiting to run
vault-ci / test (ubuntu-latest) (push) Waiting to run
vault-ci / test (windows-latest) (push) Waiting to run
vault-ci / app-core wiring tests (push) Waiting to run
verify-patches / verify patches/CHECKSUMS.sha256 (push) Waiting to run
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Waiting to run
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Waiting to run
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Waiting to run
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Waiting to run
Voice Benchmark Smoke / voice bench smoke summary (push) Blocked by required conditions
Windows CI / windows ([bun run --cwd packages/app-core test bun run --cwd packages/elizaos test bun run --cwd packages/cloud/shared test], app-and-cli) (push) Waiting to run
Windows CI / windows ([bun run --cwd packages/scenario-runner test bun run --cwd packages/vault test bun run --cwd packages/security test bun run --cwd plugins/plugin-coding-tools test], framework-packages) (push) Waiting to run
Windows CI / windows ([bun run --cwd plugins/plugin-elizacloud test bun run --cwd plugins/plugin-discord test bun run --cwd plugins/plugin-anthropic test bun run --cwd plugins/plugin-openai test bun run --cwd plugins/plugin-app-control test bun run --cwd plugins/pl… (push) Waiting to run
Windows CI / windows ([node packages/scripts/run-turbo.mjs run build --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/agent --concurrency=4 node packages/scripts/run-bash-linux-only.mjs scripts/verify-riscv64-buildpaths.sh node packages/scripts/run… (push) Waiting to run
Windows CI / windows ([node packages/scripts/run-turbo.mjs run typecheck --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/cloud-shared --concurrency=4 bun run --cwd packages/core test bun run --cwd packages/shared test], core-runtime, 75) (push) Waiting to run
Test Packaging / Build & Test PyPI Package (push) Waiting to run
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:43:05 +08:00

7.8 KiB
Raw Permalink Blame History

Single-machine parallel certification

Runs the entire certification stack (epic #14541, this piece #14549) on one beefy Linux box in reasonable wall-clock: container-parallel CPU test lanes plus pipelined GPU vision work. macOS certifiers keep the native path (bun run test + scripts/gpu-vision/serve.mjs) — compose is the Linux/vast lane; the orchestrator only cares that lanes report and the queue drains.

Quick start (Linux, docker + compose v2, NVIDIA container toolkit)

# cpu tier: all test lanes containerized, per-lane timings collected
node docker/certification/certify-parallel.mjs

# full tier: cpu lanes + resident GPU vision service + queue worker
node docker/certification/certify-parallel.mjs --tier full

# knobs (also accepted by the generator)
node docker/certification/certify-parallel.mjs --cores 32 --unit-shards 6 --e2e-shards 3

certify-parallel.mjs writes timings.json beside this file: per-lane exit codes, ISO start/finish stamps, and a flat timings record (Record<phase, milliseconds>) that packages/evidence can merge verbatim into BundleMeta.timings.

Where the lane list comes from (there is no second registry)

generate-compose-lanes.mjs derives the cpu-profile services from node packages/scripts/run-all-tests.mjs --plan=json --all — the test runner's own plan:

  • each distinct scriptName in summary.byScript becomes a lane (testunit, test:e2ee2e, test:uiui, …); a package adding a brand-new test script surfaces as a new lane on regeneration, with zero edits here;
  • the big groups are split with the runner's own TEST_SHARD=N/M (deterministic package-dir hashing), so shard membership is never listed in the compose file;
  • the plan's cloudStep becomes the cloud lane (bun run test:cloud), which is why every other lane can pass --no-cloud without losing coverage.

compose.yml is generated-then-committed. The drift gate (generate-compose-lanes.mjs --check, enforced by compose-lanes.test.mjs) fails when the committed file no longer matches regeneration — regenerate and commit, never hand-edit.

Cores → lane mapping

Defaults (cores=16 unit-shards=4 e2e-shards=2) produce 10 lanes; cpusets are contiguous, remainder cores go to the earliest (heaviest) lanes:

Lane cpuset cpus runs
unit-1of4 0-1 2 TEST_SCRIPT_FILTER=^test$ TEST_SHARD=1/4
unit-2of4 2-3 2 shard 2/4
unit-3of4 4-5 2 shard 3/4
unit-4of4 6-7 2 shard 4/4
e2e-1of2 8-9 2 TEST_SCRIPT_FILTER=^test:e2e$ 1/2
e2e-2of2 10-11 2 shard 2/2
integration 12 1 ^test:integration$
live 13 1 ^test:live$ (pr lane → guarded skips)
ui 14 1 ^test:ui$
cloud 15 1 bun run test:cloud

Sizing guidance: ~1 lane per 1.52 physical cores. 32 cores → --cores 32 --unit-shards 6 --e2e-shards 3 is a good starting point; more than ~8 unit shards hits diminishing returns because bun install + build:core dominate short shards. Memory: budget ~4 GiB per unit/e2e lane (vitest + browsers), ~8 GiB for cloud.

Each lane gets the repo read-only at /repo, syncs it into its private scratch-lane-* volume (incremental after the first run), installs through the shared build-cache volume (BUN_INSTALL_CACHE_DIR=/cache/bun), and runs its lane command via lane-entry.sh.

GPU profile: one service owns the device

capture lanes ──(job files)──▶ queue/pending ──▶ gpu-queue-worker ──HTTP──▶ gpu-vision
                                                       │                    (both llama-servers)
                                                       └──▶ queue/results/<id>.json
  • Doctrine: containers do NOT share the GPU; they share the GPU service over HTTP. Exactly one container (gpu-vision) reserves the device and runs both resident llama-server instances (gpu-entry.sh); lanes and the worker talk to http://gpu-vision:8090 (Unlimited-OCR) and :8091 (Qwen3-VL) with --parallel N slots each.

  • VRAM budget ~610 GiB at Q4 (fits a single RTX 4090-class card with headroom; both models resident, from scripts/gpu-vision/models.lock.json):

    Blob Bytes
    Unlimited-OCR Q4_K_M ~1.95 GiB
    Unlimited-OCR mmproj F16 ~0.81 GiB
    Qwen3-VL-4B Q4_K_M ~2.50 GiB
    Qwen3-VL mmproj F16 ~0.84 GiB
    KV cache + compute (2× serve) ~14 GiB
  • MPS is the escape hatch, not the default. The two llama-server processes in the one gpu-vision container time-slice the device, which is fine for a drain-the-queue workload. If kernel-level concurrency between resident processes ever becomes the bottleneck, enable NVIDIA MPS on the host — do not hand the device to more containers. MIG is N/A on consumer cards.

  • Models mount read-only from ${ELIZA_GPU_MODELS_DIR:-~/.cache/eliza/gpu-vision} — populate with node scripts/gpu-vision/setup.mjs --with-vlm (hash-pinned).

Pipelined queue (filesystem, no redis)

Producers drop { id?, model: "ocr"|"vlm", request, imagePath? } JSON into queue/pending/ (enqueueJob() from queue-worker.mjs does this atomically with max-pending backpressure). The worker claims by rename, POSTs request to the model's /v1/chat/completions (inlining imagePath as a data URI at the queue:image placeholder), and writes queue/results/<id>.jsonok (with response + duration), failed (with reason), or skipped. Analysis therefore finishes shortly after the last capture instead of serializing behind it.

Degradation is explicit: while the service is unreachable jobs bounce back to pending and retry; past --drain-after-ms (default 120 s) the worker drains every pending job to an honest skipped record naming the outage. All state transitions are pure functions in queue-lib.mjs with unit tests.

Exit codes (certify-parallel.mjs)

Code Meaning
0 all lanes exited 0 (and queue drained at --tier full)
1 one or more lanes failed (timings.json still written)
4 EXIT_NO_DOCKER — serial native fallback printed, nothing ran
5 EXIT_DRIFT — committed compose.yml stale vs the live plan
6 EXIT_TIMEOUT--timeout-min elapsed with lanes still running

Image

Services reference ghcr.io/elizaos/certification-gpu (override with ELIZA_CERT_IMAGE / ELIZA_CERT_GPU_IMAGE), the prebuilt CUDA + bun + node + playwright + llama-server image owned by the vast.ai runner work (#14548) — this directory consumes that image and never defines a competing Dockerfile. Lane containers additionally expect rsync and git; lane-entry.sh falls back to a slow full copy and says so if rsync is absent.

Tests

bun test docker/certification (outside workspace discovery; CI runs it as an explicit step): generator drift, plan→lane derivation, cpuset math, YAML/ docker compose config validation, queue state machine, real worker process against a stub HTTP service (success/failure/backpressure/drain-to-skip), and orchestrator degradation (no docker → exit 4). The full containerized run is the owner-gated on-Linux acceptance for #14549.