diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 0494bcee9..cd7fd4ba4 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -223,34 +223,29 @@ jobs:
name: ${{ github.event_name == 'workflow_dispatch' && inputs.evidence_json != '' && 'evidence-dispatch-idle-public-surface' || 'public-surface' }}
if: ${{ github.event_name != 'workflow_dispatch' || inputs.evidence_json == '' }}
runs-on: ubuntu-latest
- defaults:
- run:
- shell: bash -el {0}
-
steps:
- name: Checkout
uses: actions/checkout@v5
- - name: Set up Miniconda
- uses: conda-incubator/setup-miniconda@v3
+ - name: Set up Python
+ uses: actions/setup-python@v6
with:
- auto-update-conda: true
- activate-environment: worldfoundry-ci
- auto-activate-base: false
+ python-version: "3.11"
- name: Set up Node
uses: actions/setup-node@v5
with:
+ node-version-file: docs/fumadocs/.nvmrc
cache: npm
cache-dependency-path: docs/fumadocs/package-lock.json
- - name: Build docs
- run: bash scripts/docs/build.sh --skip-bootstrap
-
- name: Install quality gate dependencies
run: |
python -m pip install --upgrade pip
- python -m pip install PyYAML "ruff==0.12.7"
+ python -m pip install -e . "ruff==0.12.7"
+
+ - name: Build docs
+ run: bash scripts/docs/build.sh
- name: Check generated docs
run: make docs-check
diff --git a/.gitignore b/.gitignore
index b46c26657..93cf3ab78 100644
--- a/.gitignore
+++ b/.gitignore
@@ -390,7 +390,10 @@ worldfoundry/studio/assets/vendor/
/plan/
/memory/
/configs/
-/benchmarks/
+/benchmarks/*
+!/benchmarks/inference/
+/benchmarks/inference/*
+!/benchmarks/inference/wan_execution_preparation.py
/gg
# Public branch: keep private training and embedded upstream QA out of commits.
@@ -988,6 +991,7 @@ worldfoundry/studio/assets/vendor/
/tests/**
!/tests/**/
!/tests/**/*.py
+!/tests/**/*.mjs
!/tests/**/*.md
!/tests/**/*.sh
!/tests/**/*.yaml
diff --git a/MANIFEST.in b/MANIFEST.in
index 123edfb58..950f54c09 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,4 +1,9 @@
include .pre-commit-config.yaml
+include LICENSE
+include CODE_OF_CONDUCT.md
+include CONTRIBUTING.md
+recursive-include skills *.md
+include SECURITY.md
include THIRD-PARTY-NOTICES
include worldfoundry/synthesis/visual_generation/dino_wm/datasets/UPSTREAM.md
include worldfoundry/synthesis/visual_generation/egowm/nav_25dof_stats.json
@@ -86,13 +91,10 @@ prune worldfoundry/synthesis/visual_generation/wonderworld/wonderworld_runtime
prune thirdparty/diff-gaussian-rasterization
prune thirdparty/SageAttention
prune thirdparty/simple-knn
+prune thirdparty/matrix-game
# Upstream runtime mirrors should ship source code, not demo galleries, notebooks,
# eval question dumps, or bundled sample media.
-prune worldfoundry/synthesis/visual_generation/pandora/pandora_runtime/ChatUniVi/eval
-prune worldfoundry/synthesis/visual_generation/pandora/pandora_runtime/ChatUniVi/train
-prune worldfoundry/synthesis/visual_generation/dynamicrafter_pandora/DynamiCrafter/assets
-prune worldfoundry/synthesis/visual_generation/dynamicrafter_pandora/DynamiCrafter/prompts
global-exclude __pycache__
global-exclude *.py[cod]
global-exclude .DS_Store
@@ -121,11 +123,13 @@ global-exclude test_*.py *_test.py test_*.cpp *_test.cpp
# Publish first-party test sources and fixtures in sdists, after the upstream
# QA exclusions above. Wheels continue to contain only worldfoundry packages.
-recursive-include tests *.py *.md *.sh *.yaml *.yml *.json *.jsonl
+recursive-include tests *.py *.mjs *.md *.sh *.yaml *.yml *.json *.jsonl
include docs/fumadocs/public/measurements/mg2-conditioned-trajectory-2026-10-03.json
# First-party packaging helper exercised by the published license tests.
include thirdparty/fastvideo-kernel/build_backend.py
include .github/workflows/ci.yml
+include .github/workflows/pr-checks.yml
+recursive-include scripts/dev *.py
include Makefile scripts/setup/check_packaging_license_gate.py
global-exclude */__pycache__/* */.pytest_cache/* */.mypy_cache/* */.ruff_cache/*
global-exclude */tmp/* */temp/* */logs/* */outputs/* .env* *.py[cod]
diff --git a/README.md b/README.md
index 75863d6af..d677a216f 100644
--- a/README.md
+++ b/README.md
@@ -1,19 +1,21 @@
# WorldFoundry
[](pyproject.toml)
-[](THIRD-PARTY-NOTICES)
-[](https://openenvision.github.io/WorldFoundry/docs/reference/cli)
+[](LICENSE)
+[](https://github.com/OpenEnvision/WorldFoundry/actions/workflows/ci.yml)
[](https://openenvision.github.io/WorldFoundry/docs)
-WorldFoundry is an open-source infrastructure for world models: a shared stack for in-tree runners, local asset staging, inference (TUI / CLI / Studio), and benchmark evaluation across video generation, 3D/4D representation, embodied action, and interactive worlds.
+[Documentation](https://openenvision.github.io/WorldFoundry/docs) · [中文文档](https://openenvision.github.io/WorldFoundry/zh/docs) · [Contributing](CONTRIBUTING.md)
-> ⚠️ This repository is still under active development. We will keep updating it regularly. Feel free to open an issue if you encounter any problem.
+WorldFoundry is an open-source framework for world-model inference and evaluation.
+It brings video generation, interactive worlds, 3D/4D reconstruction, and embodied action into a shared workflow.
-Day-one workflow:
+
+
+## 📰 News
-1. **Environment + assets** — bootstrap conda, stage checkpoints and datasets outside git.
-2. **Inference** — generate and inspect artifacts via TUI, CLI, scripts, or Studio.
-3. **Evaluation** — score only after artifacts match the benchmark layout; use scorecards for readiness claims.
+- **[2026-07-12]** 🔥 **WorldFoundry reached 100+ stars on its very first day!** Thanks to the community for the incredible support and encouragement. More exciting updates are coming!
+- **[2026-07-11]** 🎉 **WorldFoundry is officially open-sourced.** We welcome ⭐ stars, bug reports, feature requests, and pull requests from the community!
## 🤝 Community
@@ -53,394 +55,84 @@ Join the **WorldFoundry Community** on Slack, [Discord](https://discord.gg/ybUQM
QR codes are updated periodically if they expire.
-## 📰 News
+## Highlights
-- **[2026-07-12]** 🔥 **WorldFoundry reached 100+ stars on its very first day!** Thanks to the community for the incredible support and encouragement. More exciting updates are coming!
-- **[2026-07-11]** 🎉 **WorldFoundry is officially open-sourced.** We welcome ⭐ stars, bug reports, feature requests, and pull requests from the community!
+- **Model and benchmark catalogs** — discover models, checkpoint sources, runtime requirements, and benchmark protocols.
+- **Unified inference** — run in-tree pipelines through the CLI, terminal UI, or browser-based Studio.
+- **Artifact inspection** — review job status, generated media, and geometry through Studio and its visualizers.
+- **Benchmark evaluation** — run model × benchmark cells and inspect normalized metrics, readiness, and eligibility scorecards.
+## System Requirements
-
+- **Platform:** Linux with an NVIDIA CUDA-capable GPU.
+- **Driver:** CUDA 12.8+ support for the default unified environment.
+- **GPU architecture / VRAM:** model-specific; check the selected model's page.
+- **Tools:** Git and Conda.
-## What WorldFoundry Provides
+Inference, Studio, evaluation, and development use the same unified CUDA environment.
+Model-specific environments for ABI or simulator requirements are documented in the
+[environment guide](https://openenvision.github.io/WorldFoundry/docs/reference/environments).
-| Surface | Purpose | Entry point |
-| --- | --- | --- |
-| Model zoo | Catalogs video, world, 3D/4D, VLA/VA/WAM, hosted API, and metadata-only model entries. | [`worldfoundry/data/models/catalog`](worldfoundry/data/models/catalog) |
-| In-tree runtimes | Keeps model architecture and inference adapters inside `worldfoundry`; checkpoints stay in local/Hugging Face caches. | [`worldfoundry/synthesis`](worldfoundry/synthesis), [`worldfoundry/pipelines`](worldfoundry/pipelines) |
-| TUI | Interactive model/benchmark picker that prints runnable CLI commands. | `worldfoundry-eval tui` / `worldfoundry-tui` |
-| Studio workspace | Browser UI for inference jobs, model-specific parameters, and artifact review. | [`worldfoundry.studio.serving.workspace`](worldfoundry/studio/serving/workspace.py) |
-| Benchmark zoo | Catalogs benchmark manifests, required assets, official runner constraints, and readiness states. | [`worldfoundry/data/benchmarks/catalog`](worldfoundry/data/benchmarks/catalog) |
-| Evaluation runner | Runs model × benchmark cells, imports existing outputs, and writes normalized scorecards. | [`worldfoundry/evaluation`](worldfoundry/evaluation) |
-| Tests | Public CPU inference gate and extended module suites. | [`tests`](tests), [test guide](docs/fumadocs/content/docs/reference/validation.mdx) |
-| Docs | Bilingual Fumadocs site with setup, inference, evaluation, Studio, and maintainer guides. | [`docs/fumadocs`](docs/fumadocs) |
+## Quickstart
-## From Clone To First Run
-
-Choose the install track that matches the work you are doing:
-
-| Track | Use it for | Install |
-| --- | --- | --- |
-| **Lightweight / CPU** | Catalog and CLI inspection, TUI use, docs work, and CPU release checks | An editable pip install with only the required extras, for example `python -m pip install -e ".[tui]"` |
-| **GPU runtime** | CUDA inference, Studio model execution, and GPU-backed benchmark runners | `bash scripts/setup/bootstrap_worldfoundry.sh` |
-
-Optional extras declare Python dependencies but do not select a CUDA-specific
-PyTorch wheel index. Do not treat a bare pip install of a GPU-coupled extra as
-the supported CUDA setup; use the bootstrap/conda track instead. Optional native
-kernels must be built inside the exact target PyTorch environment.
-
-For GPU work, start with the unified environment and use a dedicated
-environment only when a model profile documents an ABI or simulator conflict.
-The full day-one path lives in the
-[Quickstart](https://openenvision.github.io/WorldFoundry/docs/quickstart).
-
-Model demo videos are served from GitHub CDN; docs development does not need `git lfs pull`.
+Clone the repository, create the GPU environment, and launch Studio:
```bash
-# Recommended: skip LFS smudge for a much faster clone
GIT_LFS_SKIP_SMUDGE=1 git clone https://github.com/OpenEnvision/WorldFoundry.git
-
cd WorldFoundry
bash scripts/setup/bootstrap_worldfoundry.sh
source tmp/worldfoundry_unified_env.sh
conda activate "${WORLDFOUNDRY_UNIFIED_ENV_PREFIX}"
-```
-
-To download local demo video binaries later, install Git LFS and run `git lfs pull` inside the clone.
-
-Checkpoints, datasets, evaluator weights, API keys, and generated artifacts are **not** in git.
-See [Local asset preparation](https://openenvision.github.io/WorldFoundry/docs/guides/local-assets) for cache layout, Hugging Face downloads, non-HF aliases, and benchmark assets.
-
-On modern CUDA 12.8 hosts the installer resolves `worldfoundry-unified-cu128`. Pin a wheel tier only when the host requires it:
-
-```bash
-bash scripts/setup/bootstrap_worldfoundry.sh --cuda cu124
-bash scripts/setup/bootstrap_worldfoundry.sh --cuda cu121
-```
-
-Keep datasets and checkpoints outside the repository on shared machines:
-
-```bash
-bash scripts/setup/bootstrap_worldfoundry.sh \
- --home /path/to/worldfoundry-home \
- --data-root /path/to/worldfoundry-data \
- --model-root /path/to/worldfoundry-models \
- --artifact-root /path/to/worldfoundry-artifacts
-```
-
-Hugging Face models use native Hub loading (`from_pretrained`, `snapshot_download`, `HF_HOME` / `HF_HUB_CACHE`, and `HF_TOKEN` for gated assets). `WORLDFOUNDRY_CKPT_DIR` remains for non-HF checkpoints and compatibility aliases.
-
-Some VLA/action policies need a documented model-specific environment (for example OpenVLA-OFT / CogACT). Embodied simulator benchmarks follow the Docker VLA harness pattern — see the [environment reference](https://openenvision.github.io/WorldFoundry/docs/reference/environments).
-
-After the environment is active:
-
-```bash
-worldfoundry-eval --help
-worldfoundry-eval zoo models --json
-worldfoundry-eval zoo benchmarks --json
-```
-
-### Interactive first path (TUI)
-
-```bash
-python -m pip install -e ".[tui]"
-worldfoundry-eval tui
-# or: worldfoundry-tui
-```
-
-The TUI reads the same catalogs as the CLI and can print a runnable command before anything expensive runs:
-
-```bash
-worldfoundry-eval tui \
- --model-id \
- --benchmark-id \
- --print-command
-```
-
-### Scripted first model run
-
-Prepare assets, then launch a small demo. A common starter is `matrix-game-2` (public HF repo `Skywork/Matrix-Game-2.0`):
-
-```bash
-bash scripts/inference/prepare_model_infer.sh matrix-game-2 --download
-worldfoundry-eval zoo model-download --model-id matrix-game-2 --check-local --json
-
-bash scripts/inference/run_infer.sh --category navigation-video --model matrix-game-2 \
- --output-dir tmp/matrix_game2_first_run
-```
-
-If weights already live in a shared checkpoint tree, link them instead of copying:
-
-```bash
-bash scripts/setup/link_hf_checkpoints.sh \
- --ckpt-dir "${WORLDFOUNDRY_CKPT_DIR}" \
- --hfd-root "${WORLDFOUNDRY_HFD_ROOT}" \
- --hf-hub-cache "${HF_HUB_CACHE}" \
- --default-world
-```
-
-## Run Inference
-
-Prefer the TUI or the documented inference helpers once assets are staged:
-
-```bash
-bash scripts/inference/run_infer.sh --category navigation-video --model matrix-game-2
-
-conda run -p "${WORLDFOUNDRY_UNIFIED_ENV_PREFIX}" \
- bash scripts/inference/run_infer.sh --category navigation-video --model matrix-game-2
-
-bash scripts/inference/run_infer.sh --category video --model
-bash scripts/inference/run_infer.sh --category three_d_four_d --model
-```
-
-CLI-shaped inference (same contract as Studio jobs):
-
-```bash
-python -m worldfoundry.studio.workspace_job infer \
- --model-id \
- --prompt "a cinematic scene, high quality" \
- --output-dir tmp/worldfoundry_infer/ \
- --device cuda
-```
-
-Each successful run should write media, logs, and manifest metadata under the output directory. Treat a file as demo evidence only after visual check and matching runtime-profile assumptions. Details: [Inference guide](https://openenvision.github.io/WorldFoundry/docs/guides/inference).
-
-### Opt-in inference acceleration
-
-Acceleration is request-scoped. Pipelines record the requested backend, the effective backend, and any fallback. The exact path stays the default. The [inference optimization truth matrix](docs/fumadocs/content/docs/guides/inference-optimization.mdx) shows which options have a CPU contract or GPU certification, and which remain pending or rejected.
-
-The following example shows available controls, not a certified combination. Check model-specific compatibility and quality gates before enabling approximate options.
-
-```python
-from worldfoundry.pipelines.wan.pipeline_wan_2p2 import Wan2p2Pipeline
-
-pipe = Wan2p2Pipeline.from_pretrained(
- model_path="/checkpoints/wan22",
- device="cuda",
- offload_mode="resident", # aliases: fast/none; async-block when VRAM is tight
- attention_backend="flash2", # flash2/flash3/sage/sage3/xformers
- quantization={"mode": "fp8"}, # runtime report proves kernel vs dense fallback
- fuse_qkv=True,
- fused_rope=True,
- static_cross_kv=True,
- torch_compile=True,
- teacache=True, # lossy and explicit
- vae_decode_autocast="bf16",
- vae_spatial_tiling=True,
- vae_temporal_chunk_size=4,
-)
-```
-
-**Acceleration options and checks**
-
-- FlashAttention and xFormers are intended as numerically equivalent providers; check the effective backend in the run report.
-- SageAttention, FP8/NVFP4, STA/VSA/VMoBA, pinned LightX2V sparse lanes, TeaCache, and token pruning are approximate. They must pass the target model's quality budget.
-- Missing packages, unsupported GPUs, or unsupported shapes either fall back to a reported exact path or fail closed.
-- Wan2.2 TI2V-5B uses the resident preset by default in Studio on the target H100 path. `block` / `async-block` overlaps the next layer's H2D copy with compute, and is effective only with async copies, no synchronous rescue copies, and at most two CUDA-resident layers.
-- Quantization plus block offload is rejected. Use resident quantization or dense async offload.
-
-**Check a run before citing a speedup**
-
-```bash
-# Sequence-parallel reference, then the multi-rank candidate.
-torchrun --nproc_per_node=1 -m benchmarks.inference.wan22_multigpu_e2e \
- --checkpoint /checkpoints/Wan2.2-TI2V-5B \
- --output-dir benchmarks/results/wan22-sp1 \
- --fused-rope --rope-precision fp64 \
- --save-reference-latents \
- --warmup-runs 1 --measured-runs 3
-
-torchrun --nproc_per_node=4 -m benchmarks.inference.wan22_multigpu_e2e \
- --checkpoint /checkpoints/Wan2.2-TI2V-5B \
- --output-dir benchmarks/results/wan22-sp4 \
- --sp-degree 4 \
- --fused-rope --rope-precision fp64 \
- --warmup-runs 1 --measured-runs 3 \
- --reference-latents benchmarks/results/wan22-sp1/final-latents.pt \
- --reference-video benchmarks/results/wan22-sp1/output.mp4 \
- --fail-on-fallback --profile-collectives
-
-# Adapter overhead must stay within 3% of the direct provider.
-python -m benchmarks.operators.attention_adapter_parity \
- --backend flash2 --strict --out benchmarks/results
-```
-
-The checked-in VMoBA profile is only valid for the default TI2V grid `(31, 22, 40)`. Other frame or spatial shapes need a retuned profile; bad geometry fails closed. Framework A/B numbers need schema v4 on one physical GPU in `Exclusive_Process` mode. Shared H100s in `Default` mode fail that gate, so current timings stay diagnostic. Gate details live in the truth matrix linked above.
-
-## Launch Studio Workspace
-
-Studio is the preferred UI for release validation: model-specific forms, job status, preview media, and artifact links in one place. Start it from the same unified env used for inference:
-
-```bash
-source tmp/worldfoundry_unified_env.sh
-conda activate "${WORLDFOUNDRY_UNIFIED_ENV_PREFIX}"
-
-bash scripts/workspace/run_workspace.sh \
- --host 127.0.0.1 \
- --port 7870 \
- --max-jobs 8
-```
-
-Open `http://127.0.0.1:7870/`. If `python`, **LOAD**, or **START** fails with a missing interpreter, `cv2`, or `libssl`/`libcrypto` error, recreate or verify the env and restart:
-
-```bash
-bash scripts/setup/bootstrap_worldfoundry.sh --verify-only
-source tmp/worldfoundry_unified_env.sh
-bash scripts/workspace/run_workspace.sh
-```
-
-Configure jobs in **Create Job**; optional shared defaults can use `WORLDFOUNDRY_STUDIO_SETTINGS_FILE`. Expensive runtime checks and preview builders are opt-in via `WORLDFOUNDRY_STUDIO_*` — see the [Studio guide](https://openenvision.github.io/WorldFoundry/docs/guides/studio).
-
-Use the **Visualizers** tab as the browser entrypoint for local preview services (World realtime, Spark, Viser, Rerun, Embodied bridge). On a remote machine, forward port `7870` plus any viewer ports you launch.
-
-For a single-model Studio process:
-
-```bash
-worldfoundry-studio
-```
-
-## Run Evaluation
-
-Run evaluation through a runnable benchmark path. Use `official-run` when the evaluator can execute locally; use `official-validation` when you already have official-shaped result files to import.
-
-```bash
-worldfoundry-eval run \
- --model matrix-game-2 \
- --benchmark vbench \
- --mode official-run \
- --output-dir tmp/hello_world_run \
- --json
-```
-
-Inspect:
-
-- `run_manifest.json`: selected model, benchmark/task metadata, timestamps, and output paths.
-- `results.jsonl`: per-sample generation records and artifact metadata.
-- `metrics/summary.json`: aggregate metrics and failed/skipped sample counts.
-- `scorecard.json`: readiness, leaderboard eligibility, metric values, and blockers.
-
-For model and benchmark discovery:
-```bash
-worldfoundry-eval tasks list
-worldfoundry-eval zoo models --json
-worldfoundry-eval zoo benchmarks --json
-worldfoundry-eval zoo model-show --model-id --include-manifest --json
-worldfoundry-eval zoo benchmark-show --benchmark-id --include-spec --json
-```
-
-For existing official-shaped benchmark outputs:
-
-```bash
-worldfoundry-eval zoo benchmark-run --benchmark-id vbench --mode official-validation --official-results-path --generated-artifact-dir --output-dir tmp/benchmark_zoo/official_validation/vbench --json
-```
-
-For existing generated outputs:
-
-```bash
-worldfoundry-eval evaluate --results-path tmp/results.jsonl --output-dir tmp/worldfoundry_evaluate --metric artifact_count --required-artifact video --json
-```
-
-For the formal benchmark inventory, review the expanded plan first:
-
-```bash
-worldfoundry-eval prepare --all-benchmarks --output-dir tmp/worldfoundry_all_benchmarks_plan --json
-
-worldfoundry-eval run --all-benchmarks --model --prepare --data-root cache/worldfoundry/data/hfd_datasets --plan-only --output-dir tmp/worldfoundry_all_benchmarks_plan --json
-```
-
-Use the integrity commands before claiming benchmark support:
-
-```bash
-worldfoundry-eval zoo benchmarks --json
-worldfoundry-eval run --plan-only --json
+bash scripts/workspace/run_workspace.sh --host 127.0.0.1 --port 7870
```
-For release audits, use public CLI surfaces only:
+Open **http://127.0.0.1:7870/** to configure inference jobs and inspect their outputs.
+On a remote GPU machine, forward port `7870`; additional viewer ports are listed in the
+[Studio guide](https://openenvision.github.io/WorldFoundry/docs/guides/studio).
-```bash
-worldfoundry-eval validate-artifact tmp/benchmark-run/scorecard.json \
- --kind scorecard --check-artifacts --json
-```
+Checkpoints, datasets, API keys, and generated artifacts stay outside git.
+Before running a model, prepare its assets using the
+[model page](https://openenvision.github.io/WorldFoundry/docs/guides/supported-models) and
+[local asset guide](https://openenvision.github.io/WorldFoundry/docs/guides/local-assets).
-Contract runs, normalizer-only imports, partial dataset runs, and missing-official-runner checks are not leaderboard evidence. A public claim needs the full official data/runtime path and a scorecard whose eligibility fields explicitly support the claim.
+Prefer the terminal? Run `worldfoundry-eval tui` in the same environment to build a runnable command.
+The [full Quickstart](https://openenvision.github.io/WorldFoundry/docs/quickstart) walks through assets,
+inference, and evaluation.
-## Documentation Site
+## Documentation
-Run the docs locally:
+Browse the documentation in [English](https://openenvision.github.io/WorldFoundry/docs)
+or [中文](https://openenvision.github.io/WorldFoundry/zh/docs).
-```bash
-cd docs/fumadocs
-npm ci
-npm run dev -- --port 8014
-```
-
-Build the static docs from the repository root:
-
-```bash
-bash scripts/docs/build.sh
-```
+| Task | Guide |
+| --- | --- |
+| Choose a model or benchmark | [Models](https://openenvision.github.io/WorldFoundry/docs/guides/supported-models) · [Benchmark Hub](https://openenvision.github.io/WorldFoundry/docs/evaluation/benchmark-hub) |
+| Prepare environments and assets | [Environments](https://openenvision.github.io/WorldFoundry/docs/reference/environments) · [Local assets](https://openenvision.github.io/WorldFoundry/docs/guides/local-assets) |
+| Run inference from the terminal | [Inference](https://openenvision.github.io/WorldFoundry/docs/guides/inference) · [CLI](https://openenvision.github.io/WorldFoundry/docs/reference/cli) |
+| Use the browser workspace | [Studio](https://openenvision.github.io/WorldFoundry/docs/guides/studio) |
+| Tune inference | [Inference optimization](https://openenvision.github.io/WorldFoundry/docs/guides/inference-optimization) |
+| Score generated outputs | [Evaluation](https://openenvision.github.io/WorldFoundry/docs/evaluation) |
+| Validate changes and understand internals | [Validation](https://openenvision.github.io/WorldFoundry/docs/reference/validation) · [Architecture](https://openenvision.github.io/WorldFoundry/docs/maintainers/architecture) |
-The docs app serves English routes under `/docs` and Chinese routes under `/zh/docs`.
+## Contributing
-## Development Checks
+See [CONTRIBUTING.md](CONTRIBUTING.md) for GPU development setup, coding conventions,
+tests, DCO sign-off, and the PR workflow.
Repository [Agent Skills](skills/index.md) provide opt-in workflows for model and
benchmark integration, inference optimization, numerical validation, and maintenance.
Use these checks before opening a PR or marking a model/benchmark ready:
-```bash
-source tmp/worldfoundry_unified_env.sh
-conda activate "${WORLDFOUNDRY_UNIFIED_ENV_PREFIX}"
-
-PYTHONPATH=. python -m compileall -q worldfoundry scripts
-make lint
-make packaging-check
-make docs-check
-bash scripts/docs/build.sh --skip-bootstrap
-
-worldfoundry-eval zoo model-download --model-id --check-local --json
-worldfoundry-eval zoo benchmark-download --benchmark-id --check-local --json
-worldfoundry-eval run --plan-only --fail-on-overclaim --fail-on-stale --json
-```
-
-When adding or changing a model:
-
-1. Port required inference code into `worldfoundry`; do not depend on a cloned external repo at runtime.
-2. Keep official repositories only as provenance or parity references.
-3. Declare checkpoints, runtime variables, and environment assumptions in the model catalog/runtime profile.
-4. Run the smallest official-style demo and visually inspect the artifact.
-5. Record evidence in the docs before promoting readiness.
-
-## Repository Layout
-
-```text
-WorldFoundry
-├─ docs/fumadocs # Documentation site, teaser, screenshots, and demo media
-├─ requirements # Unified and optional dependency presets
-├─ scripts
-│ ├─ inference # User-facing inference entrypoints
-│ ├─ setup # Conda setup wrappers
-│ ├─ workspace # Studio / Workspace launch helpers
-│ └─ docs # Documentation build wrapper
-├─ worldfoundry
-│ ├─ base_models # Shared model components, perception, and 3D/4D runtimes
-│ ├─ core # Shared contracts and reusable runtime abstractions
-│ ├─ data # Model/benchmark catalogs, runtime profiles, fixtures
-│ ├─ evaluation # Runner, tasks, metrics, scorecards, reports
-│ ├─ operators # Input validation, preprocessing, interaction handling
-│ ├─ pipelines # User-facing pipeline wrappers
-│ ├─ runtime # Runtime paths, assets, jobs, and probes
-│ ├─ studio # Workspace and Studio frontends
-│ └─ synthesis # In-tree model synthesis/action-generation runtimes
-├─ thirdparty # Reviewed vendored/native dependencies
-└─ tools # Maintenance and asset utilities
-```
+Community standards and private vulnerability reporting are covered by the
+[Code of Conduct](CODE_OF_CONDUCT.md) and [Security Policy](SECURITY.md).
## Citation
-If you use WorldFoundry or its benchmark/model integrations in research, cite this repository and the upstream methods, checkpoints, datasets, and benchmarks that your run depends on. A formal paper citation will be added when the technical report is released.
+If you use WorldFoundry in research, cite this repository and the upstream methods,
+checkpoints, datasets, and benchmarks that your work depends on.
## Community Policies
@@ -449,13 +141,14 @@ Contributions follow the [Code of Conduct](CODE_OF_CONDUCT.md). Use the
## License
-WorldFoundry-authored code is licensed under the [Apache License 2.0](THIRD-PARTY-NOTICES), except where a file or component carries a different license notice. Vendored and adapted upstream components remain subject to their original licenses.
+WorldFoundry-authored code is licensed under the [Apache License 2.0](LICENSE), except where a file or component carries a different license notice. Vendored and adapted upstream components remain subject to their original licenses, collected in [THIRD-PARTY-NOTICES](THIRD-PARTY-NOTICES).
## Acknowledgment
-WorldFoundry integrates and wraps a large set of upstream world-model, video-generation, perception, reconstruction, and embodied-action projects. See the method-specific runtime profiles and the docs appendix for upstream project pointers and licenses.
+WorldFoundry builds on upstream world-model, video-generation, reconstruction, and embodied-action projects.
+See the model pages and [upstream license guide](https://openenvision.github.io/WorldFoundry/docs/reference/vendored-licenses) for attribution.
-We also thank the following open-source projects for their model, runtime, and evaluation work:
+We also thank:
- [FastVideo](https://github.com/hao-ai-lab/FastVideo) — a unified inference and post-training framework for accelerated video generation
- [OpenWorldLib](https://github.com/OpenDCAI/OpenWorldLib) — a unified codebase for advanced world models
diff --git a/docs/fumadocs/content/docs/guides/meta.json b/docs/fumadocs/content/docs/guides/meta.json
index 30b21edb3..38a5ce420 100644
--- a/docs/fumadocs/content/docs/guides/meta.json
+++ b/docs/fumadocs/content/docs/guides/meta.json
@@ -8,7 +8,6 @@
"interactive-inference",
"inference-optimization",
"diffusion-acceleration",
- "run-status",
"supported-models",
"studio",
"add-model",
diff --git a/docs/fumadocs/content/docs/guides/meta.zh.json b/docs/fumadocs/content/docs/guides/meta.zh.json
index 15c7f5ac1..4aabcbe82 100644
--- a/docs/fumadocs/content/docs/guides/meta.zh.json
+++ b/docs/fumadocs/content/docs/guides/meta.zh.json
@@ -8,7 +8,6 @@
"interactive-inference",
"inference-optimization",
"diffusion-acceleration",
- "run-status",
"supported-models",
"studio",
"add-model",
diff --git a/docs/fumadocs/content/docs/guides/run-status.mdx b/docs/fumadocs/content/docs/guides/run-status.mdx
deleted file mode 100644
index 659cb0a14..000000000
--- a/docs/fumadocs/content/docs/guides/run-status.mdx
+++ /dev/null
@@ -1,15 +0,0 @@
----
-title: Run status
-description: Reader labels for recorded route evidence. Not raw profile_resolves_* strings.
----
-
-When a model page or catalog note talks about whether a route has been run, use these labels. Do not copy raw `profile_resolves_*` or other `runtime_status` tokens from YAML into docs or tickets as if they were product badges.
-
-- **Verified** — A GPU artifact or official-demo parity record exists for that route. Copy the model-page command and expect the recorded artifact.
-- **Runner parity pending** — An in-tree pipeline or catalog variant resolves, but WorldFoundry has not recorded runner or official-demo parity yet. You can run it; treat outputs as unvalidated.
-- **Static load only** — Checkpoint structure, import, or schema checks passed. That is not a GPU run and not official-demo evidence.
-- **Planned** — Intent and upstream source only. Nothing runnable yet.
-
-Internal strings such as `profile_resolves_catalog_variant_runner_parity_pending` mean **Runner parity pending**. Catalog readiness badges on the [model hub](/docs/guides/supported-models) (Runner verified, Integrated, and the rest) are a separate computed signal; this page does not replace them.
-
-Everyday reproducible commands use `worldfoundry-eval run --pipeline.task-profile …`. See [CLI entrypoints](/docs/reference/cli#entrypoints).
diff --git a/docs/fumadocs/content/docs/guides/run-status.zh.mdx b/docs/fumadocs/content/docs/guides/run-status.zh.mdx
deleted file mode 100644
index 6f5e11d78..000000000
--- a/docs/fumadocs/content/docs/guides/run-status.zh.mdx
+++ /dev/null
@@ -1,15 +0,0 @@
----
-title: 运行状态
-description: 已记录路径证据的读者标签。不要直接使用 profile_resolves_* 字符串。
----
-
-模型页或 catalog 说明某条路径有没有跑通时,用下面这些标签。不要把 YAML 里的 `profile_resolves_*` 或其他 `runtime_status` 原样抄进文档或工单,当成产品徽章。
-
-- **Verified** — 该路径已记录 GPU 产物或官方 demo 一致性。复制模型页命令,可以预期得到已记录的 artifact。
-- **Runner parity pending** — 仓内 pipeline 或 catalog variant 能解析,但 WorldFoundry 尚未记录 runner / 官方 demo 一致性。可以跑;输出应视为未验证。
-- **Static load only** — 只通过了 checkpoint 结构、import 或 schema 检查。这不是 GPU run,也不是官方 demo 证据。
-- **Planned** — 只记录了意向和上游来源。目前没有可运行内容。
-
-例如 `profile_resolves_catalog_variant_runner_parity_pending` 应读成 **Runner parity pending**。[模型中心](/zh/docs/guides/supported-models) 上的 catalog 就绪度徽章(Runner verified、Integrated 等)是另一套计算结果;本页不替换它们。
-
-日常可复现命令用 `worldfoundry-eval run --pipeline.task-profile …`。入口对照见 [CLI 命令入口](/zh/docs/reference/cli#命令入口)。
diff --git a/docs/fumadocs/content/docs/maintainers/contributing.mdx b/docs/fumadocs/content/docs/maintainers/contributing.mdx
index a8edf31be..8867c1a44 100644
--- a/docs/fumadocs/content/docs/maintainers/contributing.mdx
+++ b/docs/fumadocs/content/docs/maintainers/contributing.mdx
@@ -174,6 +174,45 @@ Python-backed docs codegen and drift checks (`api:*`, `models:*`, `coverage:*`,
`cli:screenshots`) go through `docs/fumadocs/scripts/run-python.sh`. Override the interpreter
with `WF_DOCS_PYTHON` (then `PYTHON`, then `python3` / `python`) when needed.
+## Documentation setup and deployment
+
+The documentation app uses Next.js 16, React 19, Fumadocs, and Tailwind CSS 4.
+Use Node.js 22 (`docs/fumadocs/.nvmrc`), npm, and the unified Python environment.
+From the repository root:
+
+```bash
+npm --prefix docs/fumadocs ci
+npm --prefix docs/fumadocs run dev
+bash scripts/docs/build.sh
+npm --prefix docs/fumadocs start
+```
+
+The development and static-preview servers use `http://localhost:3000`; both
+`/docs` and `/zh/docs` are available. Add `--skip-install` to the build command
+when dependencies are already installed. The build checks types and generated
+data before exporting `docs/fumadocs/out/`.
+
+Inside `docs/fumadocs/`, `app/` owns routes, `components/` shared UI,
+`content/docs/` paired pages, `content/blog/` articles, `mdx/partials/` shared
+prose, `lib/` helpers and catalog data, `public/` assets, and `scripts/` tooling.
+`source.config.ts` configures collections; `next.config.mjs` configures static
+export and caching. `.source/`, `generated/`, `tmp/`, `.next/`, and `out/` are
+generated. Run `api:generate`, `models:generate`, `benchmarks:generate`, or
+`coverage:generate` after changing their inputs, then the matching `*:check`.
+`models:homes:check` validates model pages; `types:check` generates MDX/types
+and checks TypeScript.
+
+`.github/workflows/deploy-docs.yml` publishes the static export on matching
+`main` changes or manual dispatch. Set these values before the deployment build:
+
+| Variable | Official deployment |
+| --- | --- |
+| `NEXT_PUBLIC_BASE_PATH` | `/WorldFoundry`; empty for local development. |
+| `NEXT_PUBLIC_SITE_URL` | `https://openenvision.github.io`. |
+| `NEXT_PUBLIC_DEMO_ASSET_BASE_URL` | GitHub media CDN for `docs/fumadocs/public`. |
+
+Demo videos remain on the CDN rather than in the Pages artifact.
+
## Fast site iteration
Model demo videos are served from GitHub CDN; docs development does not need `git lfs pull`.
diff --git a/docs/fumadocs/content/docs/maintainers/contributing.zh.mdx b/docs/fumadocs/content/docs/maintainers/contributing.zh.mdx
index a41d5be23..1ed7264f7 100644
--- a/docs/fumadocs/content/docs/maintainers/contributing.zh.mdx
+++ b/docs/fumadocs/content/docs/maintainers/contributing.zh.mdx
@@ -149,6 +149,43 @@ Fumadocs 是唯一维护的文档面。新增或修改页面时,在 `docs/fuma
`cli:screenshots`)统一经 `docs/fumadocs/scripts/run-python.sh` 调用解释器。需要覆盖时,
解析顺序为 `WF_DOCS_PYTHON`、`PYTHON`、`python3`、`python`。
+## 文档启动与发布
+
+文档应用使用 Next.js 16、React 19、Fumadocs 和 Tailwind CSS 4。
+准备 Node.js 22(见 `docs/fumadocs/.nvmrc`)、npm 和统一 Python 环境。
+在仓库根目录执行:
+
+```bash
+npm --prefix docs/fumadocs ci
+npm --prefix docs/fumadocs run dev
+bash scripts/docs/build.sh
+npm --prefix docs/fumadocs start
+```
+
+开发与静态预览地址均为 `http://localhost:3000`,包含 `/docs` 和 `/zh/docs`。
+依赖已安装时可给构建命令添加 `--skip-install`。构建先检查类型与生成数据,
+再导出至 `docs/fumadocs/out/`。
+
+`docs/fumadocs/` 内,`app/` 管理路由,`components/` 管理共享 UI,
+`content/docs/` 保存双语页面,`content/blog/` 保存文章,`mdx/partials/`
+保存共享正文,`lib/` 保存工具与目录数据,`public/` 保存资源,`scripts/`
+保存工具脚本。`source.config.ts` 配置集合,`next.config.mjs` 配置静态导出与缓存。
+`.source/`、`generated/`、`tmp/`、`.next/` 和 `out/` 为生成目录。
+输入变化后运行 `api:generate`、`models:generate`、`benchmarks:generate` 或
+`coverage:generate`,再运行对应的 `*:check`。`models:homes:check` 检查模型页;
+`types:check` 生成 MDX/类型并检查 TypeScript。
+
+`.github/workflows/deploy-docs.yml` 在匹配的 `main` 变更或手动触发时发布静态站点。
+部署构建前设置:
+
+| 变量 | 官方部署值 |
+| --- | --- |
+| `NEXT_PUBLIC_BASE_PATH` | `/WorldFoundry`;本地开发留空。 |
+| `NEXT_PUBLIC_SITE_URL` | `https://openenvision.github.io`。 |
+| `NEXT_PUBLIC_DEMO_ASSET_BASE_URL` | `docs/fumadocs/public` 对应的 GitHub media CDN。 |
+
+演示视频保留在 CDN,不放入 Pages 产物。
+
## 快速站点迭代
模型演示视频由 GitHub CDN 提供,文档开发不需要执行 `git lfs pull`。
diff --git a/docs/fumadocs/content/docs/quickstart.mdx b/docs/fumadocs/content/docs/quickstart.mdx
index 2e37db2cc..f5184c327 100644
--- a/docs/fumadocs/content/docs/quickstart.mdx
+++ b/docs/fumadocs/content/docs/quickstart.mdx
@@ -15,7 +15,7 @@ This guide walks through the shortest complete path from a clone to a reviewable
Most runs follow the same shape even when the model or benchmark changes: make the Python environment importable, discover stable IDs, prepare only the required checkpoints and benchmark assets, generate artifacts, inspect them, and only then score them.
- You do not need a GPU or model weights to browse catalogs and inspect readiness. Complete environment and discovery checks, read the reported blockers, and stop before asset download if you are only evaluating coverage.
+ Run environment and catalog checks before downloading model weights. Review the reported blockers and prepare only the assets needed for your first GPU run.
## Workflow
@@ -37,10 +37,12 @@ Most runs follow the same shape even when the model or benchmark changes: make t
## Prerequisites
-- **OS:** Linux recommended for GPU inference and most benchmark runners
-- **Install track:** use `python -m pip install -e ".[tui]"` for lightweight CPU catalog/CLI/TUI work; use `bash scripts/setup/bootstrap_worldfoundry.sh` for the CUDA conda runtime. That bootstrap is the official first-clone script; it already calls `scripts/setup/unified_install.sh` to create the unified GPU env, so you do not start from `unified_install.sh` unless you are only refreshing that env. Optional extras do not select a CUDA PyTorch wheel index.
-- **Python:** 3.10+; the GPU path manages it through the WorldFoundry unified conda environment
-- **Optional:** CUDA-capable GPU, Hugging Face token for gated checkpoints
+- **OS:** Linux for the default GPU runtime and most benchmark runners
+- **GPU:** NVIDIA CUDA-capable GPU; model pages specify architecture and VRAM requirements
+- **Driver:** CUDA 12.8+ support for the unified environment
+- **Install:** `bash scripts/setup/bootstrap_worldfoundry.sh` creates the CUDA conda runtime and already calls `scripts/setup/unified_install.sh`. Optional extras do not select a CUDA PyTorch wheel index.
+- **Python:** 3.10–3.13; bootstrap manages the unified environment's interpreter
+- **Authentication:** Hugging Face token only for gated checkpoints
Catalog browsing and readiness inspection work without weights. The expensive path begins only when you choose a concrete model run and download assets.
@@ -145,7 +147,6 @@ Full cache and path conventions are in [Local assets](/docs/guides/local-assets)
Use the TUI when you do not want to remember IDs and flags. It reads the same manifests as the CLI, shows the available choices, and can print the final command before anything expensive runs.
```bash
-python -m pip install -e ".[tui]"
worldfoundry-eval tui
```
@@ -192,7 +193,7 @@ python -m worldfoundry.studio.workspace_job infer \
--device cuda
```
-The full command map is in [CLI](/docs/reference/cli). Run-status labels are in [Run status](/docs/guides/run-status).
+The full command map is in [CLI](/docs/reference/cli).
## 5. Inference
@@ -283,6 +284,5 @@ worldfoundry-eval run \
-
diff --git a/docs/fumadocs/content/docs/quickstart.zh.mdx b/docs/fumadocs/content/docs/quickstart.zh.mdx
index 9931cbb09..301850aae 100644
--- a/docs/fumadocs/content/docs/quickstart.zh.mdx
+++ b/docs/fumadocs/content/docs/quickstart.zh.mdx
@@ -15,7 +15,7 @@ description: 配置环境、准备资产、使用 TUI 或 CLI,然后运行推
换了模型或 benchmark,大多数 run 的形状仍然一样:先让 Python 环境可 import,再发现稳定 ID,只准备必要的 checkpoint 与 benchmark 资产,生成并检查 artifact,最后才对 artifact 打分。
- 浏览 catalog 和检查 readiness 不需要 GPU 或模型权重。如果你只是判断 WorldFoundry 是否覆盖目标系统,可以完成环境与 discovery 检查、阅读 blocker,然后在下载资产之前停止。
+ 下载模型权重前,先检查环境和 catalog,阅读报告中的 blocker,只准备第一次 GPU 运行需要的资产。
## 使用流程
@@ -37,10 +37,12 @@ description: 配置环境、准备资产、使用 TUI 或 CLI,然后运行推
## 前置条件
-- **操作系统:** 推荐 Linux,用于 GPU 推理和大多数 benchmark runner
-- **安装路径:** 轻量 CPU catalog/CLI/TUI 工作使用 `python -m pip install -e ".[tui]"`;CUDA conda runtime 使用 `bash scripts/setup/bootstrap_worldfoundry.sh`。这是文档用户的官方首次 clone 脚本;它已经会调用 `scripts/setup/unified_install.sh` 创建统一 GPU 环境,因此不要从 `unified_install.sh` 起步,除非你只是在刷新该环境。可选 extras 不会自动选择 CUDA PyTorch wheel index。
-- **Python:** 3.10+;GPU 路径由 WorldFoundry 统一 conda 环境管理
-- **可选:** 支持 CUDA 的 GPU、用于 gated checkpoint 的 Hugging Face token
+- **操作系统:** 默认 GPU runtime 和大多数 benchmark runner 使用 Linux
+- **GPU:** 支持 CUDA 的 NVIDIA GPU;具体架构和显存要求见模型页
+- **驱动:** 统一环境需要支持 CUDA 12.8+ 的 NVIDIA 驱动
+- **安装:** `bash scripts/setup/bootstrap_worldfoundry.sh` 创建 CUDA conda runtime,已包含对 `scripts/setup/unified_install.sh` 的调用。可选 extras 不会自动选择 CUDA PyTorch wheel index。
+- **Python:** 3.10–3.13;bootstrap 管理统一环境的解释器
+- **认证:** 仅 gated checkpoint 需要 Hugging Face token
没有权重也可以浏览 catalog 和检查 readiness。只有在你选定具体模型 run 并开始下载资产后,才会进入昂贵路径。
@@ -145,7 +147,6 @@ export HF_TOKEN=
不想记 model ID、benchmark ID 和命令参数时,用 TUI。它读取的就是 CLI 使用的同一套 manifest,会展示可选项,并且可以在真正启动昂贵任务前打印最终命令。
```bash
-python -m pip install -e ".[tui]"
worldfoundry-eval tui
```
@@ -192,7 +193,7 @@ python -m worldfoundry.studio.workspace_job infer \
--device cuda
```
-完整命令说明见 [CLI](/zh/docs/reference/cli)。状态用词见 [运行状态](/zh/docs/guides/run-status)。
+完整命令说明见 [CLI](/zh/docs/reference/cli)。
## 5. 推理
@@ -283,6 +284,5 @@ worldfoundry-eval run \
-
diff --git a/docs/fumadocs/content/docs/reference/cli.mdx b/docs/fumadocs/content/docs/reference/cli.mdx
index 00b9f2b68..7fc27d3e7 100644
--- a/docs/fumadocs/content/docs/reference/cli.mdx
+++ b/docs/fumadocs/content/docs/reference/cli.mdx
@@ -65,7 +65,7 @@ Running `worldfoundry-eval` with no arguments prints a short first-run banner. A
- **`worldfoundry-studio`** — Separate Studio launcher. See the [Studio guide](/docs/guides/studio).
- **`python -m worldfoundry.studio.workspace_job infer`** — Workspace visual smoke (the same job path the Studio UI submits). Not the documented first-run command.
-**Which command.** Everyday reproducible / model-page commands use `worldfoundry-eval run --pipeline.task-profile …`. Use `python -m worldfoundry.studio.workspace_job infer` only for Workspace visual smoke. Run-status labels are in [Run status](/docs/guides/run-status).
+**Which command.** Everyday reproducible / model-page commands use `worldfoundry-eval run --pipeline.task-profile …`. Use `python -m worldfoundry.studio.workspace_job infer` only for Workspace visual smoke.
Examples below use `worldfoundry-eval` so shell history, job scripts, and bug reports share one spelling.
diff --git a/docs/fumadocs/content/docs/reference/cli.zh.mdx b/docs/fumadocs/content/docs/reference/cli.zh.mdx
index 0d3f4993e..cad47db83 100644
--- a/docs/fumadocs/content/docs/reference/cli.zh.mdx
+++ b/docs/fumadocs/content/docs/reference/cli.zh.mdx
@@ -65,7 +65,7 @@ python -m worldfoundry zoo models --json
- **`worldfoundry-studio`** — 独立的 Studio launcher。详见 [Studio 指南](/zh/docs/guides/studio)。
- **`python -m worldfoundry.studio.workspace_job infer`** — Workspace 视觉冒烟(与 Studio UI 提交的是同一条 job 路径)。不是文档里的第一次推理命令。
-**选哪条命令。** 日常可复现 / 模型页命令用 `worldfoundry-eval run --pipeline.task-profile …`。只有 Workspace 视觉冒烟才用 `python -m worldfoundry.studio.workspace_job infer`。状态用词见 [运行状态](/zh/docs/guides/run-status)。
+**选哪条命令。** 日常可复现 / 模型页命令用 `worldfoundry-eval run --pipeline.task-profile …`。只有 Workspace 视觉冒烟才用 `python -m worldfoundry.studio.workspace_job infer`。
下面统一写 `worldfoundry-eval`,便于 shell history、job script 和问题报告保持一致。
diff --git a/docs/fumadocs/content/docs/reference/vendored-licenses.mdx b/docs/fumadocs/content/docs/reference/vendored-licenses.mdx
index 5d7730ae5..eba2d973a 100644
--- a/docs/fumadocs/content/docs/reference/vendored-licenses.mdx
+++ b/docs/fumadocs/content/docs/reference/vendored-licenses.mdx
@@ -3,10 +3,11 @@ title: Third-party notices
description: Where to find the authoritative license and provenance records for in-tree upstream code.
---
-WorldFoundry includes selected upstream inference code and optional native dependencies. Complete license texts, copyright statements, and component restrictions are collected in the root `THIRD-PARTY-NOTICES`; this page provides links to those records.
+WorldFoundry includes selected upstream inference code and optional native dependencies. Repository-level license texts, copyright statements, and component restrictions are collected in the root `THIRD-PARTY-NOTICES`. The complete BigVGAN license texts are retained in that central bundle; source comments identify their original records. This page provides links to the central records.
-- [Licenses and third-party notices](https://github.com/iChubai/WorldFoundry/blob/release/public-inference-20260909/THIRD-PARTY-NOTICES) include WorldFoundry's Apache-2.0 license, upstream terms, model notices, and the consolidated `thirdparty/` license notes. `Original-File` labels identify where each retained text came from.
-- [Upstream provenance](https://github.com/iChubai/WorldFoundry/blob/release/public-inference-20260909/thirdparty/UPSTREAM_PROVENANCE.md) records source repositories and revisions for vendored components.
+- [Project license](https://github.com/OpenEnvision/WorldFoundry/blob/main/LICENSE) contains the Apache-2.0 terms for WorldFoundry-authored code.
+- [Licenses and third-party notices](https://github.com/OpenEnvision/WorldFoundry/blob/main/THIRD-PARTY-NOTICES) include WorldFoundry's Apache-2.0 license, upstream terms, model notices, and the consolidated `thirdparty/` license notes. `Original-File` labels identify where each retained text came from.
+- [Upstream provenance](https://github.com/OpenEnvision/WorldFoundry/blob/main/thirdparty/UPSTREAM_PROVENANCE.md) records source repositories and revisions for vendored components.
The Kandinsky6 BigVGAN audio decoder retains all nine upstream license texts:
NVIDIA, HiFi-GAN, Snake, alias-free-torch, Seungwon Park, Julius, Descript,
@@ -15,4 +16,4 @@ Charactr and Amphion. Look up the `bigvgan_v2/LICENSE` and
`THIRD-PARTY-NOTICES`. Their complete texts are included in both distribution
formats; the decoder's source comments identify the applicable records.
-Read the applicable license text and retained source-file notices before redistributing or using a component. Consolidation does not change any component's license or remove distribution restrictions. Model checkpoints and datasets may have separate terms; their catalog entries and upstream release pages identify those sources. Wheels and source distributions include the central notice bundle.
+Read the applicable license text and retained source-file notices before redistributing or using a component. Consolidation does not change any component's license or remove distribution restrictions. Model checkpoints and datasets may have separate terms; their catalog entries and upstream release pages identify those sources. Wheels and source distributions include both the project license and central notice bundle.
diff --git a/docs/fumadocs/content/docs/reference/vendored-licenses.zh.mdx b/docs/fumadocs/content/docs/reference/vendored-licenses.zh.mdx
index 9060cf879..ba79c864f 100644
--- a/docs/fumadocs/content/docs/reference/vendored-licenses.zh.mdx
+++ b/docs/fumadocs/content/docs/reference/vendored-licenses.zh.mdx
@@ -3,10 +3,11 @@ title: 第三方许可与来源
description: 查找仓内上游代码的正式许可说明与来源记录。
---
-WorldFoundry 包含部分上游推理代码和可选的原生依赖。完整许可证文本、版权声明和组件使用限制统一放在根目录的 `THIRD-PARTY-NOTICES`;本页提供正式记录的入口。
+WorldFoundry 包含部分上游推理代码和可选的原生依赖。仓库级许可原文、版权声明和组件限制维护在根目录的 `THIRD-PARTY-NOTICES`。BigVGAN 的完整许可原文保留在该集中声明文件中,源码注释标明原始记录。本页提供集中记录的入口。
-- [许可证与第三方声明](https://github.com/iChubai/WorldFoundry/blob/release/public-inference-20260909/THIRD-PARTY-NOTICES)包含 WorldFoundry 自身的 Apache-2.0 许可证、上游许可原文、模型声明,以及集中后的 `thirdparty/` 许可说明。`Original-File` 标明每段保留文本的原始来源。
-- [上游来源记录](https://github.com/iChubai/WorldFoundry/blob/release/public-inference-20260909/thirdparty/UPSTREAM_PROVENANCE.md)记录仓内依赖的源码仓库与版本。
+- [项目许可证](https://github.com/OpenEnvision/WorldFoundry/blob/main/LICENSE)包含 WorldFoundry 自有代码的 Apache-2.0 条款。
+- [许可证与第三方声明](https://github.com/OpenEnvision/WorldFoundry/blob/main/THIRD-PARTY-NOTICES)包含 WorldFoundry 自身的 Apache-2.0 许可证、上游许可原文、模型声明,以及集中后的 `thirdparty/` 许可说明。`Original-File` 标明每段保留文本的原始来源。
+- [上游来源记录](https://github.com/OpenEnvision/WorldFoundry/blob/main/thirdparty/UPSTREAM_PROVENANCE.md)记录仓内依赖的源码仓库与版本。
Kandinsky6 的 BigVGAN 音频解码器完整保留九份上游许可文本:NVIDIA、HiFi-GAN、
Snake、alias-free-torch、Seungwon Park、Julius、Descript、Charactr 和 Amphion。
@@ -14,4 +15,4 @@ Snake、alias-free-torch、Seungwon Park、Julius、Descript、Charactr 和 Amph
`bigvgan_v2/incl_licenses/LICENSE_1` 至 `LICENSE_8` 对应记录。
两种发行格式均包含完整文本,解码器的源码注释标明适用记录。
-重新分发或使用组件前,请阅读适用的许可原文和源码中保留的声明。集中整理不改变组件的许可证,也不解除分发限制。模型 checkpoint 与数据集可能另有条款;可从目录条目和上游发布页查找来源。wheel 和源码发行包均包含集中后的许可文件。
+重新分发或使用组件前,请阅读适用的许可原文和源码中保留的声明。集中整理不改变组件的许可证,也不解除分发限制。模型 checkpoint 与数据集可能另有条款;可从目录条目和上游发布页查找来源。wheel 和源码发行包均包含项目许可证和集中的第三方许可文件。
diff --git a/docs/fumadocs/public/models/irasim/overview.png b/docs/fumadocs/public/models/irasim/overview.png
deleted file mode 100644
index cfe1a18c2..000000000
Binary files a/docs/fumadocs/public/models/irasim/overview.png and /dev/null differ
diff --git a/docs/fumadocs/public/models/pandora/overview.png b/docs/fumadocs/public/models/pandora/overview.png
deleted file mode 100644
index d5d5b08a8..000000000
Binary files a/docs/fumadocs/public/models/pandora/overview.png and /dev/null differ
diff --git a/docs/fumadocs/public/org-logos/SOURCES.md b/docs/fumadocs/public/org-logos/SOURCES.md
index a918af403..b84e4af5f 100644
--- a/docs/fumadocs/public/org-logos/SOURCES.md
+++ b/docs/fumadocs/public/org-logos/SOURCES.md
@@ -21,7 +21,7 @@ No file in this directory is a personal GitHub avatar.
| `benchcouncil.jpg` | BenchCouncil | GitHub organization brand avatar (github.com/BenchCouncil), pre-existing repo asset | Organization brand mark | benchmark:aigcbench |
| `berkeley.svg` | UC Berkeley | https://commons.wikimedia.org/wiki/File:Seal_of_University_of_California,_Berkeley.svg | Public domain | benchmark:bridgedata-v2, model:cut3r, model:infinite-vggt, model:k-planes, model:loger, model:octo, model:shape-of-motion |
| `buaa.png` | Beihang University | Official university brand mark (www.buaa.edu.cn), crest cropped and restored to Beihang blue #004EA2 | Organization brand mark | benchmark:robocerebra |
-| `bytedance.svg` | ByteDance | Simple Icons (https://simpleicons.org), CC0-1.0; official brand hex #3C8CFF | CC0-1.0 | model:ati-wan21-14b, model:bernini, model:bernini-r-1.3b, model:bernini-r-14b, model:depth-anything-v1, model:depth-anything-v2-prior, model:depth-anything-v3, model:depth-anything-v3-prior, model:irasim, model:roboflamingo, model:video-depth-anything-prior |
+| `bytedance.svg` | ByteDance | Simple Icons (https://simpleicons.org), CC0-1.0; official brand hex #3C8CFF | CC0-1.0 | model:ati-wan21-14b, model:bernini, model:bernini-r-1.3b, model:bernini-r-14b, model:depth-anything-v1, model:depth-anything-v2-prior, model:depth-anything-v3, model:depth-anything-v3-prior, model:roboflamingo, model:video-depth-anything-prior |
| `caltech.svg` | California Institute of Technology (Caltech) | Original simple circular-seal rendition of the Caltech seal (torch) | Public domain (simple seal rendition) | benchmark:stevo-bench |
| `cas.png` | Chinese Academy of Sciences | Official CAS seal from the UCAS brand mark (www.ucas.ac.cn), crest cropped and restored to CAS navy #004B87 | Organization brand mark | benchmark:devil-dynamics, benchmark:t2v-safety-bench, model:starwm |
| `cau.svg` | Chung-Ang University (HAI Lab) | Original simple circular-seal rendition of the CAU monogram | Public domain (simple seal rendition) | - |
@@ -120,7 +120,7 @@ No file in this directory is a personal GitHub avatar.
| `tsinghua.png` | Tsinghua University | https://commons.wikimedia.org/wiki/File:Tsinghua_University_Logo.svg | Public domain | benchmark:iworld-bench, benchmark:worldarena, benchmark:worldreasonbench, model:astra, model:causal-forcing, model:ctrl-world, model:h-rdt, model:rdt-1b, model:sama-14b, model:vid2world, model:xvla |
| `ucas.png` | University of Chinese Academy of Sciences | Official university brand mark (www.ucas.ac.cn), CAS seal cropped and restored to UCAS navy #003087 | Organization brand mark | model:consistent4d, model:scope |
| `ucla.svg` | UCLA | Original simple circular-seal rendition of the UCLA wordmark | Public domain (simple seal rendition) | benchmark:worldbench |
-| `ucsd.svg` | UC San Diego | https://commons.wikimedia.org/wiki/File:Seal_of_the_University_of_California,_San_Diego.svg | Public domain | benchmark:maniskill, benchmark:maniskill2, benchmark:videoscience-bench, model:pandora |
+| `ucsd.svg` | UC San Diego | https://commons.wikimedia.org/wiki/File:Seal_of_the_University_of_California,_San_Diego.svg | Public domain | benchmark:maniskill, benchmark:maniskill2, benchmark:videoscience-bench |
| `umass.svg` | UMass Amherst | https://commons.wikimedia.org/wiki/File:UMass_Amherst_athletics_logo.svg | Public domain (simple geometry) | model:tesseract |
| `umich.svg` | University of Michigan | https://commons.wikimedia.org/wiki/File:University_of_Michigan_logo.svg | Public domain (simple geometry) | benchmark:robomme, model:hexplane, model:mme-vla |
| `unige.svg` | University of Geneva | https://commons.wikimedia.org/wiki/File:Uni_GE_logo.svg | Public domain | model:diamond, model:iris |
diff --git a/docs/fumadocs/scripts/generate-org-logos.py b/docs/fumadocs/scripts/generate-org-logos.py
index d066124e2..62f73be65 100644
--- a/docs/fumadocs/scripts/generate-org-logos.py
+++ b/docs/fumadocs/scripts/generate-org-logos.py
@@ -35,7 +35,9 @@
import json
import re
+from collections.abc import Iterable
from pathlib import Path
+from typing import cast
DOCS_ROOT = Path(__file__).resolve().parents[1]
LOGO_DIR = DOCS_ROOT / "public" / "org-logos"
@@ -143,7 +145,8 @@ def recolor_university_seals() -> int:
raise SystemExit(f"missing university seal: {path}")
target = tuple(int(hex_color[i : i + 2], 16) for i in (0, 2, 4))
image = Image.open(path).convert("RGBA")
- pixels = list(image.getdata())
+ # Pillow's ImagingCore supports iteration without declaring the protocol in its stub.
+ pixels = list(cast(Iterable[tuple[int, int, int, int]], image.getdata()))
opaque = [px for px in pixels if px[3] > 30]
if not opaque:
continue
@@ -1243,7 +1246,6 @@ def recolor_university_seals() -> int:
"infinite-world": "meigen",
"inspatio-world": "inspatio",
"internvla-a1": "shanghai-ai-lab",
- "irasim": "bytedance",
"iris": "unige",
"joyai-echo-longvideo": "jd",
"joyai-echo-wm": "jd",
@@ -1315,7 +1317,6 @@ def recolor_university_seals() -> int:
"openpi": "physical-intelligence",
"openvla": "stanford",
"openvla-oft": "stanford",
- "pandora": "ucsd",
"pi0": "physical-intelligence",
"pi0-fast": "physical-intelligence",
"pi0-worldfoundry": "physical-intelligence",
@@ -1612,7 +1613,7 @@ def write_sources(orgs: dict[str, dict]) -> None:
lines.append("")
lines.append("Institutions without a committed logo render their abbreviation instead:")
abbr_only = [
- f"`{org_id}` ({entry['name']}, \"{entry['abbr']}\")"
+ f'`{org_id}` ({entry["name"]}, "{entry["abbr"]}")'
for org_id, entry in sorted(orgs.items())
if "src" not in entry
]
diff --git a/docs/fumadocs/scripts/harvest-model-media.py b/docs/fumadocs/scripts/harvest-model-media.py
index ad00bf232..c176a4c56 100644
--- a/docs/fumadocs/scripts/harvest-model-media.py
+++ b/docs/fumadocs/scripts/harvest-model-media.py
@@ -24,6 +24,7 @@
import urllib.request
import xml.etree.ElementTree as ET
from pathlib import Path
+from typing import TypedDict
from model_paper_figures import figure_records
@@ -295,9 +296,6 @@
"teaser": "https://arxiv.org/html/2607.04988v1/teaser.png",
"overview": "https://arxiv.org/html/2607.04988v1/Model-A1.5.png",
},
- "irasim": {
- "overview": "https://arxiv.org/html/2406.14540/x2.png",
- },
"kairos-sensenova": {
"teaser": "https://arxiv.org/html/2606.16533v3/figures/motivation_v2.png",
"overview": "https://arxiv.org/html/2606.16533v3/figures/framework_new_v1.png",
@@ -708,9 +706,6 @@
"teaser": "https://arxiv.org/html/2412.03572v2/figure_ood_v2.png",
"overview": "https://arxiv.org/html/2412.03572v2/CDiTv6.png",
},
- "pandora": {
- "overview": "https://arxiv.org/html/2406.09455v1/architecture_v2.png",
- },
"prior-depth-anything": {
"teaser": "https://arxiv.org/html/2505.10565v1/motivation.png",
"overview": "https://arxiv.org/html/2505.10565v1/model.png",
@@ -853,7 +848,20 @@ def compress_figure(src: Path, dest: Path) -> Path | None:
cwebp = shutil.which("cwebp")
webp_dest = dest.with_suffix(".webp")
if cwebp:
- cmd = [cwebp, "-quiet", "-q", "78", "-m", "6", "-resize", str(MAX_FIGURE_WIDTH), "0", str(src), "-o", str(webp_dest)]
+ cmd = [
+ cwebp,
+ "-quiet",
+ "-q",
+ "78",
+ "-m",
+ "6",
+ "-resize",
+ str(MAX_FIGURE_WIDTH),
+ "0",
+ str(src),
+ "-o",
+ str(webp_dest),
+ ]
if subprocess.run(cmd, check=False, capture_output=True).returncode == 0 and webp_dest.is_file():
if dest.exists() and dest != webp_dest:
dest.unlink()
@@ -995,7 +1003,7 @@ def fetch_arxiv(ids: list[str]) -> dict[str, dict[str, object]]:
continue
root = ET.fromstring(raw)
for entry in root.findall("a:entry", ARXIV_NS):
- entry_id = (entry.findtext("a:id", default="", namespaces=ARXIV_NS) or "")
+ entry_id = entry.findtext("a:id", default="", namespaces=ARXIV_NS) or ""
match = re.search(r"(\d{4}\.\d{4,5})", entry_id)
if not match:
continue
@@ -1041,7 +1049,14 @@ def teaser_src(figures: list[dict[str, str]]) -> str | None:
return first.get("poster") or (first.get("src") if first.get("kind") != "video" else None)
-def apply_payload(media: dict[str, dict[str, object]]) -> None:
+class _ModelMedia(TypedDict, total=False):
+ """Paper metadata and figures stored for one model homepage."""
+
+ paper: dict[str, object]
+ figures: list[dict[str, str]]
+
+
+def apply_payload(media: dict[str, _ModelMedia]) -> None:
recipes = json.loads(RECIPES.read_text(encoding="utf-8"))
for recipe in recipes["recipes"]:
extra = media.get(recipe["id"]) or {}
@@ -1079,7 +1094,8 @@ def main() -> None:
else:
media = {}
for model_id in sorted({*CURATED_FIGURES, *saved}):
- extra = media.get(model_id) if isinstance(media.get(model_id), dict) else {}
+ raw_extra = media.get(model_id)
+ extra = raw_extra if isinstance(raw_extra, dict) else {}
figures = merge_official_figures(list(extra.get("figures") or []), model_id)
extra = dict(extra)
extra["figures"] = figures
@@ -1108,11 +1124,11 @@ def main() -> None:
papers = fetch_arxiv(unique_ids)
print(f"arxiv metadata: {len(papers)}", flush=True)
- media: dict[str, dict[str, object]] = {}
+ media: dict[str, _ModelMedia] = {}
downloaded = 0
for recipe in recipes:
model_id = recipe["id"]
- entry: dict[str, object] = {}
+ entry: _ModelMedia = {}
arxiv_id = arxiv_for.get(model_id)
if arxiv_id and arxiv_id in papers:
entry["paper"] = papers[arxiv_id]
diff --git a/docs/fumadocs/scripts/model_paper_figures.py b/docs/fumadocs/scripts/model_paper_figures.py
index 04d49041b..5a684c0bc 100644
--- a/docs/fumadocs/scripts/model_paper_figures.py
+++ b/docs/fumadocs/scripts/model_paper_figures.py
@@ -620,12 +620,6 @@
"论文方法总览:InternVLA-A1-3B 的机器人操作架构。",
),
},
- "irasim": {
- "overview": (
- "Method overview: Network Architecture of IRASim . (a) shows the general diffusion transformer architecture of IRASim. The input to IRASim includes the historical frames and the given trajectory. (b) Video-level adaptation.",
- "论文方法总览:IRASim 的视频生成架构。",
- ),
- },
"kairos-sensenova": {
"teaser": (
"Official paper teaser: Motivation of Kairos. Existing world models have advanced along representational, generative, interactive, and unified world-action directions, providing useful capabilities such as abstract reasoning, high-fidelity.",
@@ -1604,12 +1598,6 @@
"论文方法总览:条件扩散 Transformer 块用 AdaLN 注入动作,并对上下文状态做交叉注意力。",
),
},
- "pandora": {
- "overview": (
- "Method overview: a pretrained LLM backbone consumes vision-encoded states and language actions, then a video generator rolls out the next world state.",
- "论文方法总览:预训练 LLM 骨干接收视觉编码状态与语言动作,再由视频生成器滚动出下一世界状态。",
- ),
- },
"prior-depth-anything": {
"teaser": (
"Official paper teaser: Prior Depth Anything fuses dense geometric estimates with sparse metric measurements.",
diff --git a/pyproject.toml b/pyproject.toml
index ce20612c7..31de5c4e1 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -429,7 +429,7 @@ all = [
[project.urls]
Homepage = "https://github.com/OpenEnvision/WorldFoundry"
-Documentation = "https://github.com/OpenEnvision/WorldFoundry"
+Documentation = "https://openenvision.github.io/WorldFoundry/docs"
Repository = "https://github.com/OpenEnvision/WorldFoundry"
Issues = "https://github.com/OpenEnvision/WorldFoundry/issues"
@@ -535,7 +535,7 @@ markers = [
[tool.ty.environment]
python-version = "3.10"
-extra-paths = ["."]
+extra-paths = [".", "docs/fumadocs/scripts"]
[tool.ty.src]
exclude = [
diff --git a/scripts/docs/build.sh b/scripts/docs/build.sh
index 4e46e42dd..6d7802950 100755
--- a/scripts/docs/build.sh
+++ b/scripts/docs/build.sh
@@ -1,17 +1,15 @@
#!/usr/bin/env bash
set -euo pipefail
-SKIP_BOOTSTRAP=0
SKIP_INSTALL=0
usage() {
cat <<'USAGE'
-Usage: bash scripts/docs/build.sh [--skip-bootstrap] [--skip-install]
+Usage: bash scripts/docs/build.sh [--skip-install]
Build the WorldFoundry Fumadocs site with type checking.
Options:
- --skip-bootstrap Reserved for CI compatibility; JavaScript dependencies are still installed.
--skip-install Do not run npm ci before checking and building.
-h, --help Show this help text.
USAGE
@@ -19,9 +17,6 @@ USAGE
while (($#)); do
case "$1" in
- --skip-bootstrap)
- SKIP_BOOTSTRAP=1
- ;;
--skip-install)
SKIP_INSTALL=1
;;
@@ -42,10 +37,6 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
DOCS_ROOT="${REPO_ROOT}/docs/fumadocs"
-if [[ "${SKIP_BOOTSTRAP}" == "0" ]]; then
- :
-fi
-
cd "${DOCS_ROOT}"
if [[ "${SKIP_INSTALL}" == "0" ]]; then
diff --git a/scripts/inference/prepare_model_infer.sh b/scripts/inference/prepare_model_infer.sh
index 8e778d6cf..5c79ebd3a 100755
--- a/scripts/inference/prepare_model_infer.sh
+++ b/scripts/inference/prepare_model_infer.sh
@@ -297,9 +297,7 @@ download_hf_with_mirror() {
verify_rolling_forcing_checkpoint() {
local checkpoint_path="$1"
local expected_size="17028919541"
- local expected_sha256="08448992460d85ef1b992dd30585d5724d098d805a48399730c8e717027a6d9d"
local actual_size
- local actual_sha256
if [[ ! -f "$checkpoint_path" ]]; then
echo "RollingForcing checkpoint is missing: ${checkpoint_path}" >&2
@@ -310,11 +308,6 @@ verify_rolling_forcing_checkpoint() {
echo "RollingForcing checkpoint size mismatch: expected ${expected_size}, got ${actual_size}" >&2
return 1
fi
- actual_sha256="$(sha256sum "$checkpoint_path" | awk '{print $1}')"
- if [[ "$actual_sha256" != "$expected_sha256" ]]; then
- echo "RollingForcing checkpoint SHA256 mismatch: expected ${expected_sha256}, got ${actual_sha256}" >&2
- return 1
- fi
}
download_rolling_forcing_assets() {
diff --git a/scripts/setup/bootstrap_worldfoundry.sh b/scripts/setup/bootstrap_worldfoundry.sh
index 21ac7b174..2e9c1b6f9 100755
--- a/scripts/setup/bootstrap_worldfoundry.sh
+++ b/scripts/setup/bootstrap_worldfoundry.sh
@@ -45,7 +45,7 @@ Common examples:
bash scripts/setup/bootstrap_worldfoundry.sh --prepare-model skyreels-v3 --download-model-assets
Options:
- --cuda TIER auto, cu128, cu124, or cu121. Default: auto.
+ --cuda TIER auto or cu128. Requires a CUDA 12.8+ NVIDIA driver.
--home PATH WorldFoundry runtime root. Default: ${XDG_CACHE_HOME:-$HOME/.cache}/worldfoundry.
--env-root PATH Conda envs root. Default: ${WORLDFOUNDRY_HOME}/conda_envs.
--data-root PATH Data root forwarded to unified_install.sh.
@@ -212,7 +212,8 @@ if [[ -z "$ENV_PREFIX" && "$INSTALL_UNIFIED" != "1" ]]; then
fi
if [[ "$VERIFY" == "1" && -n "$ENV_PREFIX" ]]; then
- conda run -p "$ENV_PREFIX" python - <<'PY'
+ if [[ "$INSTALL_UNIFIED" != "1" ]]; then
+ conda run -p "$ENV_PREFIX" python - <<'PY'
import json
import importlib
import torch
@@ -224,10 +225,11 @@ result["cuda_available"] = torch.cuda.is_available()
result["cuda_device_count"] = torch.cuda.device_count()
print(json.dumps(result, sort_keys=True))
PY
+ fi
conda run -p "$ENV_PREFIX" worldfoundry-eval zoo models --json >/dev/null
fi
-for model_id in "${MODELS[@]}"; do
+for model_id in ${MODELS[@]+"${MODELS[@]}"}; do
args=(bash "$ROOT/scripts/setup/model_env_install.sh" --model "$model_id" --cuda "$CUDA_TIER" --home "$HOME_ROOT")
[[ -n "$ENV_ROOT" ]] && args+=(--env-root "$ENV_ROOT")
[[ "$VERIFY_ONLY" == "1" ]] && args+=(--verify-only)
@@ -236,7 +238,7 @@ for model_id in "${MODELS[@]}"; do
"${args[@]}"
done
-for model_id in "${PREPARE_MODELS[@]}"; do
+for model_id in ${PREPARE_MODELS[@]+"${PREPARE_MODELS[@]}"}; do
args=(bash "$ROOT/scripts/inference/prepare_model_infer.sh" "$model_id" --skip-env)
if [[ "$DOWNLOAD_MODEL_ASSETS" == "1" ]]; then
args+=(--download)
diff --git a/scripts/setup/conda_install.sh b/scripts/setup/conda_install.sh
index 37bf6f712..97ac43b65 100755
--- a/scripts/setup/conda_install.sh
+++ b/scripts/setup/conda_install.sh
@@ -32,8 +32,8 @@ Creates or updates the open-source WorldFoundry GPU conda environment.
Options:
--env-name NAME Conda environment name. Default: worldfoundry.
--prefix PATH Conda environment prefix instead of --env-name.
- --cuda PROFILE PyTorch CUDA wheel bucket: auto, cu128, cu124, or cu121.
- Default: auto; modern CUDA 12.8 hosts resolve to cu128.
+ --cuda PROFILE auto or cu128. Default: auto.
+ The unified Torch 2.7+ stack requires CUDA 12.8+ drivers.
--environment-file PATH
Conda environment YAML. Default: environment.yml.
--preset NAME max-infer or slim. Default: max-infer.
@@ -225,12 +225,12 @@ env_selector() {
conda_run() {
local args=()
- local env_prefix=()
mapfile -t args < <(env_selector)
if [[ -n "${PIP_CONFIG_FILE:-}" ]]; then
- env_prefix=(env "PIP_CONFIG_FILE=${PIP_CONFIG_FILE}")
+ env "PIP_CONFIG_FILE=${PIP_CONFIG_FILE}" "$CONDA_EXE_PATH" run "${args[@]}" "$@"
+ else
+ "$CONDA_EXE_PATH" run "${args[@]}" "$@"
fi
- "${env_prefix[@]}" "$CONDA_EXE_PATH" run "${args[@]}" "$@"
}
ensure_matching_cuda_nvcc() {
diff --git a/scripts/setup/model_env_install.sh b/scripts/setup/model_env_install.sh
index b70c7c43d..46919c894 100755
--- a/scripts/setup/model_env_install.sh
+++ b/scripts/setup/model_env_install.sh
@@ -129,7 +129,25 @@ if ! command -v "$CONDA_EXE_PATH" >/dev/null 2>&1 && [[ "$LIST_ONLY" != "1" ]];
exit 1
fi
-CUDA_REPORT="$(PYTHONPATH="$WORLDFOUNDRY_SOURCE_ROOT" "$PYTHON_BIN" -m worldfoundry.runtime.cuda_tiers --requested "$CUDA_TIER_REQUEST" --field json)"
+CUDA_REPORT="$(PYTHONPATH="$WORLDFOUNDRY_SOURCE_ROOT" "$PYTHON_BIN" - "$CUDA_TIER_REQUEST" <<'PY'
+import json
+import sys
+
+from worldfoundry.runtime.cuda_tiers import (
+ SUPPORTED_CUDA_TIERS,
+ best_cuda_tier_for_driver,
+ detect_nvidia_driver_cuda,
+ resolve_cuda_tier,
+)
+
+requested = sys.argv[1]
+if requested not in {"auto", *SUPPORTED_CUDA_TIERS}:
+ raise SystemExit(f"Unsupported CUDA tier: {requested}; use auto, cu128, cu124, or cu121.")
+driver = detect_nvidia_driver_cuda()
+tier = best_cuda_tier_for_driver(driver) if requested == "auto" else resolve_cuda_tier(requested, driver_cuda=driver)
+print(json.dumps({"tier": tier, "driver_cuda": driver}, sort_keys=True))
+PY
+)"
CUDA_TIER="$(printf '%s' "$CUDA_REPORT" | "$PYTHON_BIN" -c 'import json, sys; print(json.load(sys.stdin)["tier"])')"
DETECTED_DRIVER_CUDA="$(printf '%s' "$CUDA_REPORT" | "$PYTHON_BIN" -c 'import json, sys; print(json.load(sys.stdin).get("driver_cuda") or "")')"
if [[ -z "$ENV_ROOT" ]]; then
@@ -191,13 +209,13 @@ import json
import sys
from worldfoundry.runtime.conda import load_runtime_conda_env_spec
-from worldfoundry.runtime.cuda_tiers import resolve_install_tier, unified_env_name
+from worldfoundry.runtime.cuda_tiers import DEFAULT_CUDA_TIER, unified_env_name
from worldfoundry.core.io.paths import conda_envs_root_path
model_id = sys.argv[1]
spec = load_runtime_conda_env_spec(model_id)
if spec is None:
- tier = resolve_install_tier()
+ tier = DEFAULT_CUDA_TIER
root = conda_envs_root_path()
print(json.dumps({
"model_id": model_id,
@@ -226,13 +244,13 @@ PY
print_mapping() {
PYTHONPATH="$WORLDFOUNDRY_SOURCE_ROOT" "$PYTHON_BIN" <<'PY'
from worldfoundry.runtime.conda import load_runtime_conda_env_specs_with_overrides
-from worldfoundry.runtime.cuda_tiers import resolve_install_tier, unified_env_name
+from worldfoundry.runtime.cuda_tiers import DEFAULT_CUDA_TIER, unified_env_name
from worldfoundry.core.io.paths import conda_envs_root_path
from worldfoundry.evaluation.models.runtime.profiles import load_runtime_profiles
specs = load_runtime_conda_env_specs_with_overrides()
profiles = load_runtime_profiles(check_conda_env_exists=False)
-tier = resolve_install_tier()
+tier = DEFAULT_CUDA_TIER
unified = unified_env_name(tier)
root = conda_envs_root_path()
rows = {}
diff --git a/scripts/setup/unified_install.sh b/scripts/setup/unified_install.sh
index 311f94168..4d3df80d6 100755
--- a/scripts/setup/unified_install.sh
+++ b/scripts/setup/unified_install.sh
@@ -28,12 +28,12 @@ Install the default unified WorldFoundry GPU environment. This is the recommende
one-command setup for local inference on modern NVIDIA hosts.
Default stack:
- CUDA tier: auto (cu128 on CUDA 12.8+ drivers, cu124 on 12.4+, cu121 on 12.1+)
+ CUDA tier: auto (cu128, requiring a CUDA 12.8+ NVIDIA driver)
install preset: max-infer
env prefix: ${WORLDFOUNDRY_HOME:-$HOME/.cache/worldfoundry}/conda_envs/worldfoundry-unified-
Options:
- --cuda TIER auto, cu128, cu124, or cu121. Default: auto.
+ --cuda TIER auto or cu128. Default: auto.
--environment-file PATH
Conda environment YAML. Default: environment.yml.
--env-name NAME Override unified env name.
@@ -257,12 +257,8 @@ if [[ "$WRITE_ENV_FILE" == "1" ]]; then
echo "WorldFoundry env exports: ${ENV_FILE}"
fi
-bash "$ROOT/scripts/setup/conda_install.sh" \
- --prefix "$ENV_PREFIX" \
- --cuda "$CUDA_TIER" \
- --environment-file "$CONDA_ENVIRONMENT_FILE" \
- --preset "$INSTALL_PRESET" \
- "${INSTALL_ARGS[@]}"
+INSTALL_ARGS+=(--prefix "$ENV_PREFIX" --cuda "$CUDA_TIER" --environment-file "$CONDA_ENVIRONMENT_FILE" --preset "$INSTALL_PRESET")
+bash "$ROOT/scripts/setup/conda_install.sh" "${INSTALL_ARGS[@]}"
install_worldfoundry_wrapper() {
local name="$1"
diff --git a/tests/core/test_docs_infra_guidance.py b/tests/core/test_docs_infra_guidance.py
index e9eddc717..b03ffaa50 100644
--- a/tests/core/test_docs_infra_guidance.py
+++ b/tests/core/test_docs_infra_guidance.py
@@ -28,16 +28,16 @@ def test_environment_and_cli_docs_cover_compile_cache_and_logging() -> None:
assert "WORLDFOUNDRY_LOG_CONTEXT" in text
-def test_install_docs_keep_cpu_gpu_and_native_boundaries_explicit() -> None:
+def test_install_docs_use_the_unified_gpu_environment() -> None:
for path in (
REPO_ROOT / "README.md",
DOCS_ROOT / "quickstart.mdx",
DOCS_ROOT / "quickstart.zh.mdx",
):
text = _text(path)
- assert 'pip install -e ".[tui]"' in text
assert "bootstrap_worldfoundry.sh" in text
- assert "CPU" in text and "GPU" in text
+ assert "GPU" in text and "CUDA 12.8" in text
+ assert 'conda activate "${WORLDFOUNDRY_UNIFIED_ENV_PREFIX}"' in text
def test_maintainer_docs_name_setup_and_contribution_gates() -> None:
diff --git a/tests/core/test_docs_toolchain.py b/tests/core/test_docs_toolchain.py
index 18e838dbe..16979906d 100644
--- a/tests/core/test_docs_toolchain.py
+++ b/tests/core/test_docs_toolchain.py
@@ -4,12 +4,14 @@
import json
import os
+import shlex
import shutil
import stat
import subprocess
from pathlib import Path
import pytest
+import yaml
REPO_ROOT = Path(__file__).resolve().parents[2]
FUMADOCS = REPO_ROOT / "docs" / "fumadocs"
@@ -94,6 +96,55 @@ def test_build_checks_all_generated_docs_data_before_next_build() -> None:
assert types_check < source.index(f"npm run {command}") < build
+@pytest.mark.unit
+def test_public_surface_builds_docs_with_installation_and_generated_data_checks(tmp_path: Path) -> None:
+ workflow = yaml.safe_load((REPO_ROOT / ".github/workflows/ci.yml").read_text())
+ build = next(
+ step["run"] for step in workflow["jobs"]["public-surface"]["steps"] if step.get("name") == "Build docs"
+ )
+ npm_log = tmp_path / "npm.log"
+ npm = tmp_path / "npm"
+ npm.write_text('#!/bin/sh\nprintf "%s\\n" "$*" >> "$WF_DOCS_TEST_NPM_LOG"\n', encoding="utf-8")
+ npm.chmod(npm.stat().st_mode | stat.S_IXUSR)
+
+ completed = subprocess.run(
+ shlex.split(build),
+ cwd=REPO_ROOT,
+ capture_output=True,
+ text=True,
+ timeout=10,
+ check=False,
+ env={**os.environ, "PATH": f"{tmp_path}{os.pathsep}{os.environ['PATH']}", "WF_DOCS_TEST_NPM_LOG": str(npm_log)},
+ )
+
+ assert completed.returncode == 0, completed.stderr
+ assert npm_log.read_text().splitlines() == [
+ "ci",
+ "run types:check",
+ "run api:check",
+ "run models:check",
+ "run models:homes:check",
+ "run benchmarks:check",
+ "run coverage:check",
+ "run build",
+ ]
+
+
+@pytest.mark.unit
+def test_public_surface_prepares_python_dependencies_and_pinned_node_before_docs() -> None:
+ workflow = yaml.safe_load((REPO_ROOT / ".github/workflows/ci.yml").read_text())
+ steps = workflow["jobs"]["public-surface"]["steps"]
+ python = next(index for index, step in enumerate(steps) if step.get("uses", "").startswith("actions/setup-python@"))
+ node = next(index for index, step in enumerate(steps) if step.get("uses", "").startswith("actions/setup-node@"))
+ install = next(index for index, step in enumerate(steps) if step.get("name") == "Install quality gate dependencies")
+ build = next(index for index, step in enumerate(steps) if step.get("name") == "Build docs")
+ assert steps[python]["with"]["python-version"] == "3.11"
+ assert steps[node]["with"]["node-version-file"] == "docs/fumadocs/.nvmrc"
+ assert python < install < build
+ assert node < build
+ assert 'python -m pip install -e . "ruff==0.12.7"' in steps[install]["run"]
+
+
def test_makefile_docs_and_bounded_shell_gates() -> None:
source = (REPO_ROOT / "Makefile").read_text(encoding="utf-8")
cli_block = source[source.index("cli-entrypoint-check:") : source.index("\nlint:")]
diff --git a/tests/eval_core/test_docs_first_run.py b/tests/eval_core/test_docs_first_run.py
index 43192e5fd..6d335ceb4 100644
--- a/tests/eval_core/test_docs_first_run.py
+++ b/tests/eval_core/test_docs_first_run.py
@@ -2,15 +2,13 @@
from pathlib import Path
+CANONICAL_MODEL_RUN = "worldfoundry-eval run "
+CANONICAL_EVALUATE = "worldfoundry-eval evaluate"
-CANONICAL_MODEL_RUN = "conda run -n worldfoundry bash scripts/inference/test_nav_video_gen.sh matrix-game-2"
-CANONICAL_EVALUATE = "conda run -n worldfoundry worldfoundry-eval evaluate"
-
-def test_user_docs_share_model_first_run_command() -> None:
+def test_quickstart_docs_share_model_first_run_command() -> None:
repo_root = Path(__file__).resolve().parents[2]
doc_paths = [
- repo_root / "README.md",
repo_root / "docs" / "fumadocs" / "content" / "docs" / "quickstart.mdx",
repo_root / "docs" / "fumadocs" / "content" / "docs" / "quickstart.zh.mdx",
]
@@ -18,15 +16,15 @@ def test_user_docs_share_model_first_run_command() -> None:
for path in doc_paths:
text = path.read_text(encoding="utf-8")
assert CANONICAL_MODEL_RUN in text, f"{path} lost the canonical model run command"
+ assert "--pipeline.task-profile " in text
assert "scorecard.json" in text, f"{path} should tell users where the first-run scorecard is"
def test_evaluation_docs_expose_materialized_output_evaluate_command() -> None:
repo_root = Path(__file__).resolve().parents[2]
doc_paths = [
- repo_root / "README.md",
- repo_root / "docs" / "fumadocs" / "content" / "docs" / "quickstart.mdx",
- repo_root / "docs" / "fumadocs" / "content" / "docs" / "quickstart.zh.mdx",
+ repo_root / "docs" / "fumadocs" / "content" / "docs" / "evaluation" / "index.mdx",
+ repo_root / "docs" / "fumadocs" / "content" / "docs" / "evaluation" / "index.zh.mdx",
repo_root / "docs" / "fumadocs" / "content" / "docs" / "reference" / "cli.mdx",
repo_root / "docs" / "fumadocs" / "content" / "docs" / "reference" / "cli.zh.mdx",
]
@@ -42,8 +40,6 @@ def test_evaluation_docs_expose_task_materialize_command() -> None:
doc_paths = [
repo_root / "docs" / "fumadocs" / "content" / "docs" / "evaluation" / "index.mdx",
repo_root / "docs" / "fumadocs" / "content" / "docs" / "evaluation" / "index.zh.mdx",
- repo_root / "docs" / "fumadocs" / "content" / "docs" / "evaluation" / "benchmarks.mdx",
- repo_root / "docs" / "fumadocs" / "content" / "docs" / "evaluation" / "benchmarks.zh.mdx",
]
for path in doc_paths:
diff --git a/tests/eval_core/test_docs_quickstart.py b/tests/eval_core/test_docs_quickstart.py
index 42946a495..4a224424b 100644
--- a/tests/eval_core/test_docs_quickstart.py
+++ b/tests/eval_core/test_docs_quickstart.py
@@ -39,14 +39,6 @@ def test_public_docs_document_model_download_and_inference_contract() -> None:
)
repo_id = model_manifest["checkpoint"]["repos"][0]["id"]
revision = model_manifest["checkpoint"]["repos"][0]["sha"]
- readme = (REPO_ROOT / "README.md").read_text(encoding="utf-8")
-
- assert "matrix-game-2" in readme
- assert repo_id in readme
- assert "worldfoundry-eval zoo model-download --model-id matrix-game-2" in readme
- assert "bash scripts/inference/prepare_model_infer.sh matrix-game-2 --download" in readme
- assert "bash scripts/inference/run_infer.sh --category navigation-video --model matrix-game-2" in readme
-
inference_paths = (
REPO_ROOT / "docs" / "fumadocs" / "content" / "docs" / "guides" / "inference.mdx",
REPO_ROOT / "docs" / "fumadocs" / "content" / "docs" / "guides" / "inference.zh.mdx",
@@ -94,9 +86,8 @@ def test_fumadocs_build_artifacts_are_not_tracked() -> None:
assert tracked == ""
-def test_public_docs_expose_all_benchmarks_run_shortcut() -> None:
+def test_cli_docs_expose_all_benchmarks_run_shortcut() -> None:
paths = (
- REPO_ROOT / "README.md",
REPO_ROOT / "docs" / "fumadocs" / "content" / "docs" / "reference" / "cli.mdx",
REPO_ROOT / "docs" / "fumadocs" / "content" / "docs" / "reference" / "cli.zh.mdx",
)
@@ -109,6 +100,63 @@ def test_public_docs_expose_all_benchmarks_run_shortcut() -> None:
assert "--plan-only" in text
+def test_readme_gpu_quickstart_launches_studio() -> None:
+ readme = (REPO_ROOT / "README.md").read_text(encoding="utf-8")
+
+ assert "CUDA 12.8" in readme
+ assert "bash scripts/setup/bootstrap_worldfoundry.sh" in readme
+ assert "source tmp/worldfoundry_unified_env.sh" in readme
+ assert 'conda activate "${WORLDFOUNDRY_UNIFIED_ENV_PREFIX}"' in readme
+ assert "bash scripts/workspace/run_workspace.sh --host 127.0.0.1 --port 7870" in readme
+ assert "http://127.0.0.1:7870/" in readme
+
+
+def test_readme_links_to_usage_and_maintainer_guides() -> None:
+ readme = (REPO_ROOT / "README.md").read_text(encoding="utf-8")
+ docs_root = REPO_ROOT / "docs/fumadocs/content/docs"
+ guides = (
+ "quickstart",
+ "guides/supported-models",
+ "guides/local-assets",
+ "guides/inference",
+ "guides/inference-optimization",
+ "guides/studio",
+ "evaluation",
+ "evaluation/benchmark-hub",
+ "reference/cli",
+ "reference/environments",
+ "reference/validation",
+ "reference/vendored-licenses",
+ "maintainers/architecture",
+ )
+
+ for guide in guides:
+ assert f"https://openenvision.github.io/WorldFoundry/docs/{guide})" in readme
+ for suffix in (".mdx", ".zh.mdx"):
+ assert (docs_root / f"{guide}{suffix}").is_file() or (docs_root / guide / f"index{suffix}").is_file(), guide
+
+ for target in ("CONTRIBUTING.md", "skills/index.md", "CODE_OF_CONDUCT.md", "SECURITY.md"):
+ assert f"]({target})" in readme
+ assert (REPO_ROOT / target).is_file()
+
+
+def test_readme_keeps_news_and_community_qr_codes() -> None:
+ readme = (REPO_ROOT / "README.md").read_text(encoding="utf-8")
+
+ assert (
+ readme.index("![WorldFoundry teaser]")
+ < readme.index("## 📰 News")
+ < readme.index("## 🤝 Community")
+ < readme.index("## Highlights")
+ )
+ assert "https://join.slack.com/t/worldfoundrycommunity/" in readme
+ assert "https://discord.gg/ybUQMDA4x" in readme
+ for filename in ("wechat_qr.png", "wechat_qr_2.png", "wechat_qr_3.png"):
+ image = f"docs/fumadocs/public/{filename}"
+ assert f'src="{image}"' in readme
+ assert (REPO_ROOT / image).is_file()
+
+
def test_readme_does_not_advertise_retired_gpu_validation_commands() -> None:
readme = (REPO_ROOT / "README.md").read_text(encoding="utf-8")
diff --git a/tests/eval_core/test_versioning.py b/tests/eval_core/test_versioning.py
index d9620c81a..b95cb1680 100644
--- a/tests/eval_core/test_versioning.py
+++ b/tests/eval_core/test_versioning.py
@@ -5,12 +5,9 @@
import subprocess
from pathlib import Path
-from worldfoundry.evaluation.api import GenerationRequest
from tests.eval_core.contract_fixture import CONTRACT_FIXTURE_MODEL_ID, CONTRACT_FIXTURE_RUNNER_TARGET
from worldfoundry.evaluation.utils import (
- RUN_FINGERPRINT_SCHEMA_VERSION,
VERSION_CONTEXT_SCHEMA_VERSION,
- build_run_fingerprint,
build_version_context,
git_metadata,
stable_hash,
@@ -26,8 +23,7 @@ def test_stable_hash_is_order_independent_for_mappings() -> None:
assert stable_hash(left) == stable_hash(right)
-def test_run_fingerprint_excludes_run_id_and_time_varying_fields() -> None:
- request = GenerationRequest(sample_id="sample-a", task_name="unit")
+def test_version_context_records_runner_and_evaluation_metadata() -> None:
context = build_version_context(
runner="unit-runner",
benchmark={"benchmark_name": "unit"},
@@ -36,13 +32,12 @@ def test_run_fingerprint_excludes_run_id_and_time_varying_fields() -> None:
extra={"profile": "cpu"},
)
- first = build_run_fingerprint(version_context=context, requests=[request])
- second = build_run_fingerprint(version_context=context, requests=[request])
-
assert context["schema_version"] == VERSION_CONTEXT_SCHEMA_VERSION
- assert first["schema_version"] == RUN_FINGERPRINT_SCHEMA_VERSION
- assert first["hash"] == second["hash"]
- assert first["version_context_hash"] == stable_hash(context)
+ assert context["runner"] == "unit-runner"
+ assert context["benchmark"] == {"benchmark_name": "unit"}
+ assert context["model"] == {"model_name": "fake"}
+ assert context["dataset"] == {"sample_count": 1}
+ assert context["extra"] == {"profile": "cpu"}
def test_git_metadata_does_not_scan_untracked_files(monkeypatch) -> None:
@@ -133,7 +128,7 @@ def test_version_context_does_not_include_python_executable(monkeypatch) -> None
assert context["python"] == {"version": versioning.platform.python_version()}
-def test_eval_runner_writes_version_context_and_fingerprint(tmp_path: Path) -> None:
+def test_eval_runner_writes_version_context(tmp_path: Path) -> None:
output_dir = tmp_path / "run"
from worldfoundry.evaluation.runner import EvaluateRunRequest, execute_evaluate_run
@@ -154,7 +149,6 @@ def test_eval_runner_writes_version_context_and_fingerprint(tmp_path: Path) -> N
scorecard = json.loads((output_dir / "scorecard.json").read_text(encoding="utf-8"))
assert manifest["version_context"]["schema_version"] == VERSION_CONTEXT_SCHEMA_VERSION
- assert manifest["run_fingerprint"]["schema_version"] == RUN_FINGERPRINT_SCHEMA_VERSION
- assert plan["run_fingerprint"]["hash"] == manifest["run_fingerprint"]["hash"]
- assert scorecard["run"]["run_fingerprint"]["hash"] == manifest["run_fingerprint"]["hash"]
+ assert plan["version_context"] == manifest["version_context"]
+ assert scorecard["run"]["version_context"] == manifest["version_context"]
assert scorecard["run"]["version_context"]["contract_versions"]["generation_request"]
diff --git a/tests/scripts/test_run_video_model_matrix.py b/tests/scripts/test_run_video_model_matrix.py
deleted file mode 100644
index af133932e..000000000
--- a/tests/scripts/test_run_video_model_matrix.py
+++ /dev/null
@@ -1,996 +0,0 @@
-from __future__ import annotations
-
-import hashlib
-import importlib.util
-import json
-import sys
-from pathlib import Path
-from types import SimpleNamespace
-
-REPO_ROOT = Path(__file__).resolve().parents[2]
-SCRIPT_PATH = REPO_ROOT / "scripts" / "workspace" / "run_video_model_matrix.py"
-SPEC = importlib.util.spec_from_file_location("worldfoundry_run_video_model_matrix", SCRIPT_PATH)
-assert SPEC is not None and SPEC.loader is not None
-run_video_model_matrix = importlib.util.module_from_spec(SPEC)
-sys.modules[SPEC.name] = run_video_model_matrix
-SPEC.loader.exec_module(run_video_model_matrix)
-
-
-def _model(load_kwargs: dict[str, object]) -> dict[str, object]:
- return {
- "default_variant_id": "default",
- "variants": [
- {
- "variant_id": "default",
- "model_ref": "",
- "checkpoints": [],
- "load_kwargs": load_kwargs,
- }
- ],
- }
-
-
-def test_readiness_uses_model_refs_declared_in_load_kwargs(tmp_path: Path) -> None:
- model_path = tmp_path / "gamma"
- encoder_path = tmp_path / "reason"
- model_path.mkdir()
- encoder_path.mkdir()
-
- readiness = run_video_model_matrix._checkpoint_readiness(
- _model(
- {
- "mode": "causal_few_step",
- "model_path": str(model_path),
- "text_encoder_path": str(encoder_path),
- "output_path": str(tmp_path / "not-created.mp4"),
- }
- ),
- tmp_path,
- )
-
- assert readiness["ready"] is True
- assert readiness["required_refs"] == [str(model_path), str(encoder_path)]
- assert readiness["missing_refs"] == []
-
-
-def test_readiness_reuses_resolution_and_structure_scans_within_one_audit(
- tmp_path: Path, monkeypatch
-) -> None:
- checkpoint = tmp_path / "shared-checkpoint"
- checkpoint.mkdir()
- calls = {"resolve": 0, "structure": 0}
- original_resolve = run_video_model_matrix._resolve_ref
-
- def counted_resolve(raw_ref: str, checkpoint_root: Path) -> str:
- calls["resolve"] += 1
- return original_resolve(raw_ref, checkpoint_root)
-
- def counted_structure(resolved_ref: str, checkpoint_root: Path) -> str:
- calls["structure"] += 1
- assert resolved_ref == str(checkpoint.resolve())
- assert checkpoint_root == tmp_path
- return ""
-
- monkeypatch.setattr(run_video_model_matrix, "_resolve_ref", counted_resolve)
- monkeypatch.setattr(
- run_video_model_matrix,
- "_checkpoint_artifact_structure_error",
- counted_structure,
- )
- resolution_cache: dict[str, str] = {}
- structure_cache: dict[str, str] = {}
-
- for _ in range(2):
- readiness = run_video_model_matrix._checkpoint_readiness(
- _model({"model_path": str(checkpoint)}),
- tmp_path,
- resolution_cache=resolution_cache,
- structure_cache=structure_cache,
- )
- assert readiness["ready"] is True
-
- assert calls == {"resolve": 1, "structure": 1}
-
-
-def test_readiness_requires_every_declared_model_component(tmp_path: Path) -> None:
- checkpoint = tmp_path / "model.safetensors"
- checkpoint.touch()
- missing_base_model = tmp_path / "base-model"
-
- readiness = run_video_model_matrix._checkpoint_readiness(
- _model(
- {
- "required_components": {
- "checkpoint_path": str(checkpoint),
- "base_model_root": str(missing_base_model),
- "runtime_root": str(tmp_path),
- }
- }
- ),
- tmp_path,
- )
-
- assert readiness["ready"] is False
- assert readiness["missing_refs"] == [str(missing_base_model)]
-
-
-def test_readiness_treats_flux_path_as_a_required_model_component(tmp_path: Path) -> None:
- missing_flux = tmp_path / "black-forest-labs--FLUX.1-Fill-dev"
-
- readiness = run_video_model_matrix._checkpoint_readiness(
- _model({"flux_path": str(missing_flux)}),
- tmp_path,
- )
-
- assert readiness["ready"] is False
- assert readiness["required_refs"] == [str(missing_flux)]
- assert readiness["missing_refs"] == [str(missing_flux)]
-
-
-def test_readiness_accepts_complete_flux_diffusers_snapshot_with_optional_export_marker(
- tmp_path: Path,
-) -> None:
- flux = tmp_path / "black-forest-labs--FLUX.1-Fill-dev"
- for relative in (
- "model_index.json",
- "scheduler/scheduler_config.json",
- "text_encoder/config.json",
- "text_encoder_2/config.json",
- "tokenizer/tokenizer_config.json",
- "tokenizer_2/tokenizer_config.json",
- "transformer/config.json",
- "vae/config.json",
- ):
- path = flux / relative
- path.parent.mkdir(parents=True, exist_ok=True)
- path.write_text("{}", encoding="utf-8")
- optional_export = flux / "flux1-fill-dev.safetensors"
- optional_export.touch()
- Path(f"{optional_export}.aria2").write_bytes(b"in-progress")
-
- readiness = run_video_model_matrix._checkpoint_readiness(
- _model({"flux_path": str(flux)}),
- tmp_path,
- )
-
- assert readiness["ready"] is True
- assert readiness["component_errors"] == []
-
-
-def test_readiness_rejects_flux_snapshot_missing_directory_component(tmp_path: Path) -> None:
- flux = tmp_path / "black-forest-labs--FLUX.1-Fill-dev"
- flux.mkdir()
- (flux / "model_index.json").write_text("{}", encoding="utf-8")
- optional_export = flux / "flux1-fill-dev.safetensors"
- optional_export.touch()
- Path(f"{optional_export}.aria2").write_bytes(b"in-progress")
-
- readiness = run_video_model_matrix._checkpoint_readiness(
- _model({"flux_path": str(flux)}),
- tmp_path,
- )
-
- assert readiness["ready"] is False
- assert readiness["reason"] == "required checkpoint component is structurally incomplete"
- assert "scheduler/scheduler_config.json" in readiness["component_errors"][0]
-
-
-def test_readiness_rejects_model_specific_checkpoint_architecture_errors(
- tmp_path: Path,
- monkeypatch,
-) -> None:
- checkpoint = tmp_path / "epoch-0.safetensors"
- checkpoint.touch()
- model = _model({})
- model["id"] = "echo-memory-spatial"
- model["variants"][0]["model_ref"] = str(checkpoint)
- monkeypatch.setattr(
- run_video_model_matrix,
- "_model_checkpoint_structure_error",
- lambda model_id, resolved_ref: (
- "spatial recipe requires spatial_memory_module weights"
- if model_id == "echo-memory-spatial" and resolved_ref == str(checkpoint)
- else ""
- ),
- )
-
- readiness = run_video_model_matrix._checkpoint_readiness(model, tmp_path)
-
- assert readiness["ready"] is False
- assert readiness["reason"] == "required checkpoint component is structurally incomplete"
- assert readiness["missing_refs"] == [str(checkpoint)]
- assert "spatial_memory_module" in readiness["component_errors"][0]
-
-
-def test_model_checkpoint_inspection_exception_becomes_a_checkpoint_error(
- tmp_path: Path,
- monkeypatch,
-) -> None:
- from worldfoundry.base_models.diffusion_model.models.denoisers import (
- echo_memory_checkpoint,
- )
-
- class CorruptHeaderError(Exception):
- pass
-
- checkpoint = tmp_path / "epoch-0.safetensors"
- checkpoint.touch()
-
- def fail_inspection(*_args, **_kwargs) -> None:
- raise CorruptHeaderError("incomplete metadata, file not fully covered")
-
- monkeypatch.setattr(
- echo_memory_checkpoint,
- "inspect_echo_checkpoint",
- fail_inspection,
- )
-
- error = run_video_model_matrix._model_checkpoint_structure_error(
- "echo-memory-context-k20",
- str(checkpoint),
- )
-
- assert "checkpoint architecture is incompatible" in error
- assert "incomplete metadata" in error
-
-
-def test_readiness_does_not_treat_runtime_model_id_as_checkpoint(tmp_path: Path) -> None:
- checkpoint = tmp_path / "checkpoint.pt"
- checkpoint.touch()
-
- readiness = run_video_model_matrix._checkpoint_readiness(
- _model(
- {
- "model_id": "rolling-forcing",
- "checkpoint_path": str(checkpoint),
- }
- ),
- tmp_path,
- )
-
- assert readiness["ready"] is True
- assert readiness["required_refs"] == [str(checkpoint)]
-
-
-def test_readiness_audits_native_dit_and_codec_overrides(tmp_path: Path) -> None:
- dit = tmp_path / "dit"
- codec = tmp_path / "codec"
- dit.mkdir()
- codec.mkdir()
-
- readiness = run_video_model_matrix._checkpoint_readiness(
- _model(
- {
- "checkpoint_overrides": {
- "dit": str(dit),
- "codec": str(codec),
- }
- }
- ),
- tmp_path,
- )
-
- assert readiness["ready"] is True
- assert readiness["required_refs"] == [str(dit), str(codec)]
-
-
-def test_readiness_replaces_symbolic_model_id_checkpoint_with_model_ref(tmp_path: Path) -> None:
- checkpoint = tmp_path / "gen3c"
- checkpoint.mkdir()
- model = _model({})
- model["id"] = "gen3c"
- model["model_ref"] = str(checkpoint)
- model["variants"][0]["checkpoints"] = [
- {"role": "primary", "uri": "gen3c", "required": True}
- ]
-
- readiness = run_video_model_matrix._checkpoint_readiness(model, tmp_path)
-
- assert readiness["ready"] is True
- assert readiness["required_refs"] == [str(checkpoint)]
- assert readiness["resolved_model_ref"] == str(checkpoint)
-
-
-def test_relative_declared_reference_is_resolved_from_working_directory(
- tmp_path: Path, monkeypatch
-) -> None:
- checkpoint = tmp_path / "weights" / "model.pt"
- checkpoint.parent.mkdir()
- checkpoint.touch()
- monkeypatch.chdir(tmp_path)
-
- readiness = run_video_model_matrix._checkpoint_readiness(
- _model({"checkpoint_path": "weights/model.pt"}),
- tmp_path / "checkpoints",
- )
-
- assert readiness["ready"] is True
- assert readiness["resolved_refs"] == [str(checkpoint.resolve())]
-
-
-def test_absolute_legacy_hfd_reference_preserves_nested_component_path(tmp_path: Path) -> None:
- checkpoint_root = tmp_path / "checkpoints"
- checkpoint = checkpoint_root / "publisher--model" / "dit" / "model.pth"
- checkpoint.parent.mkdir(parents=True)
- checkpoint.write_bytes(b"checkpoint")
- legacy_ref = tmp_path / "legacy" / "ckpt" / "hfd" / "publisher--model" / "dit" / "model.pth"
-
- readiness = run_video_model_matrix._checkpoint_readiness(
- _model({"checkpoint_path": str(legacy_ref)}),
- checkpoint_root,
- )
-
- assert readiness["ready"] is True
- assert readiness["resolved_refs"] == [str(checkpoint.resolve())]
-
-
-def test_readiness_rejects_structurally_incomplete_gemma_root(tmp_path: Path) -> None:
- checkpoint = tmp_path / "model.safetensors"
- checkpoint.touch()
- upsampler = tmp_path / "upsampler.safetensors"
- upsampler.touch()
- gemma_root = tmp_path / "gemma"
- gemma_root.mkdir()
-
- readiness = run_video_model_matrix._checkpoint_readiness(
- _model(
- {
- "required_components": {
- "checkpoint_path": str(checkpoint),
- "spatial_upsampler_path": str(upsampler),
- "gemma_root": str(gemma_root),
- }
- }
- ),
- tmp_path,
- )
-
- assert readiness["ready"] is False
- assert readiness["reason"] == "required checkpoint component is structurally incomplete"
- assert readiness["missing_refs"] == [str(gemma_root)]
- assert "model-*.safetensors" in readiness["component_errors"][0]
- assert "tokenizer.model" in readiness["component_errors"][0]
-
- (gemma_root / "model-00001-of-00001.safetensors").touch()
- (gemma_root / "tokenizer.model").touch()
- readiness = run_video_model_matrix._checkpoint_readiness(
- _model(
- {
- "required_components": {
- "checkpoint_path": str(checkpoint),
- "spatial_upsampler_path": str(upsampler),
- "gemma_root": str(gemma_root),
- }
- }
- ),
- tmp_path,
- )
-
- assert readiness["ready"] is True
- assert readiness["component_errors"] == []
-
-
-def test_readiness_audits_explicit_runtime_and_python_paths(tmp_path: Path) -> None:
- source = tmp_path / "source"
- source.mkdir()
- python = tmp_path / "env" / "bin" / "python"
- python.parent.mkdir(parents=True)
- python.touch()
-
- readiness = run_video_model_matrix._checkpoint_readiness(
- _model(
- {
- "source_root": str(source),
- "python_executable": str(python),
- }
- ),
- tmp_path,
- )
-
- assert readiness["ready"] is True
- assert readiness["required_refs"] == [str(source), str(python)]
-
-
-def test_readiness_requires_materialized_hyworld_scene_layout(tmp_path: Path) -> None:
- scene = tmp_path / "scene"
- scene.mkdir()
- readiness = run_video_model_matrix._checkpoint_readiness(
- _model({"scene_path": str(scene)}),
- tmp_path,
- )
-
- assert readiness["ready"] is False
- assert readiness["reason"] == "required checkpoint component is structurally incomplete"
- assert "render_results/global_pcd.ply" in readiness["component_errors"][0]
-
- point_cloud = scene / "render_results" / "global_pcd.ply"
- point_cloud.parent.mkdir()
- point_cloud.touch()
- readiness = run_video_model_matrix._checkpoint_readiness(
- _model({"scene_path": str(scene)}),
- tmp_path,
- )
- assert readiness["ready"] is True
-
-
-def test_readiness_rejects_explicit_sparse_checkpoint_placeholder(tmp_path: Path) -> None:
- checkpoint = tmp_path / "model.safetensors"
- with checkpoint.open("wb") as handle:
- handle.seek(2 * 1024 * 1024 - 1)
- handle.write(b"\0")
-
- readiness = run_video_model_matrix._checkpoint_readiness(
- _model({"checkpoint_path": str(checkpoint)}),
- tmp_path,
- )
-
- assert readiness["ready"] is False
- assert readiness["reason"] == "required checkpoint component is structurally incomplete"
- assert "sparse" in readiness["component_errors"][0]
-
-
-def test_readiness_accepts_readable_checkpoint_when_filesystem_reports_zero_blocks(
- tmp_path: Path, monkeypatch
-) -> None:
- checkpoint = tmp_path / "model.safetensors"
- checkpoint.write_bytes(b"materialized-checkpoint" + b"\1" * (2 * 1024 * 1024))
- original_stat = Path.stat
-
- def stat_with_zero_blocks(path: Path, *args, **kwargs):
- result = original_stat(path, *args, **kwargs)
- if path == checkpoint:
- return SimpleNamespace(
- st_mode=result.st_mode,
- st_size=result.st_size,
- st_blocks=0,
- )
- return result
-
- monkeypatch.setattr(Path, "stat", stat_with_zero_blocks)
-
- readiness = run_video_model_matrix._checkpoint_readiness(
- _model({"checkpoint_path": str(checkpoint)}),
- tmp_path,
- )
-
- assert readiness["ready"] is True
- assert readiness["component_errors"] == []
-
-
-def test_readiness_rejects_sparse_shard_named_by_checkpoint_index(tmp_path: Path) -> None:
- checkpoint = tmp_path / "indexed-model"
- checkpoint.mkdir()
- shard = checkpoint / "model-00001-of-00001.safetensors"
- with shard.open("wb") as handle:
- handle.seek(2 * 1024 * 1024 - 1)
- handle.write(b"\0")
- (checkpoint / "model.safetensors.index.json").write_text(
- '{"weight_map": {"layer.weight": "model-00001-of-00001.safetensors"}}',
- encoding="utf-8",
- )
-
- readiness = run_video_model_matrix._checkpoint_readiness(
- _model({"model_path": str(checkpoint)}),
- tmp_path,
- )
-
- assert readiness["ready"] is False
- assert str(shard) in readiness["component_errors"][0]
-
-
-def test_readiness_rejects_aria2_control_file_for_checkpoint(tmp_path: Path) -> None:
- checkpoint = tmp_path / "model.pt"
- checkpoint.write_bytes(b"checkpoint")
- Path(f"{checkpoint}.aria2").write_bytes(b"in-progress")
-
- readiness = run_video_model_matrix._checkpoint_readiness(
- _model({"checkpoint_path": str(checkpoint)}),
- tmp_path,
- )
-
- assert readiness["ready"] is False
- assert ".aria2 exists" in readiness["component_errors"][0]
-
-
-def test_readiness_rejects_aria2_control_file_for_dreamdojo_distcp(tmp_path: Path) -> None:
- checkpoint = tmp_path / "model" / "__0_0.distcp"
- checkpoint.parent.mkdir()
- checkpoint.write_bytes(b"checkpoint" * (128 * 1024))
- Path(f"{checkpoint}.aria2").write_bytes(b"in-progress")
-
- readiness = run_video_model_matrix._checkpoint_readiness(
- _model({"checkpoint_shards": [str(checkpoint)]}),
- tmp_path,
- )
-
- assert readiness["ready"] is False
- assert ".aria2 exists" in readiness["component_errors"][0]
-
-
-def test_dreamdojo_input_blocker_requires_lerobot_statistics(tmp_path: Path) -> None:
- dataset = tmp_path / "GR1_robot"
- model = _model({"dataset_path": str(dataset)})
- model["id"] = "dreamdojo"
- readiness = {"ready": True}
-
- blocker = run_video_model_matrix._input_blocker(model, readiness)
- assert "meta/stats.json" in blocker
-
- stats = dataset / "meta" / "stats.json"
- stats.parent.mkdir(parents=True)
- stats.write_text("{}", encoding="utf-8")
- assert run_video_model_matrix._input_blocker(model, readiness) == ""
-
-
-def test_readiness_ignores_unindexed_optional_sparse_export(tmp_path: Path) -> None:
- checkpoint = tmp_path / "indexed-model"
- checkpoint.mkdir()
- required = checkpoint / "model-00001-of-00001.safetensors"
- required.write_bytes(b"required")
- optional = checkpoint / "optional-export.safetensors"
- with optional.open("wb") as handle:
- handle.seek(2 * 1024 * 1024 - 1)
- handle.write(b"\0")
- (checkpoint / "model.safetensors.index.json").write_text(
- '{"weight_map": {"layer.weight": "model-00001-of-00001.safetensors"}}',
- encoding="utf-8",
- )
-
- readiness = run_video_model_matrix._checkpoint_readiness(
- _model({"model_path": str(checkpoint)}),
- tmp_path,
- )
-
- assert readiness["ready"] is True
-
-
-def test_readiness_rejects_unindexed_sparse_numbered_shard(tmp_path: Path) -> None:
- checkpoint = tmp_path / "model"
- component = checkpoint / "text_encoder"
- component.mkdir(parents=True)
- (component / "model-00001-of-00002.safetensors").write_bytes(b"first")
- second = component / "model-00002-of-00002.safetensors"
- with second.open("wb") as handle:
- handle.seek(2 * 1024 * 1024 - 1)
- handle.write(b"\0")
-
- readiness = run_video_model_matrix._checkpoint_readiness(
- _model({"model_path": str(checkpoint)}),
- tmp_path,
- )
-
- assert readiness["ready"] is False
- assert str(second) in readiness["component_errors"][0]
-
-
-def test_resolved_checkpoint_invalidates_previous_checkpoint_blocker() -> None:
- assert run_video_model_matrix._can_reuse_previous_row(
- {"status": "blocked_checkpoint", "blocker": "missing yesterday"},
- {"ready": True, "reason": ""},
- retry_this_model=False,
- ) is False
-
-
-def test_unresolved_checkpoint_preserves_previous_checkpoint_blocker() -> None:
- assert run_video_model_matrix._can_reuse_previous_row(
- {"status": "blocked_checkpoint", "blocker": "missing yesterday"},
- {"ready": False, "reason": "still missing"},
- retry_this_model=False,
- ) is True
-
-
-def test_current_checkpoint_reason_replaces_stale_reused_blocker(tmp_path: Path) -> None:
- model = _model({"checkpoint_path": str(tmp_path / "missing.pt")})
- readiness = run_video_model_matrix._checkpoint_readiness(model, tmp_path)
- row = {
- "status": "blocked_checkpoint",
- "blocker": "default variant declares no checkpoint or model_ref",
- }
- run_video_model_matrix._refresh_checkpoint_blocker(row, readiness)
-
- assert row["blocker"] == "required checkpoint path is not locally resolvable"
-
-
-def test_retry_never_reuses_previous_terminal_row() -> None:
- assert run_video_model_matrix._can_reuse_previous_row(
- {"status": "failed"},
- {"ready": True, "reason": ""},
- retry_this_model=True,
- ) is False
-
-
-def test_submission_retry_row_is_not_reused_after_runner_restart() -> None:
- assert run_video_model_matrix._can_reuse_previous_row(
- {"status": "submission_retry"},
- {"ready": True, "reason": ""},
- retry_this_model=False,
- ) is False
-
-
-def test_submission_failure_requeues_until_finite_retry_budget() -> None:
- model = {"id": "temporary-workspace-outage"}
- row: dict[str, object] = {}
- queue: list[dict[str, object]] = []
-
- retrying = run_video_model_matrix._record_submission_failure(
- queue=queue,
- model=model,
- row=row,
- gpu=2,
- attempt=1,
- max_attempts=3,
- exc=ConnectionError("Workspace is restarting"),
- )
-
- assert retrying is True
- assert queue == [model]
- assert row["status"] == "submission_retry"
- assert row["submission_attempts"] == 1
-
- queue.clear()
- retrying = run_video_model_matrix._record_submission_failure(
- queue=queue,
- model=model,
- row=row,
- gpu=2,
- attempt=3,
- max_attempts=3,
- exc=ConnectionError("Workspace is still unavailable"),
- )
-
- assert retrying is False
- assert queue == []
- assert row["status"] == "submission_failed"
- assert row["submission_attempts"] == 3
-
-
-def test_video_validation_records_content_hash(tmp_path: Path, monkeypatch) -> None:
- video = tmp_path / "demo.mp4"
- video.write_bytes(b"deterministic-video")
- calls = 0
-
- def fake_run(*args, **kwargs):
- nonlocal calls
- calls += 1
- if calls == 1:
- return SimpleNamespace(returncode=0, stdout='{"streams": [{"width": 16, "height": 16}]}', stderr="")
- return SimpleNamespace(returncode=0, stdout="", stderr="")
-
- monkeypatch.setattr(run_video_model_matrix, "_find_executable", lambda name: name)
- monkeypatch.setattr(run_video_model_matrix.subprocess, "run", fake_run)
-
- result = run_video_model_matrix._validate_video(video)
-
- assert result["size_bytes"] == len(b"deterministic-video")
- assert result["sha256"] == hashlib.sha256(b"deterministic-video").hexdigest()
- assert result["full_decode_ok"] is True
-
-
-def test_completed_job_runs_strict_temporal_validation(tmp_path: Path, monkeypatch) -> None:
- model_id = "strict-model"
- video = tmp_path / "demo.mp4"
- video.write_bytes(b"strict-video-content")
- manifest = tmp_path / "manifest.json"
- manifest.write_text(
- json.dumps(
- {
- "model_id": model_id,
- "status": "succeeded",
- "preview_video": str(video),
- "artifacts": [str(video)],
- }
- ),
- encoding="utf-8",
- )
-
- def fake_run(command, **kwargs):
- output_path = Path(command[command.index("--output") + 1])
- output_path.write_text(
- json.dumps(
- {
- "manifest": str(manifest),
- "path": str(video),
- "ok": True,
- "sha256": hashlib.sha256(video.read_bytes()).hexdigest(),
- "decoded_frames": 17,
- "width": 64,
- "height": 48,
- "fps": 8.0,
- "size_bytes": video.stat().st_size,
- "temporal_change": True,
- }
- )
- + "\n",
- encoding="utf-8",
- )
- return SimpleNamespace(returncode=0, stdout="", stderr="")
-
- monkeypatch.setattr(run_video_model_matrix.subprocess, "run", fake_run)
-
- validation = run_video_model_matrix._strictly_validate_completed_job(
- {"result": {"manifest_path": str(manifest)}},
- output_dir=tmp_path,
- model_id=model_id,
- )
-
- assert validation["valid"] is True
- assert validation["videos"][0]["temporal_change"] is True
- assert validation["videos"][0]["full_decode_ok"] is True
-
-
-def test_gpu_idle_gate_rejects_memory_utilization_and_compute_processes() -> None:
- idle = {0: {"memory_mib": 7, "utilization_percent": 0, "compute_pids": []}}
- assert run_video_model_matrix._gpu_is_idle(
- idle,
- 0,
- memory_limit_mib=32,
- utilization_limit_percent=0,
- ) is True
-
- for state in (
- {"memory_mib": 33, "utilization_percent": 0, "compute_pids": []},
- {"memory_mib": 7, "utilization_percent": 1, "compute_pids": []},
- {"memory_mib": 7, "utilization_percent": 0, "compute_pids": [123]},
- ):
- assert run_video_model_matrix._gpu_is_idle(
- {0: state},
- 0,
- memory_limit_mib=32,
- utilization_limit_percent=0,
- ) is False
-
-
-def test_gpu_idle_gate_can_ignore_only_explicitly_trusted_compute_processes() -> None:
- activity = {
- 0: {"memory_mib": 3901, "utilization_percent": 0, "compute_pids": [42064]},
- }
-
- assert run_video_model_matrix._gpu_is_idle(
- activity,
- 0,
- memory_limit_mib=5000,
- utilization_limit_percent=0,
- ignored_compute_pids={42064},
- ) is True
- assert run_video_model_matrix._gpu_is_idle(
- {0: {**activity[0], "compute_pids": [42064, 12345]}},
- 0,
- memory_limit_mib=5000,
- utilization_limit_percent=0,
- ignored_compute_pids={42064},
- ) is False
-
-
-def test_partial_gpu_scheduling_is_the_safe_shared_cluster_default() -> None:
- args = run_video_model_matrix.build_parser().parse_args(
- ["--checkpoint-root", "/checkpoints", "--output-dir", "/results"]
- )
-
- assert args.require_all_gpus_idle_before_start is False
- assert args.gpu_idle_ignored_compute_pids is None
-
-
-def test_multi_gpu_models_are_deferred_to_exclusive_gang_phase() -> None:
- assert "4-GPU gang phase" in run_video_model_matrix._multi_gpu_gang_blocker(
- "lingbot-world-v2"
- )
- assert "4-GPU gang phase" in run_video_model_matrix._multi_gpu_gang_blocker(
- "wan2.1-vace"
- )
- assert run_video_model_matrix._multi_gpu_gang_blocker("cosmos-predict2.5") == ""
-
-
-def test_job_elapsed_seconds_uses_persisted_timestamps() -> None:
- assert run_video_model_matrix._job_elapsed_seconds(
- {
- "started_at": "2026-08-30T12:00:00+00:00",
- "finished_at": "2026-08-30T12:01:02.500000+00:00",
- }
- ) == 62.5
-
-
-def _write_strict_evidence(
- root: Path,
- *,
- model_id: str,
- report_name: str = "strict_video_validation_batch.jsonl",
-) -> tuple[Path, Path, Path]:
- run_dir = root / f"20260830-120000-000000-{model_id}"
- run_dir.mkdir(parents=True)
- video = run_dir / f"{model_id}.mp4"
- video.write_bytes(b"strictly-decoded-video")
- manifest = run_dir / "manifest.json"
- manifest.write_text(
- json.dumps(
- {
- "model_id": model_id,
- "status": "succeeded",
- "preview_video": str(video),
- "artifacts": [str(video)],
- }
- ),
- encoding="utf-8",
- )
- strict_report = root / report_name
- strict_report.write_text(
- json.dumps(
- {
- "manifest": str(manifest),
- "path": str(video),
- "ok": True,
- "sha256": hashlib.sha256(video.read_bytes()).hexdigest(),
- "decoded_frames": 81,
- "width": 832,
- "height": 480,
- "fps": 16.0,
- "size_bytes": video.stat().st_size,
- "temporal_change": True,
- }
- )
- + "\n",
- encoding="utf-8",
- )
- return manifest, video, strict_report
-
-
-def test_persistent_strict_validation_recovers_evicted_workspace_job(tmp_path: Path) -> None:
- manifest, video, strict_report = _write_strict_evidence(
- tmp_path,
- model_id="evicted-video-model",
- )
-
- evidence = run_video_model_matrix._discover_persistent_evidence([tmp_path])
-
- row = evidence["evicted-video-model"]
- assert row["status"] == "completed"
- assert row["validation"]["valid"] is True
- assert row["validation"]["manifest_path"] == str(manifest)
- assert row["validation"]["videos"][0]["path"] == str(video)
- assert row["validation"]["videos"][0]["full_decode_ok"] is True
- assert row["persistent_evidence"]["source"] == str(strict_report)
-
-
-def test_persistent_validation_uses_manifest_identity_not_directory_name(tmp_path: Path) -> None:
- _write_strict_evidence(tmp_path, model_id="manifest-model")
-
- evidence = run_video_model_matrix._discover_persistent_evidence([tmp_path])
-
- assert set(evidence) == {"manifest-model"}
-
-
-def test_invalid_persistent_validation_is_not_completion_evidence(tmp_path: Path) -> None:
- _, video, strict_report = _write_strict_evidence(tmp_path, model_id="broken-model")
- video.unlink()
-
- evidence = run_video_model_matrix._discover_persistent_evidence([tmp_path])
-
- assert "broken-model" not in evidence
- assert strict_report.is_file()
-
-
-def test_persistent_validation_rejects_changed_video_content(tmp_path: Path) -> None:
- _, video, _ = _write_strict_evidence(tmp_path, model_id="mutated-model")
- video.write_bytes(b"mutated-after-validation")
-
- evidence = run_video_model_matrix._discover_persistent_evidence([tmp_path])
-
- assert "mutated-model" not in evidence
-
-
-def test_persistent_validation_requires_temporal_change(tmp_path: Path) -> None:
- _, _, strict_report = _write_strict_evidence(tmp_path, model_id="static-model")
- record = json.loads(strict_report.read_text(encoding="utf-8"))
- record["temporal_change"] = False
- strict_report.write_text(json.dumps(record) + "\n", encoding="utf-8")
-
- evidence = run_video_model_matrix._discover_persistent_evidence([tmp_path])
-
- assert "static-model" not in evidence
-
-
-def test_strict_evidence_hash_cache_avoids_duplicate_file_reads(
- tmp_path: Path,
- monkeypatch,
-) -> None:
- _, _, strict_report = _write_strict_evidence(tmp_path, model_id="cached-model")
- original_sha256_file = run_video_model_matrix._sha256_file
- calls = 0
-
- def counted_sha256_file(path: Path) -> str:
- nonlocal calls
- calls += 1
- return original_sha256_file(path)
-
- monkeypatch.setattr(run_video_model_matrix, "_sha256_file", counted_sha256_file)
- hash_cache: dict[tuple[str, int, int], str] = {}
-
- first = run_video_model_matrix._load_strict_validation_file(
- strict_report,
- hash_cache=hash_cache,
- )
- second = run_video_model_matrix._load_strict_validation_file(
- strict_report,
- hash_cache=hash_cache,
- )
-
- assert first and second
- assert calls == 1
-
-
-def test_persistent_evidence_filter_skips_hashing_unselected_models(
- tmp_path: Path,
- monkeypatch,
-) -> None:
- _write_strict_evidence(tmp_path, model_id="unselected-model")
- calls = 0
-
- def counted_sha256_file(path: Path) -> str:
- nonlocal calls
- calls += 1
- return hashlib.sha256(path.read_bytes()).hexdigest()
-
- monkeypatch.setattr(run_video_model_matrix, "_sha256_file", counted_sha256_file)
-
- evidence = run_video_model_matrix._discover_persistent_evidence(
- [tmp_path],
- model_ids={"selected-model"},
- )
-
- assert evidence == {}
- assert calls == 0
-
-
-def test_gang_report_supplies_four_gpu_metrics_and_overrides_plain_evidence(
- tmp_path: Path,
-) -> None:
- manifest, video, strict_report = _write_strict_evidence(
- tmp_path,
- model_id="four-gpu-model",
- )
- strict_record = json.loads(strict_report.read_text(encoding="utf-8"))
- gang_dir = tmp_path / "gang"
- gang_dir.mkdir()
- gang_report = gang_dir / "gang.json"
- gang_report.write_text(
- json.dumps(
- {
- "gpus": [0, 1, 2, 3],
- "models": [
- {
- "model_id": "four-gpu-model",
- "status": "completed",
- "job_id": "studio-00099",
- "elapsed_seconds_observed": 123.5,
- "peak_memory_mib": 40960,
- "peak_memory_mib_by_gpu": {
- "0": 40000,
- "1": 40960,
- "2": 40100,
- "3": 40200,
- },
- "strict_validation": [strict_record],
- "job": {
- "id": "studio-00099",
- "model_id": "four-gpu-model",
- "status": "completed",
- "result": {
- "manifest_path": str(manifest),
- "preview_video": str(video),
- },
- },
- }
- ],
- }
- ),
- encoding="utf-8",
- )
-
- row = run_video_model_matrix._discover_persistent_evidence([tmp_path])[
- "four-gpu-model"
- ]
-
- assert row["gpu"] == "0,1,2,3"
- assert row["gpus"] == [0, 1, 2, 3]
- assert row["peak_memory_mib"] == 40960
- assert row["elapsed_seconds"] == 123.5
- assert row["persistent_evidence"]["source"] == str(gang_report)
diff --git a/tests/scripts/test_validate_generated_videos.py b/tests/scripts/test_validate_generated_videos.py
deleted file mode 100644
index 4fc946ad4..000000000
--- a/tests/scripts/test_validate_generated_videos.py
+++ /dev/null
@@ -1,35 +0,0 @@
-from __future__ import annotations
-
-import importlib.util
-import sys
-from pathlib import Path
-
-import pytest
-
-
-REPO_ROOT = Path(__file__).resolve().parents[2]
-SCRIPT_PATH = REPO_ROOT / "scripts" / "workspace" / "validate_generated_videos.py"
-SPEC = importlib.util.spec_from_file_location("worldfoundry_validate_generated_videos", SCRIPT_PATH)
-assert SPEC is not None and SPEC.loader is not None
-validate_generated_videos = importlib.util.module_from_spec(SPEC)
-sys.modules[SPEC.name] = validate_generated_videos
-SPEC.loader.exec_module(validate_generated_videos)
-
-
-def test_duration_uses_ffprobe_value() -> None:
- assert validate_generated_videos._duration_seconds(
- {"duration": "2.75"}, decoded_frames=12, fps=4.0
- ) == pytest.approx(2.75)
-
-
-@pytest.mark.parametrize("raw_duration", [None, "N/A", "nan", "-1"])
-def test_duration_falls_back_to_decoded_frames_and_fps(raw_duration: str | None) -> None:
- assert validate_generated_videos._duration_seconds(
- {"duration": raw_duration}, decoded_frames=12, fps=4.0
- ) == pytest.approx(3.0)
-
-
-def test_duration_reports_zero_without_usable_timing() -> None:
- assert validate_generated_videos._duration_seconds(
- {"duration": "N/A"}, decoded_frames=12, fps=0.0
- ) == 0.0