---
name: provider-adapter-development
description: "Use for WorldForge provider work: adding adapters, changing capability declarations, promoting scaffolds, debugging provider failures, updating provider catalog docs, or touching LeWorldModel, GR00T, LeRobot, Cosmos-Policy, JEPA, Genie, or JEPA-WMS. Ensures capabilities remain truthful and optional runtimes stay host-owned."
---

# Provider Adapter Development

## Non-Negotiables

- Valid capabilities are `predict`, `embed`, `plan`, `score`, and `policy`.
- `ProviderCapabilities()` is fail-closed. Advertise only callable, tested operations.
- `plan` is a WorldForge facade workflow. Do not benchmark or advertise it as a provider operation unless a real provider-owned planner exists.
- Optional runtimes, checkpoints, datasets, CUDA, robot packages, credentials, and robot controllers stay out of base dependencies and repo artifacts.
- Provider events are a log boundary. Never emit bearer tokens, API keys, signed URL query strings, or secret-like metadata.
- Treat upstream marketing names as untrusted. Capability labels come from observed callable behavior
  and contract tests, not from model family branding.

## Capability Map

| Provider | Truthful surface | Registration |
| --- | --- | --- |
| `mock` | `predict`, `embed` | always |
| `cosmos-policy` | `policy` | `COSMOS_POLICY_BASE_URL` |
| `leworldmodel` | `score` | `LEWORLDMODEL_POLICY` or `LEWM_POLICY` |
| `gr00t` | `policy` | `GROOT_POLICY_HOST` |
| `lerobot` | `policy` | `LEROBOT_POLICY_PATH` or `LEROBOT_POLICY` |
| `jepa` | `score` | `JEPA_MODEL_NAME` |
| `genie` | scaffold only | env-gated reservation |
| `jepa-wms` | direct-construction score candidate | not exported or auto-registered |

## Workflow

1. Read the closest existing adapter, then `src/worldforge/providers/base.py`, `src/worldforge/providers/catalog.py`, and `docs/src/provider-authoring-guide.md`.
2. Classify the upstream runtime by what it actually does, not by model marketing language.
3. For a new scaffold, start with `uv run python scripts/scaffold_provider.py ...`; keep capabilities unadvertised until real methods return validated WorldForge models.
4. Validate public inputs before network calls, filesystem reads, or optional runtime calls.
5. Return the correct public model: `PredictionPayload`, `EmbeddingResult`, `ActionScoreResult`, or `ActionPolicyResult`.
6. Add success and malformed/error fixtures under `tests/fixtures/providers/`.
7. Add `worldforge.testing.assert_provider_contract()` coverage for every advertised capability.
8. Update `.env.example`, provider docs, generated catalog surfaces, README, changelog, `AGENTS.md`, or `CLAUDE.md` only when public behavior or env vars change.
9. Validate with focused provider tests, ruff, generated provider-doc check, and the coverage/package gates when the public surface changes.

## Definition Of Done

- Every advertised capability has a provider-contract test and at least one malformed/provider-error test.
- Provider metadata, docs, generated catalog output, and `.env.example` agree on capabilities and configuration.
- Events and public errors redact credentials, signed URLs, host-local secrets, and unsafe metadata.
- Optional-runtime paths degrade to typed skipped/preflight results without installing host-owned packages.

## Sharp Edges

| Symptom | Cause | Fix |
| --- | --- | --- |
| Provider appears in docs with wrong surface | `ProviderCapabilities` declaration drifted | Fix adapter capabilities, run provider docs generator, update tests |
| Optional provider missing from `doctor` | Required env var absent | Confirm variable name from `.env.example`; do not read `.env` |
| Contract helper fails on JSON | Metadata/raw payload not JSON-native | Validate at construction and convert tuples/objects before return |
| Remote test leaks URL/query | Event target/message metadata not sanitized | Add regression in `tests/test_observability.py` or provider test |
